From fb8cbfc8648b76b7bf3750aef76ec2eb356419da Mon Sep 17 00:00:00 2001 From: Nadja Reitzenstein Date: Mon, 18 Oct 2021 10:39:31 +0200 Subject: [PATCH] Working new State encoding --- Cargo.lock | 735 +-------------------------------------------- Cargo.toml | 32 +- src/db/mod.rs | 128 -------- src/db/state.rs | 2 +- src/lib.rs | 61 ++-- src/oid.rs | 705 ++++++++++++++++++++++--------------------- src/state/mod.rs | 136 ++++++--- src/state/value.rs | 358 ++++++++++++---------- src/varint.rs | 155 ++++++++++ 9 files changed, 879 insertions(+), 1433 deletions(-) create mode 100644 src/varint.rs diff --git a/Cargo.lock b/Cargo.lock index 2420627..b4ef77b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,15 +34,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "aho-corasick" -version = "0.7.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" -dependencies = [ - "memchr", -] - [[package]] name = "annotate-snippets" version = "0.9.0" @@ -52,21 +43,6 @@ dependencies = [ "unicode-width", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi", -] - -[[package]] -name = "arrayref" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" - [[package]] name = "arrayvec" version = "0.5.2" @@ -156,7 +132,7 @@ checksum = "b21b63ab5a0db0369deb913540af2892750e42d949faacc7a61495ac418a1692" dependencies = [ "async-io", "blocking", - "cfg-if 1.0.0", + "cfg-if", "event-listener", "futures-lite", "libc", @@ -188,29 +164,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "065374052e7df7ee4047b1160cca5e1467a12351a40b3da123c870ba0b8eda2a" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi", - "libc", - "winapi", -] - [[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" -[[package]] -name = "base64" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" - [[package]] name = "bincode" version = "2.0.0-dev" @@ -220,47 +179,12 @@ dependencies = [ "serde", ] -[[package]] -name = "bindgen" -version = "0.55.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b13ce559e6433d360c26305643803cb52cfbabbc2b9c47ce04a58493dfb443" -dependencies = [ - "bitflags", - "cexpr", - "cfg-if 0.1.10", - "clang-sys", - "clap", - "env_logger", - "lazy_static", - "lazycell", - "log", - "peeking_take_while", - "proc-macro2", - "quote", - "regex", - "rustc-hash", - "shlex", - "which", -] - [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -[[package]] -name = "blake2b_simd" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq", -] - [[package]] name = "block-buffer" version = "0.7.3" @@ -386,75 +310,12 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" -[[package]] -name = "cexpr" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4aedb84272dbe89af497cf81375129abda4fc0a9e7c5d317498c15cc30c0d27" -dependencies = [ - "nom", -] - -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "chrono" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" -dependencies = [ - "libc", - "num-integer", - "num-traits", - "time", - "winapi", -] - -[[package]] -name = "clang-sys" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cf2cc85830eae84823884db23c5306442a6c3d5bfd3beb2f2a2c829faa1816" -dependencies = [ - "glob", - "libc", - "libloading", -] - -[[package]] -name = "clap" -version = "2.33.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" -dependencies = [ - "ansi_term", - "atty", - "bitflags", - "strsim", - "textwrap", - "unicode-width", - "vec_map", -] - -[[package]] -name = "cmake" -version = "0.1.45" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb6210b637171dfba4cda12e579ac6dc73f5165ad56133e5d72ef3131f320855" -dependencies = [ - "cc", -] - [[package]] name = "concurrent-queue" version = "1.2.2" @@ -464,12 +325,6 @@ dependencies = [ "cache-padded", ] -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "cpufeatures" version = "0.2.1" @@ -479,26 +334,6 @@ dependencies = [ "libc", ] -[[package]] -name = "crossbeam-channel" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" -dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" -dependencies = [ - "cfg-if 1.0.0", - "lazy_static", -] - [[package]] name = "ctor" version = "0.1.21" @@ -509,17 +344,6 @@ dependencies = [ "syn", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "dhall" version = "0.10.1" @@ -559,42 +383,30 @@ dependencies = [ name = "diflouroborane" version = "0.3.0" dependencies = [ - "async-channel", "async-trait", "bincode", "capnp", "capnp-futures", "capnp-rpc", "capnpc", - "clap", - "easy-parallel", - "flexbuffers", + "erased-serde", "futures 0.3.16", "futures-signals", "futures-test", - "futures-util", - "genawaiter", + "inventory", "lazy_static", "libc", "lmdb-rkv", - "paho-mqtt", "ptr_meta", - "rand", "rkyv", "rkyv_dyn", "rkyv_typename", - "rsasl", - "rust-argon2", "serde", "serde_dhall", "serde_json", "signal-hook", - "slog", - "slog-async", - "slog-term", "smol", "tempfile", - "toml", "tracing", "uuid", "walkdir", @@ -618,27 +430,6 @@ dependencies = [ "generic-array 0.14.4", ] -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if 1.0.0", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "discard" version = "1.0.4" @@ -651,12 +442,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" -[[package]] -name = "easy-parallel" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd4afd79212583ff429b913ad6605242ed7eec277e950b1438f300748f948f4" - [[package]] name = "either" version = "1.6.1" @@ -673,16 +458,12 @@ dependencies = [ ] [[package]] -name = "env_logger" -version = "0.7.1" +name = "erased-serde" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +checksum = "3de9ad4541d99dc22b59134e7ff8dc3d6c988c89ecd7324bf10a8362b07a2afa" dependencies = [ - "atty", - "humantime", - "log", - "regex", - "termcolor", + "serde", ] [[package]] @@ -706,19 +487,6 @@ dependencies = [ "instant", ] -[[package]] -name = "flexbuffers" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d14128f06405808ce75bfebe11e9b0f9da18719ede6d7bdb1702d6bfe0f7e8" -dependencies = [ - "bitflags", - "byteorder", - "num_enum", - "serde", - "serde_derive", -] - [[package]] name = "form_urlencoded" version = "1.0.1" @@ -760,28 +528,12 @@ dependencies = [ "futures-sink", ] -[[package]] -name = "futures-channel-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e5f4df964fa9c1c2f8bddeb5c3611631cacd93baf810fc8bb2fb4b495c263a" -dependencies = [ - "futures-core-preview", - "futures-sink-preview", -] - [[package]] name = "futures-core" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" -[[package]] -name = "futures-core-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b35b6263fb1ef523c3056565fa67b1d16f0a8604ff12b11b08c25f28a734c60a" - [[package]] name = "futures-executor" version = "0.3.16" @@ -794,29 +546,12 @@ dependencies = [ "num_cpus", ] -[[package]] -name = "futures-executor-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75236e88bd9fe88e5e8bfcd175b665d0528fe03ca4c5207fabc028c8f9d93e98" -dependencies = [ - "futures-core-preview", - "futures-util-preview", - "num_cpus", -] - [[package]] name = "futures-io" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" -[[package]] -name = "futures-io-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4914ae450db1921a56c91bde97a27846287d062087d4a652efc09bb3a01ebda" - [[package]] name = "futures-lite" version = "1.12.0" @@ -845,20 +580,6 @@ dependencies = [ "syn", ] -[[package]] -name = "futures-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b1dce2a0267ada5c6ff75a8ba864b4e679a9e2aa44262af7a3b5516d530d76e" -dependencies = [ - "futures-channel-preview", - "futures-core-preview", - "futures-executor-preview", - "futures-io-preview", - "futures-sink-preview", - "futures-util-preview", -] - [[package]] name = "futures-signals" version = "0.3.22" @@ -879,12 +600,6 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" -[[package]] -name = "futures-sink-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f148ef6b69f75bb610d4f9a2336d4fc88c4b5b67129d1a340dd0fd362efeec" - [[package]] name = "futures-task" version = "0.3.16" @@ -908,16 +623,6 @@ dependencies = [ "pin-utils", ] -[[package]] -name = "futures-timer" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f9eb554aa23143abc64ec4d0016f038caf53bb7cbc3d91490835c54edc96550" -dependencies = [ - "futures-preview", - "pin-utils", -] - [[package]] name = "futures-util" version = "0.3.16" @@ -940,51 +645,6 @@ dependencies = [ "slab", ] -[[package]] -name = "futures-util-preview" -version = "0.3.0-alpha.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce968633c17e5f97936bd2797b6e38fb56cf16a7422319f7ec2e30d3c470e8d" -dependencies = [ - "futures-channel-preview", - "futures-core-preview", - "futures-io-preview", - "futures-sink-preview", - "memchr", - "pin-utils", - "slab", -] - -[[package]] -name = "genawaiter" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" -dependencies = [ - "genawaiter-macro", - "genawaiter-proc-macro", - "proc-macro-hack", -] - -[[package]] -name = "genawaiter-macro" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" - -[[package]] -name = "genawaiter-proc-macro" -version = "0.99.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784f84eebc366e15251c4a8c3acee82a6a6f427949776ecb88377362a9621738" -dependencies = [ - "proc-macro-error", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "generic-array" version = "0.12.4" @@ -1010,7 +670,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "wasi", ] @@ -1026,21 +686,6 @@ dependencies = [ "syn", ] -[[package]] -name = "glob" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" - -[[package]] -name = "gsasl-sys" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89192b27c2356690cddc81ef17438cede69f0e6794a645debe579de3a6bb835" -dependencies = [ - "bindgen", -] - [[package]] name = "half" version = "1.7.1" @@ -1071,15 +716,6 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -[[package]] -name = "humantime" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] - [[package]] name = "idna" version = "0.2.3" @@ -1107,7 +743,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1153,12 +789,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "lexical-core" version = "0.7.6" @@ -1167,7 +797,7 @@ checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" dependencies = [ "arrayvec", "bitflags", - "cfg-if 1.0.0", + "cfg-if", "ryu", "static_assertions", ] @@ -1178,16 +808,6 @@ version = "0.2.101" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21" -[[package]] -name = "libloading" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a" -dependencies = [ - "cfg-if 1.0.0", - "winapi", -] - [[package]] name = "lmdb-rkv" version = "0.14.0" @@ -1217,7 +837,7 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1249,25 +869,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "num-integer" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" -dependencies = [ - "autocfg", - "num-traits", -] - -[[package]] -name = "num-traits" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" -dependencies = [ - "autocfg", -] - [[package]] name = "num_cpus" version = "1.13.0" @@ -1278,28 +879,6 @@ dependencies = [ "libc", ] -[[package]] -name = "num_enum" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9bd055fb730c4f8f4f57d45d35cd6b3f0980535b056dc7ff119cee6a66ed6f" -dependencies = [ - "derivative", - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "486ea01961c4a818096de679a8b740b26d9033146ac5291b1c98557658f8cdd9" -dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "once_cell" version = "1.8.0" @@ -1318,40 +897,12 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" -[[package]] -name = "paho-mqtt" -version = "0.8.0" -source = "git+https://github.com/dequbed/paho.mqtt.rust.git?branch=master#14ec804ecf284564ee71b04345d1fdf1f75571df" -dependencies = [ - "futures 0.3.16", - "futures-timer", - "libc", - "log", - "paho-mqtt-sys", - "thiserror", -] - -[[package]] -name = "paho-mqtt-sys" -version = "0.4.1" -source = "git+https://github.com/dequbed/paho.mqtt.rust.git?branch=master#14ec804ecf284564ee71b04345d1fdf1f75571df" -dependencies = [ - "bindgen", - "cmake", -] - [[package]] name = "parking" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "427c3892f9e783d91cc128285287e70a59e206ca452770ece88a76f7a3eddd72" -[[package]] -name = "peeking_take_while" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" - [[package]] name = "percent-encoding" version = "2.1.0" @@ -1467,7 +1018,7 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92341d779fa34ea8437ef4d82d440d5e1ce3f3ff7f824aa64424cd481f9a1f25" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "log", "wepoll-ffi", @@ -1489,42 +1040,6 @@ dependencies = [ "typed-arena", ] -[[package]] -name = "proc-macro-crate" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ebace6889caf889b4d3f76becee12e90353f2b8c7d875534a71e5742f8f6f83" -dependencies = [ - "thiserror", - "toml", -] - -[[package]] -name = "proc-macro-error" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "syn-mid", - "version_check", -] - [[package]] name = "proc-macro-hack" version = "0.5.19" @@ -1566,12 +1081,6 @@ dependencies = [ "syn", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quote" version = "1.0.9" @@ -1630,33 +1139,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "redox_users" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" -dependencies = [ - "getrandom", - "redox_syscall", -] - -[[package]] -name = "regex" -version = "1.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" - [[package]] name = "remove_dir_all" version = "0.5.3" @@ -1745,41 +1227,6 @@ dependencies = [ "syn", ] -[[package]] -name = "rsasl" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165e25c96193ef9f5eeb7e68e868c5543b30d6a68bef5470be45ae2416466817" -dependencies = [ - "discard", - "gsasl-sys", - "libc", -] - -[[package]] -name = "rust-argon2" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" -dependencies = [ - "base64", - "blake2b_simd", - "constant_time_eq", - "crossbeam-utils", -] - -[[package]] -name = "rustc-hash" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" - -[[package]] -name = "rustversion" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61b3909d758bb75c79f23d4736fac9433868679d3ad2ea7a61e3c25cfda9a088" - [[package]] name = "ryu" version = "1.0.5" @@ -1874,18 +1321,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9204c41a1597a8c5af23c82d1c921cb01ec0a4c59e07a9c7306062829a3903f3" dependencies = [ "block-buffer 0.9.0", - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest 0.9.0", "opaque-debug 0.3.0", ] -[[package]] -name = "shlex" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" - [[package]] name = "signal-hook" version = "0.3.9" @@ -1911,37 +1352,6 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" -[[package]] -name = "slog" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" - -[[package]] -name = "slog-async" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "766c59b252e62a34651412870ff55d8c4e6d04df19b43eecb2703e417b097ffe" -dependencies = [ - "crossbeam-channel", - "slog", - "take_mut", - "thread_local", -] - -[[package]] -name = "slog-term" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95c1e7e5aab61ced6006149ea772770b84a0d16ce0f7885def313e4829946d76" -dependencies = [ - "atty", - "chrono", - "slog", - "term", - "thread_local", -] - [[package]] name = "smol" version = "1.2.5" @@ -1982,12 +1392,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - [[package]] name = "syn" version = "1.0.75" @@ -1999,30 +1403,13 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "syn-mid" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baa8e7560a164edb1621a55d18a0c59abf49d360f47aa7b821061dd7eea7fac9" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "take_mut" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" - [[package]] name = "tempfile" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "rand", "redox_syscall", @@ -2030,74 +1417,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "termcolor" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" -dependencies = [ - "winapi-util", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "thiserror" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "283d5230e63df9608ac7d9691adc1dfb6e701225436eb64d0b9a7f0a5a04f6ec" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa3884228611f5cd3608e2d409bf7dce832e4eb3135e3f11addbd7e41bd68e71" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "thread_local" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" -dependencies = [ - "once_cell", -] - -[[package]] -name = "time" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "tinyvec" version = "1.3.1" @@ -2113,22 +1432,13 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" -[[package]] -name = "toml" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" -dependencies = [ - "serde", -] - [[package]] name = "tracing" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2221,12 +1531,6 @@ dependencies = [ "serde", ] -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.3" @@ -2265,15 +1569,6 @@ dependencies = [ "cc", ] -[[package]] -name = "which" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d011071ae14a2f6671d0b74080ae0cd8ebf3a6f8c9589a2cd45f23126fe29724" -dependencies = [ - "libc", -] - [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 04ad4de..b11e449 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ lmdb = [] [dependencies] futures = { version = "0.3.16", features = ["thread-pool", "compat"] } -futures-util = "0.3.16" +#futures-util = "0.3.16" futures-signals = "0.3.22" smol = "1.2.5" @@ -26,9 +26,9 @@ tracing = "0.1.28" signal-hook = "0.3.9" -slog = { version = "2.7.0", features = ["max_level_trace"] } -slog-term = "2.8.0" -slog-async = "2.7.0" +#slog = { version = "2.7.0", features = ["max_level_trace"] } +#slog-term = "2.8.0" +#slog-async = "2.7.0" capnp = "0.14.3" capnpc = "0.14.4" @@ -36,28 +36,29 @@ capnp-rpc = "0.14.1" capnp-futures = "0.14.1" serde = { version = "1.0.130", features = ["derive"] } -toml = "0.5.8" -flexbuffers = "2.0.0" -bincode = "2.0.0-dev" +erased-serde = "0.3" +#toml = "0.5.8" +#flexbuffers = "2.0.0" rkyv = "0.7" ptr_meta = "0.1" rkyv_typename = "0.7" rkyv_dyn = "0.7" +inventory = "0.1" serde_dhall = { version = "0.10.1", default-features = false } serde_json = "1.0" uuid = { version = "0.8.2", features = ["serde", "v4"] } -clap = "2.33.3" +#clap = "2.33.3" # TODO update this if bindgen breaks (again) -rsasl = "1.4.0" +#rsasl = "1.4.0" #rsasl = { path = "../../rsasl" } # rumqtt needs tokio which I'm trying to get away from -paho-mqtt = { git = "https://github.com/dequbed/paho.mqtt.rust.git", branch = "master", features = ["build_bindgen"] } +#paho-mqtt = { git = "https://github.com/dequbed/paho.mqtt.rust.git", branch = "master", features = ["build_bindgen"] } #mlua = { version = "0.4", features = ["async", "luajit"] } @@ -68,12 +69,12 @@ async-trait = "0.1.51" lazy_static = "1.4.0" -rust-argon2 = "0.8.3" -rand = "0.8.4" +#rust-argon2 = "0.8.3" +#rand = "0.8.4" -async-channel = "1.6.1" -easy-parallel = "3.1.0" -genawaiter = "0.99.1" +#async-channel = "1.6.1" +#easy-parallel = "3.1.0" +#genawaiter = "0.99.1" [build-dependencies] capnpc = "0.14.4" @@ -83,6 +84,7 @@ walkdir = "2.3.2" [dev-dependencies] futures-test = "0.3.16" tempfile = "3.2" +bincode = "2.0.0-dev" [patch.crates-io] bincode = { git = "https://github.com/dequbed/bincode.git", branch = "feature/in_place_buffer" } diff --git a/src/db/mod.rs b/src/db/mod.rs index f33d98d..7f56833 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -90,131 +90,3 @@ impl> Adapter for AllocAdapter { } } -#[cfg(test)] -mod tests { - use super::*; - use std::result::Result; - use std::ops::Deref; - - use lmdb::{ - EnvironmentFlags as EF, - DatabaseFlags as DF, - WriteFlags as WF, - }; - - pub struct TempEnv { - dir: tempfile::TempDir, - env: Arc, - } - - impl Deref for TempEnv { - type Target = Arc; - fn deref(&self) -> &Self::Target { - &self.env - } - } - - pub fn open_test_env() -> TempEnv { - let dir = tempfile::tempdir().expect("Failed to create tempdir for testdb"); - let env = Environment::new() - .set_flags(EF::NO_SYNC | EF::WRITE_MAP) - .open(dir.path()).expect("Failed to open lmdb"); - let env = Arc::new(env); - - TempEnv { dir, env } - } - - struct TestAdapter; - - #[derive(Debug)] - enum TestErr { - Utf8(std::str::Utf8Error), - Binc(Box), - LMDB(lmdb::Error), - } - - impl From for TestErr { - fn from(e: lmdb::Error) -> TestErr { - TestErr::LMDB(e) - } - } - - impl From for TestErr { - fn from(e: std::str::Utf8Error) -> TestErr { - TestErr::Utf8(e) - } - } - - impl From for TestErr { - fn from(e: bincode::Error) -> TestErr { - TestErr::Binc(e) - } - } - - impl DatabaseAdapter for TestAdapter { - type Key = str; - type Err = TestErr; - - fn serialize_key(key: &Self::Key) -> &[u8] { - key.as_bytes() - } - fn deserialize_key<'de>(input: &'de [u8]) -> Result<&'de Self::Key, Self::Err> { - std::str::from_utf8(input).map_err(|e| e.into()) - } - } - - type TestDB<'txn> = Objectstore<'txn, TestAdapter, &'txn str>; - - #[test] - fn simple_get() { - let e = open_test_env(); - let ldb = e.create_db(None, DF::empty()).expect("Failed to create lmdb db"); - - let db = DB::new(e.env.clone(), ldb); - - let testdb = TestDB::new(db.clone()); - - let mut val = "value"; - let mut txn = db.begin_rw_txn().expect("Failed to being rw txn"); - testdb.put(&mut txn, "key", &val, WF::empty()).expect("Failed to insert"); - testdb.put(&mut txn, "key2", &val, WF::empty()).expect("Failed to insert"); - testdb.put(&mut txn, "key3", &val, WF::empty()).expect("Failed to insert"); - testdb.put(&mut txn, "key4", &val, WF::empty()).expect("Failed to insert"); - testdb.put(&mut txn, "key5", &val, WF::empty()).expect("Failed to insert"); - txn.commit().expect("commit failed"); - - { - let txn; - txn = db.begin_ro_txn().unwrap(); - - let val = testdb.get(&txn, "key").expect("Failed to retrieve"); - assert_eq!(Some("value"), val); - } - - { - let val2 = "longer_value"; - let mut txn = db.begin_rw_txn().unwrap(); - testdb.put(&mut txn, "key", &val2, WF::empty()).expect("Failed to update"); - txn.commit().unwrap(); - } - - { - let txn = db.begin_ro_txn().unwrap(); - let found = testdb.get_in_place(&txn, "key", &mut val).expect("Failed to retrieve update"); - assert!(found); - assert_eq!("longer_value", val); - } - - { - let txn = db.begin_ro_txn().unwrap(); - let mut it = testdb.iter(&txn).unwrap(); - assert_eq!("longer_value", it.next().unwrap().unwrap()); - let mut i = 0; - while let Some(e) = it.next() { - assert_eq!("value", e.unwrap()); - i += 1; - } - assert_eq!(i, 4) - } - } -} diff --git a/src/db/state.rs b/src/db/state.rs index 3fbbe21..5071a4a 100644 --- a/src/db/state.rs +++ b/src/db/state.rs @@ -149,7 +149,7 @@ impl StateAccessor { } } -#[cfg(test)] +#[cfg(test_dis)] mod tests { use super::*; diff --git a/src/lib.rs b/src/lib.rs index ca0c30e..8508aaf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,18 +17,18 @@ mod initiator; mod space; */ -use crate::oid::ObjectIdentifier; -use std::convert::TryFrom; -use crate::state::value::{UInt32, Vec3u8, SerializeDynOid}; use rkyv::ser::serializers::AllocSerializer; -use rkyv::SerializeUnsized; +use rkyv::{SerializeUnsized, archived_value, Infallible, Deserialize}; +use crate::oid::ObjectIdentifier; +use std::str::FromStr; mod resource; mod schema; mod state; mod db; mod network; -mod oid; +pub mod oid; +mod varint; /* @@ -55,35 +55,46 @@ pub fn main() { let db = db::StateDB::init("/tmp/state").unwrap(); println!("{:#?}", db); - let s = state::StateBuilder::new(); - let state = s.add( - ObjectIdentifier::try_from("1.3.6.1.4.1.48398.612.1").unwrap(), - Box::new(UInt32(0))) - .add( - ObjectIdentifier::try_from("1.3.6.1.4.1.48398.612.2").unwrap(), - Box::new(Vec3u8 { a: 1, b: 2, c: 3}) - ) - .finish(); - - println!("{:?}", state); - let b = true; - println!("{:?}", b.archived_type_oid()); + //println!("{}", b.archived_type_oid()); - let boid = ObjectIdentifier::try_from("1.3.6.1.4.1.48398.612.1.1").unwrap(); - let b2 = Box::new(false); - let ent = state::value::Entry { oid: &boid, val: &b2 }; + let boid = &state::value::OID_BOOL; + let b2 = false; + let ent = state::Entry { oid: boid, val: &b2 }; println!("ent {:?}", &ent); let s = serde_json::to_string(&ent).unwrap(); println!("{}", &s); - let ent2: state::value::OwnedEntry = serde_json::from_str(&s).unwrap(); + let ent2: state::OwnedEntry = serde_json::from_str(&s).unwrap(); println!("ent2: {:?}", ent2); - let mut ser = AllocSerializer::<1024>::default(); + println!("Hello"); + + let mut ser = AllocSerializer::<32>::default(); + //let b3 = Box::new(u32::from_ne_bytes([0xDE, 0xAD, 0xBE, 0xEF])) as Box; let b3 = Box::new(true) as Box; - let pos = b3.serialize_unsized(&mut ser).unwrap(); + let pos3 = b3.serialize_unsized(&mut ser).unwrap(); + let pos4 = 0; + //let pos4 = b4.serialize_unsized(&mut ser).unwrap(); let buf = ser.into_serializer().into_inner(); - println!("Serialized {} bytes: {:?}", pos, buf.as_slice()); + println!("({}) {:?} | {:?}", pos3, &buf[..pos3], &buf[pos3..]); + //println!("Serialized {} bytes: {:?} | {:?} | {:?}", pos4, &buf[..pos3], &buf[pos3+12..pos4], &buf[pos4+12..]); + let r3 = unsafe { + archived_value::>(&buf.as_slice(), pos3) + }; + let v3: Box = r3.deserialize(&mut Infallible).unwrap(); + println!("{:?}", v3); + + let koid = ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.2.1").unwrap(); + let state = state::State::build() + .add(koid, Box::new(0xDEADBEEFu32)) + .finish(); + + println!("{:?}", state); + let json = serde_json::to_string(&state).unwrap(); + println!("{}", json); + let state_back: state::State = serde_json::from_str(&json).unwrap(); + println!("{:?}", state_back); + let val = state_back.inner; } /*fn main() { diff --git a/src/oid.rs b/src/oid.rs index 97d0a98..c5a30ab 100644 --- a/src/oid.rs +++ b/src/oid.rs @@ -6,8 +6,8 @@ //! //! //! ## Parsing OID String Representation -//! ```rust -//! use oid::prelude::*; +//! ```ignore +//! use crate::oid::prelude::*; //! //! fn main() -> Result<(), ObjectIdentifierError> { //! let oid = ObjectIdentifier::try_from("0.1.2.3")?; @@ -16,8 +16,8 @@ //! ``` //! //! ## Parsing OID Binary Representation -//! ```rust -//! use oid::prelude::*; +//! ```ignore +//! use prelude::*; //! //! fn main() -> Result<(), ObjectIdentifierError> { //! let oid = ObjectIdentifier::try_from(vec![0x00, 0x01, 0x02, 0x03])?; @@ -26,8 +26,8 @@ //! ``` //! //! ## Encoding OID as String Representation -//! ```rust -//! use oid::prelude::*; +//! ```ignore +//! use prelude::*; //! //! fn main() -> Result<(), ObjectIdentifierError> { //! let oid = ObjectIdentifier::try_from("0.1.2.3")?; @@ -38,7 +38,7 @@ //! ``` //! //! ## Encoding OID as Binary Representation -//! ```rust +//! ```ignore //! use oid::prelude::*; //! //! fn main() -> Result<(), ObjectIdentifierError> { @@ -52,13 +52,20 @@ //! [Object Identifiers]: https://en.wikipedia.org/wiki/Object_identifier //! [ITU]: https://en.wikipedia.org/wiki/International_Telecommunications_Union -use core::convert::{TryFrom, TryInto}; +use core::convert::{TryFrom }; -use rkyv::{Archive, Serialize, Fallible}; +use rkyv::{Archive, Serialize}; use rkyv::vec::{ArchivedVec, VecResolver}; +use std::ops::Deref; +use std::fmt; +use std::fmt::Formatter; +use rkyv::ser::Serializer; +use std::str::FromStr; +use crate::varint::VarU128; +use std::convert::TryInto; -// OID spec doesn't specify the maximum integer size of each node, so we default to usize -type Node = usize; +type Node = u128; +type VarNode = VarU128; /// Convenience module for quickly importing the public interface (e.g., `use oid::prelude::*`) pub mod prelude { @@ -106,111 +113,253 @@ pub enum ObjectIdentifierError { } /// Object Identifier (OID) -#[derive(Clone, Debug, Eq, PartialEq, Hash)] +#[derive(Clone, Eq, PartialEq, Hash)] +#[repr(transparent)] pub struct ObjectIdentifier { - root: ObjectIdentifierRoot, - first_node: u8, - child_nodes: Vec, + nodes: Box<[u8]>, } impl ObjectIdentifier { - const fn new(root: ObjectIdentifierRoot, first_node: u8, child_nodes: Vec) - -> Self + #[inline(always)] + pub const fn new_unchecked(nodes: Box<[u8]>) -> Self { + Self { nodes } + } + pub fn from_box(nodes: Box<[u8]>) -> Result { + if nodes.len() < 1 { + return Err(ObjectIdentifierError::IllegalRootNode); + }; + ObjectIdentifierRoot::try_from(nodes[0] / 40)?; + + let mut parsing_big_int = false; + let mut big_int: Node = 0; + for i in 1..nodes.len() { + if !parsing_big_int && nodes[i] < 128 {} else { + if big_int > 0 { + if big_int >= Node::MAX >> 7 { + return Err(ObjectIdentifierError::IllegalChildNodeValue); + } + big_int <<= 7; + }; + big_int |= (nodes[i] & !0x80) as Node; + parsing_big_int = nodes[i] & 0x80 != 0; + } + if big_int > 0 && !parsing_big_int { + big_int = 0; + } + } + Ok(Self { nodes }) + } + + pub fn build>(root: ObjectIdentifierRoot, first: u8, children: B) + -> Result { - Self { root, first_node, child_nodes } + if first > 40 { + return Err(ObjectIdentifierError::IllegalFirstChildNode); + } + + let children = children.as_ref(); + let mut vec = Vec::with_capacity(children.len() + 1); + vec.push((root as u8) * 40 + first); + for child in children { + let var: VarNode = child.into(); + vec.extend_from_slice(var.as_bytes()) + } + Ok(Self { nodes: vec.into_boxed_slice() }) + } + + #[inline(always)] + pub fn root(&self) -> Result { + ObjectIdentifierRoot::try_from(self.nodes[0] / 40) + } + #[inline(always)] + pub const fn first_node(&self) -> u8 { + self.nodes[0] % 40 + } + #[inline(always)] + pub fn child_nodes(&self) -> &[u8] { + &self.nodes[1..] + } + #[inline(always)] + pub const fn as_bytes(&self) -> &[u8] { + &self.nodes } } +impl Deref for ObjectIdentifier { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + &self.nodes + } +} + +impl FromStr for ObjectIdentifier { + type Err = ObjectIdentifierError; + + fn from_str(value: &str) -> Result { + let mut nodes = value.split("."); + let root = nodes.next() + .and_then(|n| n.parse::().ok()) + .and_then(|n| n.try_into().ok()) + .ok_or(ObjectIdentifierError::IllegalRootNode)?; + + let first = nodes.next() + .and_then(|n| parse_string_first_node(n).ok()) + .ok_or(ObjectIdentifierError::IllegalFirstChildNode)?; + + let mut children = if let (_, Some(hint)) = nodes.size_hint() { + Vec::with_capacity(hint) + } else { + Vec::new() + }; + + for child in nodes.map(|n| n.parse().ok()) { + if let Some(c) = child { + children.push(c); + } else { + return Err(ObjectIdentifierError::IllegalChildNodeValue); + } + } + + ObjectIdentifier::build(root, first, children) + } +} + +impl fmt::Display for ObjectIdentifier { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let show: String = self.into(); + write!(f, "{}", show) + } +} +impl fmt::Debug for ObjectIdentifier { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + let show: String = self.into(); + write!(f, "{}", show) + } +} + +#[repr(transparent)] +pub struct ArchivedObjectIdentifier { + archived: ArchivedVec +} + +impl Deref for ArchivedObjectIdentifier { + type Target = [u8]; + fn deref(&self) -> &Self::Target { + self.archived.as_slice() + } +} + +impl fmt::Debug for ArchivedObjectIdentifier { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "{}", &convert_to_string(self.archived.as_slice()) + .unwrap_or_else(|e| format!("Invalid OID: {:?}", e))) + } +} impl Archive for ObjectIdentifier { - type Archived = ArchivedVec; + type Archived = ArchivedObjectIdentifier; type Resolver = VecResolver; unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) { - let vec: Vec = self.clone().into(); - vec.resolve(pos, resolver, out); + let (oid_pos, oid_out) = rkyv::out_field!(out.archived); + ArchivedVec::resolve_from_slice(self.nodes.as_ref(), pos + oid_pos, resolver, oid_out); + } +} +impl Archive for &'static ObjectIdentifier { + type Archived = ArchivedObjectIdentifier; + type Resolver = VecResolver; + + unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) { + let (oid_pos, oid_out) = rkyv::out_field!(out.archived); + ArchivedVec::resolve_from_slice(self.nodes.as_ref(), pos + oid_pos, resolver, oid_out); } } -impl Serialize for ObjectIdentifier - where Vec: Serialize +impl Serialize for ObjectIdentifier + where [u8]: rkyv::SerializeUnsized { fn serialize(&self, serializer: &mut S) -> Result { - let vec: Vec = self.clone().into(); - vec.serialize(serializer) + ArchivedVec::serialize_from_slice(self.nodes.as_ref(), serializer) } } -fn parse_string_first_node( - nodes: &mut dyn Iterator, -) -> Result { - if let Some(first_child_node) = nodes.next() { - let first_child_node: u8 = first_child_node - .parse() - .map_err(|_| ObjectIdentifierError::IllegalFirstChildNode)?; - if first_child_node > 39 { - return Err(ObjectIdentifierError::IllegalFirstChildNode); - } - Ok(first_child_node) +fn parse_string_first_node(first_child_node: &str) -> Result { + let first_child_node: u8 = first_child_node + .parse() + .map_err(|_| ObjectIdentifierError::IllegalFirstChildNode)?; + if first_child_node > 39 { + return Err(ObjectIdentifierError::IllegalFirstChildNode); + } + Ok(first_child_node) +} + +fn parse_string_child_node( + node_str: &str, + out: &mut Vec +) -> Result<(), ObjectIdentifierError> { + let mut node: Node = node_str.parse() + .map_err(|_| ObjectIdentifierError::IllegalChildNodeValue)?; + // TODO bench against !*node &= 0x80, compiler may already optimize better + if node <= 127 { + out.push(node as u8); } else { - Err(ObjectIdentifierError::IllegalFirstChildNode) + let vi: VarNode = node.into(); + out.extend_from_slice(vi.as_bytes()); } -} -fn parse_string_child_nodes( - nodes: &mut dyn Iterator, -) -> Result, ObjectIdentifierError> { - let mut result: Vec = vec![]; - while let Some(node) = nodes.next() { - result.push( - node.parse() - .map_err(|_| ObjectIdentifierError::IllegalChildNodeValue)?, - ); - } - Ok(result) + Ok(()) } impl ObjectIdentifier { fn from_string(value: S) -> Result where - S: Into, + S: AsRef, { - let value = value.into(); - let mut nodes = value.split("."); - match &nodes.next() { - Some(root_node_value) => { - let root_node_value: Result = root_node_value.parse(); - match root_node_value { - Ok(root_node) => { - let root_node: Result = root_node.try_into(); - match root_node { - Ok(root) => { - let first_node = parse_string_first_node(&mut nodes)?; - Ok(ObjectIdentifier { - root, - first_node, - child_nodes: parse_string_child_nodes(&mut nodes)?, - }) - } - Err(_err) => Err(ObjectIdentifierError::IllegalRootNode), - } - } - Err(_) => Err(ObjectIdentifierError::IllegalRootNode), + ObjectIdentifier::from_str(value.as_ref()) + } +} + +fn convert_to_string(nodes: &[u8]) -> Result { + assert!(nodes.len() > 0); + let root = nodes[0] / 40; + let mut out = root.to_string(); + + out.push('.'); + let first = nodes[0] % 40; + out.extend(first.to_string().chars()); + + let mut parsing_big_int = false; + let mut big_int: Node = 0; + for i in 1..nodes.len() { + if !parsing_big_int && nodes[i] < 128 { + // less than 7 bit of node value + out.push('.'); + let nr = nodes[i].to_string(); + out.extend(nr.chars()); + } else { + if big_int > 0 { + if big_int >= Node::MAX >> 7 { + return Err(ObjectIdentifierError::IllegalChildNodeValue); } - } - None => Err(ObjectIdentifierError::IllegalRootNode), + big_int <<= 7; + }; + big_int += (nodes[i] & !0x80) as Node; + parsing_big_int = nodes[i] & 0x80 != 0; + } + if big_int > 0 && !parsing_big_int { + out.push('.'); + out.extend(big_int.to_string().chars()); + big_int = 0; } } + + Ok(out) } impl Into for &ObjectIdentifier { fn into(self) -> String { - let mut result: String = self.root.into(); - result.push_str(&format!(".{}", self.first_node)); - for node in &self.child_nodes { - result.push_str(&format!(".{}", node)); - } - result + convert_to_string(&self.nodes) + .expect("Valid OID object couldn't be serialized.") } } @@ -220,34 +369,15 @@ impl Into for ObjectIdentifier { } } -impl Into> for &ObjectIdentifier { - fn into(self) -> Vec { - let mut result: Vec = vec![self.root as u8]; - result[0] = result[0] * 40 + self.first_node; - for node in self.child_nodes.iter() { - // TODO bench against !*node &= 0x80, compiler may already optimize better - if *node <= 127 { - result.push(*node as u8); - } else { - let mut value = *node; - let mut mask: Node = 0; - let mut encoded: Vec = vec![]; - while value > 0x80 { - encoded.insert(0, (value & 0x7f | mask) as u8); - value >>= 7; - mask = 0x80; - } - encoded.insert(0, (value | mask) as u8); - result.append(&mut encoded); - } - } - result +impl<'a> Into<&'a [u8]> for &'a ObjectIdentifier { + fn into(self) -> &'a [u8] { + &self.nodes } } impl Into> for ObjectIdentifier { fn into(self) -> Vec { - (&self).into() + self.nodes.into_vec() } } @@ -267,45 +397,15 @@ impl TryFrom for ObjectIdentifier { impl TryFrom<&[u8]> for ObjectIdentifier { type Error = ObjectIdentifierError; - fn try_from(value: &[u8]) -> Result { - if value.len() < 1 { - return Err(ObjectIdentifierError::IllegalRootNode); - }; - let root = ObjectIdentifierRoot::try_from(value[0] / 40)?; - let first_node = value[0] % 40; - let mut child_nodes = vec![]; - let mut parsing_big_int = false; - let mut big_int: Node = 0; - for i in 1..value.len() { - if !parsing_big_int && value[i] < 128 { - child_nodes.push(value[i] as Node); - } else { - if big_int > 0 { - if big_int >= Node::max_value() >> 7 { - return Err(ObjectIdentifierError::IllegalChildNodeValue); - } - big_int <<= 7; - }; - big_int |= (value[i] & !0x80) as Node; - parsing_big_int = value[i] & 0x80 != 0; - } - if big_int > 0 && !parsing_big_int { - child_nodes.push(big_int); - big_int = 0; - } - } - Ok(ObjectIdentifier { - root, - first_node, - child_nodes, - }) + fn try_from(nodes: &[u8]) -> Result { + Self::from_box(nodes.into()) } } impl TryFrom> for ObjectIdentifier { type Error = ObjectIdentifierError; fn try_from(value: Vec) -> Result { - value.as_slice().try_into() + Self::from_box(value.into_boxed_slice()) } } @@ -381,8 +481,7 @@ mod serde_support { let encoded: String = self.into(); serializer.serialize_str(&encoded) } else { - let encoded: Vec = self.into(); - serializer.serialize_bytes(&encoded) + serializer.serialize_bytes(self.as_bytes()) } } } @@ -391,125 +490,65 @@ mod serde_support { #[cfg(test)] mod tests { use super::*; + use std::convert::TryInto; - mod serde_support { - use super::*; - use serde_derive::{Deserialize, Serialize}; - use serde_xml_rs; - - #[test] - fn bincode_serde_serialize() { - let expected: Vec = vec![ - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, - 0x0D, 0x15, - ]; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x01, - child_nodes: vec![1, 2, 3, 5, 8, 13, 21], - }; - let actual: Vec = bincode::serialize(&oid).unwrap(); - assert_eq!(expected, actual); - } - - #[test] - fn bincode_serde_deserialize() { - let expected = ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x01, - child_nodes: vec![1, 2, 3, 5, 8, 13, 21], - }; - let actual: ObjectIdentifier = bincode::deserialize(&[ - 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x08, - 0x0D, 0x15, - ]) - .unwrap(); - assert_eq!(expected, actual); - } - - #[derive(Debug, Deserialize, PartialEq, Serialize)] - struct MyStruct { - oid: ObjectIdentifier - } - - #[test] - fn xml_serde_serialize() { - let mydata = MyStruct { - oid: ObjectIdentifier::try_from("1.2.3.5.8.13.21").unwrap() - }; - let expected = r#"1.2.3.5.8.13.21"#; - let actual = serde_xml_rs::to_string(&mydata).unwrap(); - assert_eq!(expected, actual); - } - - #[test] - fn xml_serde_deserialize_element() { - let src = r#"1.2.3.5.8.13.21"#; - - let expected = MyStruct { - oid: ObjectIdentifier::try_from("1.2.3.5.8.13.21").unwrap() - }; - let actual: MyStruct = serde_xml_rs::from_str(&src).unwrap(); - assert_eq!(expected, actual); - } - - #[test] - fn xml_serde_deserialize_attribute() { - let src = r#""#; - - let expected = MyStruct { - oid: ObjectIdentifier::try_from("1.2.3.5.8.13.21").unwrap() - }; - let actual: MyStruct = serde_xml_rs::from_str(&src).unwrap(); - assert_eq!(expected, actual); - } + #[test] + fn bincode_serde_roundtrip() { + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::ItuT, + 0x01, + vec![1, 2, 3, 5, 8, 13, 21], + ).unwrap(); + let buffer: Vec = bincode::serialize(&expected).unwrap(); + let actual = bincode::deserialize(&buffer).unwrap(); + assert_eq!(expected, actual); } #[test] fn encode_binary_root_node_0() { let expected: Vec = vec![0]; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x00, - child_nodes: vec![], - }; - let actual: Vec = (&oid).into(); + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::ItuT, + 0x00, + vec![], + ).unwrap(); + let actual: Vec = oid.into(); assert_eq!(expected, actual); } #[test] fn encode_binary_root_node_1() { let expected: Vec = vec![40]; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::Iso, - first_node: 0x00, - child_nodes: vec![], - }; - let actual: Vec = (&oid).into(); + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::Iso, + 0x00, + vec![], + ).unwrap(); + let actual: Vec = oid.into(); assert_eq!(expected, actual); } #[test] fn encode_binary_root_node_2() { let expected: Vec = vec![80]; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::JointIsoItuT, - first_node: 0x00, - child_nodes: vec![], - }; - let actual: Vec = (&oid).into(); + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::JointIsoItuT, + 0x00, + vec![], + ).unwrap(); + let actual: Vec = oid.into(); assert_eq!(expected, actual); } #[test] fn encode_binary_example_1() { let expected: Vec = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15]; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x01, - child_nodes: vec![1, 2, 3, 5, 8, 13, 21], - }; - let actual: Vec = (&oid).into(); + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::ItuT, + 0x01, + vec![1, 2, 3, 5, 8, 13, 21], + ).unwrap(); + let actual: Vec = oid.into(); assert_eq!(expected, actual); } @@ -519,35 +558,35 @@ mod tests { 0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53, 0x92, 0x30, ]; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::JointIsoItuT, - first_node: 39, - child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352], - }; - let actual: Vec = (&oid).into(); + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::JointIsoItuT, + 39, + vec![42, 2501, 65535, 2147483647, 1235, 2352], + ).unwrap(); + let actual: Vec = (oid).into(); assert_eq!(expected, actual); } #[test] fn encode_string_root_node_0() { let expected = "0.0"; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x00, - child_nodes: vec![], - }; - let actual: String = (&oid).into(); + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::ItuT, + 0x00, + vec![], + ).unwrap(); + let actual: String = (oid).into(); assert_eq!(expected, actual); } #[test] fn encode_string_root_node_1() { let expected = "1.0"; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::Iso, - first_node: 0x00, - child_nodes: vec![], - }; + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::Iso, + 0x00, + vec![], + ).unwrap(); let actual: String = (&oid).into(); assert_eq!(expected, actual); } @@ -555,11 +594,11 @@ mod tests { #[test] fn encode_string_root_node_2() { let expected = "2.0"; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::JointIsoItuT, - first_node: 0x00, - child_nodes: vec![], - }; + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::JointIsoItuT, + 0x00, + vec![], + ).unwrap(); let actual: String = (&oid).into(); assert_eq!(expected, actual); } @@ -567,11 +606,11 @@ mod tests { #[test] fn encode_string_example_1() { let expected = "0.1.1.2.3.5.8.13.21"; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x01, - child_nodes: vec![1, 2, 3, 5, 8, 13, 21], - }; + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::ItuT, + 0x01, + vec![1, 2, 3, 5, 8, 13, 21], + ).unwrap(); let actual: String = (&oid).into(); assert_eq!(expected, actual); } @@ -579,66 +618,66 @@ mod tests { #[test] fn encode_string_example_2() { let expected = "2.39.42.2501.65535.2147483647.1235.2352"; - let oid = ObjectIdentifier { - root: ObjectIdentifierRoot::JointIsoItuT, - first_node: 39, - child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352], - }; + let oid = ObjectIdentifier::build( + ObjectIdentifierRoot::JointIsoItuT, + 39, + vec![42, 2501, 65535, 2147483647, 1235, 2352], + ).unwrap(); let actual: String = (&oid).into(); assert_eq!(expected, actual); } #[test] fn parse_binary_root_node_0() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x00, - child_nodes: vec![], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::ItuT, + 0x00, + vec![], + ); let actual = vec![0x00].try_into(); assert_eq!(expected, actual); } #[test] fn parse_binary_root_node_1() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::Iso, - first_node: 0x00, - child_nodes: vec![], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::Iso, + 0x00, + vec![], + ); let actual = vec![40].try_into(); assert_eq!(expected, actual); } #[test] fn parse_binary_root_node_2() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::JointIsoItuT, - first_node: 0x00, - child_nodes: vec![], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::JointIsoItuT, + 0x00, + vec![], + ); let actual = vec![80].try_into(); assert_eq!(expected, actual); } #[test] fn parse_binary_example_1() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x01, - child_nodes: vec![1, 2, 3, 5, 8, 13, 21], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::ItuT, + 0x01, + vec![1, 2, 3, 5, 8, 13, 21], + ); let actual = vec![0x01, 0x01, 0x02, 0x03, 0x05, 0x08, 0x0D, 0x15].try_into(); assert_eq!(expected, actual); } #[test] fn parse_binary_example_2() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::JointIsoItuT, - first_node: 39, - child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::JointIsoItuT, + 39, + vec![42, 2501, 65535, 2147483647, 1235, 2352], + ); let actual = vec![ 0x77, 0x2A, 0x93, 0x45, 0x83, 0xFF, 0x7F, 0x87, 0xFF, 0xFF, 0xFF, 0x7F, 0x89, 0x53, 0x92, 0x30, @@ -649,55 +688,55 @@ mod tests { #[test] fn parse_string_root_node_0() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x00, - child_nodes: vec![], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::ItuT, + 0x00, + vec![], + ); let actual = "0.0".try_into(); assert_eq!(expected, actual); } #[test] fn parse_string_root_node_1() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::Iso, - first_node: 0x00, - child_nodes: vec![], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::Iso, + 0x00, + vec![], + ); let actual = "1.0".try_into(); assert_eq!(expected, actual); } #[test] fn parse_string_root_node_2() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::JointIsoItuT, - first_node: 0x00, - child_nodes: vec![], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::JointIsoItuT, + 0x00, + vec![], + ); let actual = "2.0".try_into(); assert_eq!(expected, actual); } #[test] fn parse_string_example_1() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::ItuT, - first_node: 0x01, - child_nodes: vec![1, 2, 3, 5, 8, 13, 21], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::ItuT, + 0x01, + vec![1, 2, 3, 5, 8, 13, 21], + ); let actual = "0.1.1.2.3.5.8.13.21".try_into(); assert_eq!(expected, actual); } #[test] fn parse_string_example_2() { - let expected = Ok(ObjectIdentifier { - root: ObjectIdentifierRoot::JointIsoItuT, - first_node: 39, - child_nodes: vec![42, 2501, 65535, 2147483647, 1235, 2352], - }); + let expected = ObjectIdentifier::build( + ObjectIdentifierRoot::JointIsoItuT, + 39, + vec![42, 2501, 65535, 2147483647, 1235, 2352], + ); let actual = "2.39.42.2501.65535.2147483647.1235.2352".try_into(); assert_eq!(expected, actual); } @@ -717,7 +756,7 @@ mod tests { for i in 40..core::u8::MAX { let string_val = format!("{}.2.3.4", i); let mut nodes_iter = string_val.split("."); - let actual = parse_string_first_node(&mut nodes_iter); + let actual = parse_string_first_node(nodes_iter.next().unwrap()); assert_eq!(expected, actual); } } @@ -727,17 +766,7 @@ mod tests { let expected = Err(ObjectIdentifierError::IllegalFirstChildNode); let string_val = String::new(); let mut nodes_iter = string_val.split("."); - let actual = parse_string_first_node(&mut nodes_iter); - assert_eq!(expected, actual); - } - - #[test] - fn illegal_first_node_none() { - let expected = Err(ObjectIdentifierError::IllegalFirstChildNode); - let string_val = String::new(); - let mut nodes_iter = string_val.split("."); - let _ = nodes_iter.next(); - let actual = parse_string_first_node(&mut nodes_iter); + let actual = parse_string_first_node(nodes_iter.next().unwrap()); assert_eq!(expected, actual); } @@ -746,7 +775,7 @@ mod tests { let expected = Err(ObjectIdentifierError::IllegalFirstChildNode); let string_val = String::from("40"); let mut nodes_iter = string_val.split("."); - let actual = parse_string_first_node(&mut nodes_iter); + let actual = parse_string_first_node(nodes_iter.next().unwrap()); assert_eq!(expected, actual); } @@ -814,11 +843,11 @@ mod tests { #[test] fn encode_to_string() { let expected = String::from("1.2.3.4"); - let actual: String = ObjectIdentifier { - root: ObjectIdentifierRoot::Iso, - first_node: 2, - child_nodes: vec![3, 4], - } + let actual: String = ObjectIdentifier::build( + ObjectIdentifierRoot::Iso, + 2, + vec![3, 4], + ).unwrap() .into(); assert_eq!(expected, actual); } @@ -826,12 +855,12 @@ mod tests { #[test] fn encode_to_bytes() { let expected = vec![0x2A, 0x03, 0x04]; - let actual: Vec = ObjectIdentifier { - root: ObjectIdentifierRoot::Iso, - first_node: 2, - child_nodes: vec![3, 4], - } + let actual: Vec = ObjectIdentifier::build( + ObjectIdentifierRoot::Iso, + 2, + vec![3, 4], + ).unwrap() .into(); assert_eq!(expected, actual); } -} +} \ No newline at end of file diff --git a/src/state/mod.rs b/src/state/mod.rs index 65a1ee7..0e4ea71 100644 --- a/src/state/mod.rs +++ b/src/state/mod.rs @@ -20,20 +20,18 @@ use rkyv::{ out_field, }; -use crate::oid::ObjectIdentifier; - pub mod value; -pub use value::{ - SerializeDynValue, - DeserializeDynValue, -}; - -#[derive(Archive, Serialize, Deserialize)] -pub struct StateEntry { - key: ObjectIdentifier, - val: Box, -} +use value::{SerializeValue, RegisteredImpl}; +use crate::state::value::{TypeOid, DynVal, DynOwnedVal}; +use crate::oid::ObjectIdentifier; +use serde::ser::SerializeMap; +use std::ops::Deref; +use std::fmt::Formatter; +use serde::Deserializer; +use serde::de::MapAccess; +use serde::de::Error as _; +#[derive(serde::Serialize, serde::Deserialize)] #[derive(Archive, Serialize, Deserialize)] /// State object of a resource /// @@ -43,44 +41,41 @@ pub struct StateEntry { /// 3. it is sendable and forwarded to all Actors and Notifys pub struct State { hash: u64, - inner: Vec, -} -impl PartialEq for State { - fn eq(&self, other: &Self) -> bool { - self.hash == other.hash - } -} -impl PartialEq> for State { - fn eq(&self, other: &Archived) -> bool { - self.hash == other.hash - } -} -impl Eq for State {} - -impl fmt::Debug for State { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut sf = f.debug_struct("State"); - for StateEntry { key, val } in self.inner.iter() { - let k: String = key.into(); - sf.field(k.as_ref(), val); - } - sf.finish() - } + pub inner: Vec, } impl State { pub fn build() -> StateBuilder { StateBuilder::new() } - pub fn hash(&self) -> u64 { self.hash } } +impl PartialEq for State { + fn eq(&self, other: &Self) -> bool { + self.hash == other.hash + } +} + +impl Eq for State {} + +impl fmt::Debug for State { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut sf = f.debug_struct("State"); + for OwnedEntry { oid, val } in self.inner.iter() { + let k: String = oid.into(); + sf.field(k.as_ref(), val); + } + sf.finish() + } +} + + pub struct StateBuilder { hasher: DefaultHasher, - inner: Vec + inner: Vec } impl StateBuilder { @@ -102,14 +97,71 @@ impl StateBuilder { /// to `Hash`. Specifically, you can't have a trait object of `Hash` because `Hash` depends on /// `Self`. In this function however the compiler still knows the exact type of `V` and can /// call statically call its `hash` method. - pub fn add(mut self, key: ObjectIdentifier<>, val: Box) -> Self - where V: SerializeDynValue + Hash + pub fn add(mut self, oid: ObjectIdentifier, val: Box) -> Self + where V: SerializeValue + Hash + Archive, + Archived: TypeOid + RegisteredImpl, { // Hash before creating the StateEntry struct which removes the type information - key.hash(&mut self.hasher); + oid.hash(&mut self.hasher); val.hash(&mut self.hasher); - self.inner.push(StateEntry { key, val }); + self.inner.push(OwnedEntry { oid, val }); self } -} \ No newline at end of file +} + +#[derive(Debug)] +pub struct Entry<'a> { + pub oid: &'a ObjectIdentifier, + pub val: &'a dyn SerializeValue, +} + +#[derive(Debug, Archive, Serialize, Deserialize)] +pub struct OwnedEntry { + pub oid: ObjectIdentifier, + pub val: Box, +} + +impl<'a> serde::Serialize for Entry<'a> { + fn serialize(&self, serializer: S) -> Result + where S: serde::Serializer + { + let mut ser = serializer.serialize_map(Some(1))?; + ser.serialize_entry(&self.oid, &DynVal(self.val))?; + ser.end() + } +} + +impl serde::Serialize for OwnedEntry { + fn serialize(&self, serializer: S) -> Result + where S: serde::Serializer + { + let mut ser = serializer.serialize_map(Some(1))?; + ser.serialize_entry(&self.oid, &DynVal(self.val.deref()))?; + ser.end() + } +} +impl<'de> serde::Deserialize<'de> for OwnedEntry { + fn deserialize(deserializer: D) -> Result + where D: Deserializer<'de> + { + deserializer.deserialize_map(OwnedEntryVisitor) + } +} + +struct OwnedEntryVisitor; +impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor { + type Value = OwnedEntry; + + fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { + write!(formatter, "an one entry map from OID to some value object") + } + + fn visit_map>(self, mut map: A) -> Result + { + let oid: ObjectIdentifier = map.next_key()? + .ok_or(A::Error::missing_field("oid"))?; + let val: DynOwnedVal = map.next_value()?; + Ok(OwnedEntry { oid, val: val.0 }) + } +} diff --git a/src/state/value.rs b/src/state/value.rs index 00f3963..b79b6be 100644 --- a/src/state/value.rs +++ b/src/state/value.rs @@ -5,12 +5,13 @@ use std::{ fmt, any::Any, hash::Hash, - ops::Deref, - convert::TryFrom, + str::FromStr, }; -use rkyv::{Archive, Archived, Serialize, Deserialize, out_field, Fallible, DeserializeUnsized, ArchivePointee, ArchiveUnsized, ArchivedMetadata, SerializeUnsized}; -use rkyv_dyn::{archive_dyn, DynSerializer, DynError, DynDeserializer}; +use rkyv::{Archive, Archived, Serialize, Deserialize, out_field, Fallible, DeserializeUnsized, + ArchivePointee, ArchiveUnsized, ArchivedMetadata, SerializeUnsized, + }; +use rkyv_dyn::{DynSerializer, DynError, DynDeserializer}; use rkyv_typename::TypeName; use ptr_meta::{DynMetadata, Pointee}; @@ -24,8 +25,14 @@ use std::fmt::Formatter; use serde::de::Error as _; use std::mem::MaybeUninit; - -pub trait Value: fmt::Debug + erased_serde::Serialize { +/// Adding a custom type to BFFH state managenment: +/// +/// 1. Implement `serde`'s [`Serialize`](serde::Serialize) and [`Deserialize`](serde::Deserialize) +/// - `derive()`d instances work just fine, but keep stability over releases in mind. +/// 2. Implement rkyv's [`Serialize`](rkyv::Serialize). +/// 3. Implement TypeOid on your Archived type (i.e. `::Archived`) +/// 4. Implement this +pub trait Value: Any + fmt::Debug + erased_serde::Serialize { /// Initialize `&mut self` from `deserializer` /// /// At the point this is called &mut self is of undefined value but guaranteed to be well @@ -38,9 +45,11 @@ pub trait Value: fmt::Debug + erased_serde::Serialize { -> Result<(), erased_serde::Error>; } erased_serde::serialize_trait_object!(Value); +erased_serde::serialize_trait_object!(SerializeValue); +erased_serde::serialize_trait_object!(DeserializeValue); impl Value for T - where T: fmt::Debug + where T: Any + fmt::Debug + erased_serde::Serialize + for<'de> serde::Deserialize<'de> { @@ -52,44 +61,32 @@ impl Value for T } } -impl Pointee for dyn Value { - type Metadata = DynMetadata; -} - -#[derive(Debug)] -pub struct Entry<'a> { - pub oid: &'a ObjectIdentifier, - pub val: &'a dyn Value, -} - -#[derive(Debug)] -pub struct OwnedEntry { - pub oid: ObjectIdentifier, - pub val: Box, -} - -impl<'a> serde::Serialize for Entry<'a> { +#[repr(transparent)] +pub(super) struct DynVal<'a>(pub &'a dyn SerializeValue); +impl<'a> serde::Serialize for DynVal<'a> { fn serialize(&self, serializer: S) -> Result where S: serde::Serializer { let mut ser = serializer.serialize_map(Some(1))?; - ser.serialize_entry(self.oid, self.val)?; + let oid = self.0.archived_type_oid(); + ser.serialize_entry(oid, self.0)?; ser.end() } } - -impl<'de> serde::Deserialize<'de> for OwnedEntry { +#[repr(transparent)] +pub(super) struct DynOwnedVal(pub Box); +impl<'de> serde::Deserialize<'de> for DynOwnedVal { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de> { - deserializer.deserialize_map(OwnedEntryVisitor) + deserializer.deserialize_map(DynValVisitor) } } -struct OwnedEntryVisitor; +struct DynValVisitor; -impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor { - type Value = OwnedEntry; +impl<'de> serde::de::Visitor<'de> for DynValVisitor { + type Value = DynOwnedVal; fn expecting(&self, formatter: &mut Formatter) -> fmt::Result { write!(formatter, "an one entry map from OID to some value object") @@ -104,10 +101,9 @@ impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor { // Get OID first. That's easy, we know it's the key, we know how to read it. let oid: ObjectIdentifier = map.next_key()? .ok_or(A::Error::missing_field("oid"))?; - let b: Vec = oid.clone().into(); // Get the Value vtable for that OID. Or fail because we don't know that OID, either works. - let valimpl = IMPL_REGISTRY.get(ImplId::from_type_oid(&b)) + let valimpl = IMPL_REGISTRY.get(ImplId::from_type_oid(&oid)) .ok_or(serde::de::Error::invalid_value( serde::de::Unexpected::Other("unknown oid"), &"oid an implementation was registered for", @@ -115,7 +111,7 @@ impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor { // Casting random usize you find on the side of the road as vtable on unchecked pointers. // What could possibly go wrong? >:D - let valbox: MaybeUninit> = unsafe { + let valbox: MaybeUninit> = unsafe { // "recreate" vtable as fat ptr metadata (we literally just cast an `usize` but the // only way to put this usize into that spot is by having a valid vtable cast so it's // probably almost safe) @@ -143,14 +139,14 @@ impl<'de> serde::de::Visitor<'de> for OwnedEntryVisitor { // the game yet. >:D let seed = InitIntoSelf(valbox); let val = map.next_value_seed(seed)?; - Ok(OwnedEntry { oid, val }) + Ok(DynOwnedVal(val)) } } -struct InitIntoSelf(MaybeUninit>); +struct InitIntoSelf(MaybeUninit>); impl<'de> serde::de::DeserializeSeed<'de> for InitIntoSelf { - type Value = Box; + type Value = Box; fn deserialize(mut self, deserializer: D) -> Result where D: serde::Deserializer<'de> @@ -171,39 +167,20 @@ impl<'de> serde::de::DeserializeSeed<'de> for InitIntoSelf { } pub trait TypeOid { - fn get_type_oid() -> ObjectIdentifier; + fn get_type_oid() -> &'static ObjectIdentifier; + fn get_type_name() -> &'static str; + fn get_type_desc() -> &'static str; } -impl TypeOid for Archived { - fn get_type_oid() -> ObjectIdentifier { - ObjectIdentifier::try_from("1.3.6.1.4.1.48398.612.1.1").unwrap() - } -} -impl DeserializeDynOid for Archived - where Archived: for<'a> Deserialize -{ - unsafe fn deserialize_dynoid(&self, deserializer: &mut dyn DynDeserializer, alloc: &mut dyn FnMut(Layout) -> *mut u8) -> Result<*mut (), DynError> { - let ptr = alloc(Layout::new::()).cast::(); - ptr.write(self.deserialize(deserializer)?); - Ok(ptr as *mut ()) - } - - fn deserialize_dynoid_metadata(&self, deserializer: &mut dyn DynDeserializer) -> Result<::Metadata, DynError> { - unsafe { - Ok(core::mem::transmute(ptr_meta::metadata( - core::ptr::null::() as *const dyn SerializeValue - ))) - } - } -} impl SerializeUnsized for dyn SerializeValue { fn serialize_unsized(&self, mut serializer: &mut S) -> Result { self.serialize_dynoid(&mut serializer) .map_err(|e| *e.downcast::().unwrap()) } - fn serialize_metadata(&self, mut serializer: &mut S) -> Result { - self.serialize_metadata(serializer) + fn serialize_metadata(&self, serializer: &mut S) -> Result { + let oid = self.archived_type_oid(); + oid.serialize(serializer) } } @@ -211,7 +188,7 @@ impl SerializeUnsized for dyn Serializ /// Serialize dynamic types by storing an OID alongside pub trait SerializeDynOid { fn serialize_dynoid(&self, serializer: &mut dyn DynSerializer) -> Result; - fn archived_type_oid(&self) -> ObjectIdentifier; + fn archived_type_oid(&self) -> &'static ObjectIdentifier; } impl SerializeDynOid for T @@ -222,12 +199,12 @@ impl SerializeDynOid for T serializer.serialize_value(self) } - fn archived_type_oid(&self) -> ObjectIdentifier { + fn archived_type_oid(&self) -> &'static ObjectIdentifier { Archived::::get_type_oid() } } -trait DeserializeDynOid { +pub trait DeserializeDynOid { unsafe fn deserialize_dynoid( &self, deserializer: &mut dyn DynDeserializer, @@ -243,7 +220,7 @@ trait DeserializeDynOid { #[ptr_meta::pointee] pub trait SerializeValue: Value + SerializeDynOid {} -impl SerializeValue for T +impl SerializeValue for T where T::Archived: RegisteredImpl {} @@ -258,9 +235,7 @@ impl ArchivePointee for dyn DeserializeValue { archived.pointer_metadata() } } -impl DeserializeUnsized for dyn DeserializeValue - where D: Fallible + DynDeserializer -{ +impl DeserializeUnsized for dyn DeserializeValue { unsafe fn deserialize_unsized(&self, mut deserializer: &mut D, mut alloc: impl FnMut(Layout) -> *mut u8 @@ -282,7 +257,7 @@ impl ArchiveUnsized for dyn SerializeValue { unsafe fn resolve_metadata(&self, pos: usize, resolver: Self::MetadataResolver, out: *mut ArchivedMetadata) { let (oid_pos, oid) = out_field!(out.type_oid); let type_oid = self.archived_type_oid(); - type_oid.resolve(oid_pos, resolver, oid); + type_oid.resolve(pos + oid_pos, resolver, oid); } } @@ -297,7 +272,10 @@ impl ArchivedValueMetadata { pub fn vtable(&self) -> usize { IMPL_REGISTRY - .get(ImplId::from_type_oid(&self.type_oid)).expect("Unregistered type oid") + .get(ImplId::from_type_oid(&self.type_oid)).expect(&format!("Unregistered \ + type \ + oid \ + {:?}", self.type_oid)) .vtable } @@ -307,41 +285,58 @@ impl ArchivedValueMetadata { } #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] -struct ImplId<'a> { +pub struct ImplId<'a> { type_oid: &'a [u8], } impl<'a> ImplId<'a> { - fn from_type_oid(type_oid: &'a [u8]) -> Self { + pub fn from_type_oid(type_oid: &'a [u8]) -> Self { Self { type_oid } } } impl ImplId<'static> { fn new() -> Self { - let oid: Vec = T::get_type_oid().into(); Self { - type_oid: oid.leak() + type_oid: &T::get_type_oid() } } } #[derive(Copy, Clone, Debug)] -struct ImplData { +struct ImplData<'a> { pub vtable: usize, - // TODO DebugImpl - // TODO DebugInfo + pub name: &'a str, + pub desc: &'a str, + pub info: ImplDebugInfo, } -impl ImplData { +#[derive(Copy, Clone, Debug)] +#[doc(hidden)] +pub struct ImplDebugInfo { + pub file: &'static str, + pub line: u32, + pub column: u32, +} +macro_rules! debug_info { + () => { + ImplDebugInfo { + file: core::file!(), + line: core::line!(), + column: core::column!(), + } + } +} + +impl ImplData<'_> { pub unsafe fn pointer_metadata(&self) -> DynMetadata { core::mem::transmute(self.vtable) } } -struct ImplEntry<'a> { +pub struct ImplEntry<'a> { id: ImplId<'a>, - data: ImplData, + data: ImplData<'a>, } inventory::collect!(ImplEntry<'static>); @@ -352,13 +347,17 @@ impl ImplEntry<'_> { id: ImplId::new::(), data: ImplData { vtable: ::vtable(), + name: ::get_type_name(), + desc: ::get_type_desc(), + info: ::debug_info(), }, } } } +#[derive(Debug)] struct ImplRegistry { - oid_to_data: HashMap, ImplData>, + oid_to_data: HashMap, ImplData<'static>>, } impl ImplRegistry { @@ -368,6 +367,14 @@ impl ImplRegistry { fn add_entry(&mut self, entry: &'static ImplEntry) { let old_val = self.oid_to_data.insert(entry.id, entry.data); + + if let Some(old) = old_val { + eprintln!("Value impl oid conflict for {:?}", entry.id.type_oid); + eprintln!("Existing impl registered at {}:{}:{}", + old.info.file, old.info.line, old.info.column); + eprintln!("New impl registered at {}:{}:{}", + entry.data.info.file, entry.data.info.line, entry.data.info.column); + } assert!(old_val.is_none()); } @@ -389,101 +396,124 @@ lazy_static::lazy_static! { pub unsafe trait RegisteredImpl { fn vtable() -> usize; + fn debug_info() -> ImplDebugInfo; } -unsafe impl RegisteredImpl for bool { - fn vtable() -> usize { - unsafe { - core::mem::transmute(ptr_meta::metadata( - core::ptr::null::() as *const dyn DeserializeValue - )) - } - } -} -inventory::submit! {ImplEntry::new::()} - -#[archive_dyn(deserialize)] -/// Trait to be implemented by any value in the state map. -/// -/// A value can be any type not having dangling references (with the added -/// restriction that it has to implement `Debug` for debugger QoL). -/// In fact Value *also* needs to implement Hash since BFFH checks if the state -/// is different to before on input and output before updating the resource re. -/// notifying actors and notifys. This dependency is not expressable via -/// supertraits since it is not possible to make Hash into a trait object. -/// To solve this [`State`] uses the [`StateBuilder`] which adds an `Hash` -/// requirement for inputs on [`add`](struct::StateBuilder::add). The hash is -/// being created over all inserted values and then used to check for equality. -/// Note that in addition to collisions, Hash is not guaranteed stable over -/// ordering and will additionally not track overwrites, so if the order of -/// insertions changes or values are set and later overwritten then two equal -/// States can and are likely to have different hashes. -pub trait DynValue: Any + fmt::Debug {} - -macro_rules! valtype { - ( $x:ident, $y:ident ) => { - #[repr(transparent)] - #[derive(Debug, PartialEq, Eq, Hash)] - #[derive(Archive, Serialize, Deserialize)] - #[derive(serde::Serialize, serde::Deserialize)] - #[archive_attr(derive(TypeName, Debug))] - pub struct $x(pub $y); - - #[archive_dyn(deserialize)] - impl DynValue for $x {} - impl DynValue for Archived<$x> {} - - impl Deref for $x { - type Target = $y; - fn deref(&self) -> &Self::Target { - &self.0 - } - } - - impl From<$y> for $x { - fn from(e: $y) -> $x { - Self(e) - } - } - - impl $x { - pub fn new(e: $y) -> Self { - Self(e) +macro_rules! oiddeser { + ( $y:ty, $z:ty ) => { + impl DeserializeDynOid for $y + where $y: for<'a> Deserialize<$z, (dyn DynDeserializer + 'a)> + { + unsafe fn deserialize_dynoid(&self, deserializer: &mut dyn DynDeserializer, alloc: &mut dyn FnMut(Layout) -> *mut u8) -> Result<*mut (), DynError> { + let ptr = alloc(Layout::new::<$z>()).cast::<$z>(); + ptr.write(self.deserialize(deserializer)?); + Ok(ptr as *mut ()) } - pub fn into_inner(self) -> $y { - self.0 + fn deserialize_dynoid_metadata(&self, _: &mut dyn DynDeserializer) -> Result<::Metadata, DynError> { + unsafe { + Ok(core::mem::transmute(ptr_meta::metadata( + core::ptr::null::<$z>() as *const dyn SerializeValue + ))) + } } } } } +macro_rules! oidvalue { + ( $x:ident, $y:ty ) => { + oidvalue! {$x, $y, $y} + }; + ( $x:ident, $y:ty, $z:ty ) => { + oiddeser! {$z, $y} -valtype!(Bool, bool); -valtype!(UInt8, u8); -valtype!(UInt16, u16); -valtype!(UInt32, u32); -valtype!(UInt64, u64); -valtype!(UInt128, u128); -valtype!(Int8, i8); -valtype!(Int16, i16); -valtype!(Int32, i32); -valtype!(Int64, i64); -valtype!(Int128, i128); -valtype!(RString, String); + impl TypeOid for $z { + fn get_type_oid() -> &'static ObjectIdentifier { + &$x + } + + fn get_type_name() -> &'static str { + stringify!($y) + } + + fn get_type_desc() -> &'static str { + "builtin" + } + } + unsafe impl RegisteredImpl for $z { + fn vtable() -> usize { + unsafe { + core::mem::transmute(ptr_meta::metadata( + core::ptr::null::<$z>() as *const dyn DeserializeValue + )) + } + } + fn debug_info() -> ImplDebugInfo { + debug_info!() + } + } + + inventory::submit! {ImplEntry::new::<$z>()} + } +} + +lazy_static::lazy_static! { + pub static ref OID_BOOL: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.1").unwrap() + }; + pub static ref OID_U8: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.2").unwrap() + }; + static ref OID_U16: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.3").unwrap() + }; + static ref OID_U32: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.4").unwrap() + }; + static ref OID_U64: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.5").unwrap() + }; + static ref OID_U128: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.6").unwrap() + }; + static ref OID_I8: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.7").unwrap() + }; + static ref OID_I16: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.8").unwrap() + }; + static ref OID_I32: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.9").unwrap() + }; + static ref OID_I64: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.10").unwrap() + }; + static ref OID_I128: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.11").unwrap() + }; + static ref OID_VEC3U8: ObjectIdentifier = { + ObjectIdentifier::from_str("1.3.6.1.4.1.48398.612.1.13").unwrap() + }; +} +oidvalue!(OID_BOOL, bool); +oidvalue!(OID_U8, u8); +oidvalue!(OID_U16, u16); +oidvalue!(OID_U32, u32); +oidvalue!(OID_U64, u64); +oidvalue!(OID_U128, u128); +oidvalue!(OID_I8, i8); +oidvalue!(OID_I16, i16); +oidvalue!(OID_I32, i32); +oidvalue!(OID_I64, i64); +oidvalue!(OID_I128, i128); #[derive(serde::Serialize, serde::Deserialize)] -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Archive, Serialize, Deserialize)] -#[archive_attr(derive(TypeName, Debug))] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)] +#[archive_attr(derive(TypeName, Debug, serde::Serialize, serde::Deserialize))] pub struct Vec3u8 { pub a: u8, pub b: u8, pub c: u8, } - -#[archive_dyn(deserialize)] -impl DynValue for Vec3u8 {} - -impl DynValue for Archived {} - -#[cfg(test)] -mod tests {} \ No newline at end of file +oidvalue!(OID_VEC3U8, Vec3u8, ArchivedVec3u8); \ No newline at end of file diff --git a/src/varint.rs b/src/varint.rs new file mode 100644 index 0000000..9eb34ee --- /dev/null +++ b/src/varint.rs @@ -0,0 +1,155 @@ +use std::default::Default; +use std::ops::{Deref}; + +pub struct VarUInt { + offset: usize, + bytes: [u8; N], +} + +impl VarUInt { + #[inline(always)] + const fn new(bytes: [u8; N], offset: usize) -> Self { + Self { bytes, offset } + } + + #[inline(always)] + pub fn as_bytes(&self) -> &[u8] { + &self.bytes[self.offset..] + } + + #[inline(always)] + fn as_mut_bytes(&mut self) -> &mut [u8] { + &mut self.bytes[..] + } + + #[inline(always)] + pub const fn into_bytes(self) -> [u8; N] { + self.bytes + } + +} + +impl Default for VarUInt { + fn default() -> Self { + Self::new([0u8; N], N) + } +} + +impl Deref for VarUInt { + type Target = [u8]; + + fn deref(&self) -> &Self::Target { + self.as_bytes() + } +} + +macro_rules! convert_from { + ( $x:ty ) => { + fn from(inp: $x) -> Self { + let mut num = inp; + let mut this = Self::default(); + let bytes = this.as_mut_bytes(); + + let mut more = 0u8; + let mut idx: usize = bytes.len()-1; + + while num > 0x7f { + bytes[idx] = ((num & 0x7f) as u8 | more); + num >>= 7; + more = 0x80; + idx -= 1; + } + bytes[idx] = (num as u8) | more; + + this.offset = idx; + this + } + } +} + +macro_rules! convert_into { + ( $x:ty ) => { + fn into(self) -> $x { + let mut out = 0; + + // [0,1,2,3,4,5,6,7,8,9] + // ^ 0 + // ^offset = 5 + // ^ len = 10 + // ^---------^ # of valid bytes = (len - offset) + // for i in offset..len ⇒ all valid idx + let bytes = self.as_bytes(); + let len = bytes.len(); + let mut shift = 0; + + for neg in 1..=len { + let idx = len-neg; + let val = (bytes[idx] & 0x7f) as $x; + let shifted = val << shift; + out |= shifted; + shift += 7; + } + + out + } + } +} + +macro_rules! impl_convert_from_to { + ( $num:ty, $req:literal, $nt:ident ) => { + pub type $nt = VarUInt<$req>; + impl From<$num> for VarUInt<$req> { + convert_from! { $num } + } + impl Into<$num> for VarUInt<$req> { + convert_into! { $num } + } + } +} + +impl_convert_from_to!(u8, 2, VarU8); +impl_convert_from_to!(u32, 5, VarU32); +impl_convert_from_to!(u64, 10, VarU64); +impl_convert_from_to!(u128, 19, VarU128); + +impl From<&T> for VarUInt + where T: Copy, + VarUInt: From +{ + fn from(t: &T) -> Self { + (*t).into() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_varuint() { + let inp = u64::MAX; + let vi: VarU64 = inp.into(); + println!("Encoded {} into {:?}", inp, vi.as_bytes()); + let outp: u64 = vi.into(); + assert_eq!(inp, outp); + + let inp = 0x80; + let vi: VarUInt<10> = inp.into(); + println!("Encoded {} into {:?}", inp, vi.as_bytes()); + let outp: u64 = vi.into(); + assert_eq!(inp, outp); + } + + #[test] + fn minimal() { + let a = 5u8; + assert_eq!(VarU8::from(a).as_bytes(), &[a]); + let a = 200u8; + assert_eq!(VarU8::from(a).as_bytes(), &[129, 72]); + + let inp = 128; + let vi: VarU32 = inp.into(); + let expected: &[u8] = &[129, 0]; + assert_eq!(vi.as_bytes(), expected) + } +} \ No newline at end of file