diff --git a/Cargo.lock b/Cargo.lock index 29c7780..627caf9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,17 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "ahash" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" +dependencies = [ + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "ahash" version = "0.8.10" @@ -114,6 +125,15 @@ dependencies = [ "syn 2.0.51", ] +[[package]] +name = "atoi" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c57d12312ff59c811c0643f4d80830505833c9ffaebd193d819392b265be8e" +dependencies = [ + "num-traits", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -642,6 +662,12 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -664,6 +690,12 @@ dependencies = [ "vsimd", ] +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + [[package]] name = "bitflags" version = "1.3.2" @@ -675,6 +707,9 @@ name = "bitflags" version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +dependencies = [ + "serde", +] [[package]] name = "block-buffer" @@ -751,6 +786,58 @@ dependencies = [ "windows-targets 0.52.3", ] +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "config" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23738e11972c7643e4ec947840fc463b6a571afcd3e735bdfce7d03c7a784aca" +dependencies = [ + "async-trait", + "json5", + "lazy_static", + "nom", + "pathdiff", + "ron", + "rust-ini", + "serde", + "serde_json", + "toml", + "yaml-rust", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + [[package]] name = "core-base" version = "0.1.0" @@ -841,6 +928,49 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "core-omnius" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "base64 0.21.7", + "bitflags 2.4.2", + "chrono", + "ciborium", + "config", + "core-base", + "crc", + "ed25519-dalek", + "fast-socks5", + "futures", + "futures-util", + "hex", + "nom", + "once_cell", + "pin-utils", + "rand", + "rand_chacha", + "rand_core", + "ring 0.16.20", + "serde", + "serde_json", + "serial_test", + "sha3", + "sqlx", + "tempfile", + "testcontainers", + "testresult", + "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", + "tracing-subscriber", + "urlencoding", + "uuid", +] + [[package]] name = "core-testkit" version = "0.1.0" @@ -863,6 +993,21 @@ dependencies = [ "libc", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32c" version = "0.6.5" @@ -881,6 +1026,27 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + [[package]] name = "crypto-common" version = "0.1.6" @@ -891,6 +1057,34 @@ dependencies = [ "typenum", ] +[[package]] +name = "curve25519-dalek" +version = "4.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "platforms", + "rustc_version", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.51", +] + [[package]] name = "darling" version = "0.13.4" @@ -936,7 +1130,17 @@ dependencies = [ "hashbrown 0.14.3", "lock_api", "once_cell", - "parking_lot_core", + "parking_lot_core 0.9.9", +] + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "zeroize", ] [[package]] @@ -959,6 +1163,64 @@ dependencies = [ "subtle", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "dlv-list" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0688c2a7f92e427f44895cd63841bff7b29f8d7a1648b9e7e07a4a365b2e1257" + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "ed25519" +version = "2.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" +dependencies = [ + "pkcs8", + "serde", + "signature", +] + +[[package]] +name = "ed25519-dalek" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" +dependencies = [ + "curve25519-dalek", + "ed25519", + "rand_core", + "serde", + "sha2", + "subtle", + "zeroize", +] + [[package]] name = "either" version = "1.10.0" @@ -990,18 +1252,44 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + [[package]] name = "fallible-iterator" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fast-socks5" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f89f36d4ee12370d30d57b16c7e190950a1a916e7dbbb5fd5a412f5ef913fe84" +dependencies = [ + "anyhow", + "async-trait", + "log", + "thiserror", + "tokio", + "tokio-stream", +] + [[package]] name = "fastrand" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +[[package]] +name = "fiat-crypto" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38793c55593b33412e3ae40c2c9781ffaa6f438f6f8c10f24e71846fbd7ae01e" + [[package]] name = "finl_unicode" version = "1.2.0" @@ -1090,6 +1378,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a604f7a68fbf8103337523b1fadc8ade7361ee3f112f7c680ad179651616aed5" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot 0.11.2", +] + [[package]] name = "futures-io" version = "0.3.30" @@ -1228,11 +1527,24 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash 0.7.8", +] [[package]] name = "hashbrown" @@ -1240,10 +1552,28 @@ version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ - "ahash", + "ahash 0.8.10", "allocator-api2", ] +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.3", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "hermit-abi" version = "0.3.8" @@ -1256,6 +1586,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -1423,6 +1762,15 @@ dependencies = [ "hashbrown 0.14.3", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -1453,6 +1801,17 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "json5" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" +dependencies = [ + "pest", + "pest_derive", + "serde", +] + [[package]] name = "jsonwebtoken" version = "9.3.0" @@ -1477,6 +1836,15 @@ dependencies = [ "mutate_once", ] +[[package]] +name = "keccak" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -1489,6 +1857,22 @@ version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.4.2", + "libc", +] + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + [[package]] name = "linux-raw-sys" version = "0.4.13" @@ -1558,6 +1942,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.2" @@ -1602,6 +1992,16 @@ dependencies = [ "tempfile", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -1716,6 +2116,16 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "ordered-multimap" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a" +dependencies = [ + "dlv-list", + "hashbrown 0.12.3", +] + [[package]] name = "outref" version = "0.5.1" @@ -1728,6 +2138,17 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -1735,7 +2156,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", ] [[package]] @@ -1746,11 +2181,23 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "pem" version = "3.0.4" @@ -1767,6 +2214,51 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pest" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26293c9193fbca7b1a3bf9b79dc1e388e927e6cacaa78b4a3ab705a1d3d41459" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ec22af7d3fb470a85dd2ca96b7c577a1eb4ef6f1683a9fe9a8c16e136c04687" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.51", +] + +[[package]] +name = "pest_meta" +version = "2.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7a240022f37c361ec1878d646fc5b7d7c4d28d5946e1a80ad5a7a4f4ca0bdcd" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + [[package]] name = "phf" version = "0.11.2" @@ -1837,12 +2329,28 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +[[package]] +name = "platforms" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23d408679286588f4d4644f965003d056e3dd5abcaaa938116871d7ce2fee7" + [[package]] name = "postgres-protocol" version = "0.6.6" @@ -1965,6 +2473,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -1974,6 +2491,17 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_users" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.10.3" @@ -2096,6 +2624,27 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "ron" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" +dependencies = [ + "base64 0.13.1", + "bitflags 1.3.2", + "serde", +] + +[[package]] +name = "rust-ini" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6d5f2436026b4f6e79dc829837d467cc7e9a55ee40e750d716713540715a2df" +dependencies = [ + "cfg-if", + "ordered-multimap", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2124,6 +2673,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.20.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b80e3dec595989ea8510028f30c408a4630db12c9cbb8de34203b89d6577e99" +dependencies = [ + "log", + "ring 0.16.20", + "sct", + "webpki", +] + [[package]] name = "rustls" version = "0.21.10" @@ -2375,7 +2936,7 @@ dependencies = [ "futures", "lazy_static", "log", - "parking_lot", + "parking_lot 0.12.1", "serial_test_derive", ] @@ -2412,6 +2973,16 @@ dependencies = [ "digest", ] +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2430,6 +3001,15 @@ dependencies = [ "libc", ] +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "rand_core", +] + [[package]] name = "simple_asn1" version = "0.6.2" @@ -2485,6 +3065,122 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "sqlformat" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +dependencies = [ + "itertools", + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8de3b03a925878ed54a954f621e64bf55a3c1bd29652d0d1a17830405350188" +dependencies = [ + "sqlx-core", + "sqlx-macros", +] + +[[package]] +name = "sqlx-core" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029" +dependencies = [ + "ahash 0.7.8", + "atoi", + "base64 0.13.1", + "bitflags 1.3.2", + "byteorder", + "bytes", + "chrono", + "crc", + "crossbeam-queue", + "dirs", + "dotenvy", + "either", + "event-listener", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-util", + "hashlink", + "hex", + "hkdf", + "hmac", + "indexmap 1.9.3", + "itoa", + "libc", + "log", + "md-5", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "rand", + "rustls 0.20.9", + "rustls-pemfile 1.0.4", + "serde", + "serde_json", + "sha1", + "sha2", + "smallvec", + "sqlformat", + "sqlx-rt", + "stringprep", + "thiserror", + "tokio-stream", + "url", + "webpki-roots", + "whoami", +] + +[[package]] +name = "sqlx-macros" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9966e64ae989e7e575b19d7265cb79d7fc3cbbdf179835cb0d716f294c2049c9" +dependencies = [ + "dotenvy", + "either", + "heck", + "once_cell", + "proc-macro2", + "quote", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-rt", + "syn 1.0.109", + "url", +] + +[[package]] +name = "sqlx-rt" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804d3f245f894e61b1e6263c84b23ca675d96753b5abfd5cc8597d86806e8024" +dependencies = [ + "once_cell", + "tokio", + "tokio-rustls 0.23.4", +] + [[package]] name = "stringprep" version = "0.1.4" @@ -2679,7 +3375,7 @@ dependencies = [ "libc", "mio", "num_cpus", - "parking_lot", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", "socket2", @@ -2731,7 +3427,7 @@ dependencies = [ "futures-channel", "futures-util", "log", - "parking_lot", + "parking_lot 0.12.1", "percent-encoding", "phf", "pin-project-lite", @@ -2744,6 +3440,17 @@ dependencies = [ "whoami", ] +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls 0.20.9", + "tokio", + "webpki", +] + [[package]] name = "tokio-rustls" version = "0.24.1" @@ -2794,6 +3501,15 @@ dependencies = [ "tracing", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "tonic" version = "0.11.0" @@ -2956,6 +3672,12 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + [[package]] name = "unicase" version = "2.7.0" @@ -2986,6 +3708,18 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-segmentation" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" + +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "untrusted" version = "0.7.1" @@ -3153,6 +3887,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.8", + "untrusted 0.9.0", +] + +[[package]] +name = "webpki-roots" +version = "0.22.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" +dependencies = [ + "webpki", +] + [[package]] name = "whoami" version = "1.4.1" @@ -3342,6 +4095,15 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4" +[[package]] +name = "yaml-rust" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "zerocopy" version = "0.7.32" diff --git a/Cargo.toml b/Cargo.toml index 0b4b76e..c4e160d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "modules/cloud", "modules/image", "modules/migration", + "modules/omnius", "modules/testkit", ] resolver = "2" @@ -17,6 +18,7 @@ core-base = { path = "./modules/base" } core-cloud = { path = "./modules/cloud", features = ["aws"] } core-image = { path = "./modules/image" } core-migration = { path = "./modules/migration", features = ["postgres"] } +core-omnius = { path = "./modules/omnius" } core-testkit = { path = "./modules/testkit" } aws-config = "0.56.1" @@ -74,3 +76,17 @@ serial_test = "2.0.0" proc-macro2 = "1.0.70" reqwest = { version = "0.11.23", features = ["json"] } testresult = "0.4.0" +base64 = "0.21.7" +ciborium = "0.2.2" +bitflags = { version = "2.4.2", features = ["serde"] } +tempfile = "3.10.0" +crc = "3.0.1" +sha3 = "0.10.8" +ed25519-dalek = { version = "2.1.0", features = ["rand_core", "serde"] } +rand_core = "0.6.4" +nom = "7.1.3" +fast-socks5 = "0.9.2" +futures = "0.3.30" +futures-util = "0.3.28" +local-ip-address = "0.5.7" +pin-utils = "0.1.0" diff --git a/modules/omnius/Cargo.toml b/modules/omnius/Cargo.toml new file mode 100644 index 0000000..35540cd --- /dev/null +++ b/modules/omnius/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "core-omnius" +version = "0.1.0" +edition = { workspace = true } +authors = { workspace = true } + +[features] +stable-test = [] + +[dependencies] +core-base = { workspace = true } + +anyhow = { workspace = true } +async-trait = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +tokio = { workspace = true } +tokio-util = { workspace = true } +tokio-stream = { workspace = true } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +uuid = { workspace = true } +sqlx = { workspace = true } +config = { workspace = true } +ring = { workspace = true } +hex = { workspace = true } +urlencoding = { workspace = true } +thiserror = { workspace = true } +once_cell = { workspace = true } +base64 = { workspace = true } +futures = { workspace = true } +futures-util = { workspace = true } +serial_test = { workspace = true } +pin-utils = { workspace = true } +nom = { workspace = true } +fast-socks5 = { workspace = true } +ed25519-dalek = { workspace = true } +rand_core = { workspace = true } +sha3 = { workspace = true } +ciborium = { workspace = true } +bitflags = { workspace = true } +tempfile = { workspace = true } +crc = { workspace = true } +chrono = { workspace = true } +rand = { workspace = true } +rand_chacha = { workspace = true } + +[dev-dependencies] +testcontainers = { workspace = true } +testresult = { workspace = true } diff --git a/modules/omnius/src/lib.rs b/modules/omnius/src/lib.rs new file mode 100644 index 0000000..a8dcbc0 --- /dev/null +++ b/modules/omnius/src/lib.rs @@ -0,0 +1,5 @@ +mod model; +mod service; + +pub use model::*; +pub use service::*; diff --git a/modules/omnius/src/model.rs b/modules/omnius/src/model.rs new file mode 100644 index 0000000..5dadb52 --- /dev/null +++ b/modules/omnius/src/model.rs @@ -0,0 +1,7 @@ +mod omni_address; +mod omni_hash; +mod omni_signature; + +pub use omni_address::*; +pub use omni_hash::*; +pub use omni_signature::*; diff --git a/modules/omnius/src/model/omni_address.rs b/modules/omnius/src/model/omni_address.rs new file mode 100644 index 0000000..44bf3bd --- /dev/null +++ b/modules/omnius/src/model/omni_address.rs @@ -0,0 +1,51 @@ +use std::fmt; + +use nom::bytes::complete::{is_not, tag}; +use nom::character::complete::{char, multispace0}; +use nom::sequence::delimited; +use nom::IResult; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct OmniAddress(String); + +impl OmniAddress { + pub fn new(value: &str) -> OmniAddress { + OmniAddress(value.to_owned()) + } + + pub fn parse_tcp(&self) -> anyhow::Result { + let (_, addr) = Self::parse_tcp_sub(&self.0).map_err(|e| e.to_owned())?; + Ok(addr.to_string()) + } + + fn parse_tcp_sub(v: &str) -> IResult<&str, &str> { + let (v, _) = tag("tcp")(v)?; + let (v, addr) = delimited(char('('), delimited(multispace0, is_not(")"), multispace0), char(')'))(v)?; + Ok((v, addr)) + } +} + +impl fmt::Display for OmniAddress { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.0) + } +} + +impl From for OmniAddress { + fn from(value: String) -> Self { + Self::new(value.as_str()) + } +} + +#[cfg(test)] +mod tests { + use crate::model::OmniAddress; + + #[tokio::test] + #[ignore] + async fn add_port_mapping_test() { + let addr = OmniAddress::new("tcp(127.0.0.1:8000)"); + println!("{:?}", addr.parse_tcp()); + } +} diff --git a/modules/omnius/src/model/omni_hash.rs b/modules/omnius/src/model/omni_hash.rs new file mode 100644 index 0000000..2cdb36a --- /dev/null +++ b/modules/omnius/src/model/omni_hash.rs @@ -0,0 +1,30 @@ +use std::fmt; + +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum OmniHashAlgorithmType { + Sha3_256, +} + +impl fmt::Display for OmniHashAlgorithmType { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let typ = match self { + OmniHashAlgorithmType::Sha3_256 => "sha3-256", + }; + + write!(f, "{}", typ) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct OmniHash { + pub typ: OmniHashAlgorithmType, + pub value: Vec, +} + +impl fmt::Display for OmniHash { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}:{}", self.typ, hex::encode(&self.value)) + } +} diff --git a/modules/omnius/src/model/omni_signature.rs b/modules/omnius/src/model/omni_signature.rs new file mode 100644 index 0000000..7aa795a --- /dev/null +++ b/modules/omnius/src/model/omni_signature.rs @@ -0,0 +1,138 @@ +use std::fmt; + +use base64::{engine::general_purpose::URL_SAFE_NO_PAD as BASE64, Engine}; +use ed25519_dalek::Signer; +use rand_core::OsRng; +use serde::{Deserialize, Serialize}; +use sha3::{Digest, Sha3_256}; + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum OmniSignType { + Ed25519, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct OmniSigner { + typ: OmniSignType, + name: String, + key: Vec, +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct OmniSignature { + typ: OmniSignType, + name: String, + public_key: Vec, + value: Vec, +} + +impl OmniSigner { + pub fn new(typ: &OmniSignType, name: &str) -> Self { + match typ { + OmniSignType::Ed25519 => { + let signing_key = ed25519_dalek::SigningKey::generate(&mut OsRng); + + let typ = typ.clone(); + let name = name.to_string(); + let key = signing_key.to_keypair_bytes().to_vec(); + Self { typ, name, key } + } + } + } + + pub fn sign(&self, msg: &[u8]) -> anyhow::Result { + match self.typ { + OmniSignType::Ed25519 => { + let signing_key_bytes = self.key.as_slice(); + if signing_key_bytes.len() != ed25519_dalek::KEYPAIR_LENGTH { + anyhow::bail!("Invalid signing_key length"); + } + let signing_key_bytes = <&[u8; ed25519_dalek::KEYPAIR_LENGTH]>::try_from(signing_key_bytes)?; + + let signing_key = ed25519_dalek::SigningKey::from_keypair_bytes(signing_key_bytes)?; + + let typ = self.typ.clone(); + let name = self.name.clone(); + let public_key = signing_key.verifying_key().to_bytes().to_vec(); + let value = signing_key.sign(msg).to_vec(); + Ok(OmniSignature { + typ, + name, + public_key, + value, + }) + } + } + } +} + +impl fmt::Display for OmniSigner { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.typ { + OmniSignType::Ed25519 => { + let signing_key_bytes: [u8; ed25519_dalek::KEYPAIR_LENGTH] = self.key.clone().try_into().map_err(|_| fmt::Error)?; + + let signing_key = ed25519_dalek::SigningKey::from_keypair_bytes(&signing_key_bytes).map_err(|_| fmt::Error)?; + let public_key = signing_key.verifying_key().to_bytes(); + + let mut hasher = Sha3_256::new(); + hasher.update(public_key); + let hash = hasher.finalize(); + + write!(f, "{}@{}", self.name, BASE64.encode(hash)) + } + } + } +} + +impl OmniSignature { + pub fn verify(&self, msg: &[u8]) -> anyhow::Result<()> { + match self.typ { + OmniSignType::Ed25519 => { + let verifying_key_bytes: [u8; ed25519_dalek::PUBLIC_KEY_LENGTH] = self + .public_key + .clone() + .try_into() + .map_err(|_| anyhow::anyhow!("Invalid verifying_key length"))?; + let signature_bytes: [u8; ed25519_dalek::SIGNATURE_LENGTH] = + self.value.clone().try_into().map_err(|_| anyhow::anyhow!("Invalid signature length"))?; + + let verifying_key = ed25519_dalek::VerifyingKey::from_bytes(&verifying_key_bytes)?; + let signature = ed25519_dalek::Signature::from_bytes(&signature_bytes); + Ok(verifying_key.verify_strict(msg, &signature)?) + } + } + } +} + +impl fmt::Display for OmniSignature { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.typ { + OmniSignType::Ed25519 => { + let mut hasher = Sha3_256::new(); + hasher.update(&self.public_key); + let hash = hasher.finalize(); + + write!(f, "{}@{}", self.name, BASE64.encode(hash)) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::{OmniSignType, OmniSigner}; + + #[tokio::test] + #[ignore] + async fn simple_test() { + let signer = OmniSigner::new(&OmniSignType::Ed25519, "test_user"); + let signature = signer.sign(b"test").unwrap(); + + println!("{}", signer); + println!("{}", signature); + + assert!(signature.verify(b"test").is_ok()); + assert!(signature.verify(b"test_err").is_err()); + } +} diff --git a/modules/omnius/src/service.rs b/modules/omnius/src/service.rs new file mode 100644 index 0000000..0ed29a6 --- /dev/null +++ b/modules/omnius/src/service.rs @@ -0,0 +1,4 @@ +mod connection; +mod util; + +pub use connection::*; diff --git a/modules/omnius/src/service/connection.rs b/modules/omnius/src/service/connection.rs new file mode 100644 index 0000000..7ef1b94 --- /dev/null +++ b/modules/omnius/src/service/connection.rs @@ -0,0 +1,3 @@ +mod stream; + +pub use stream::*; diff --git a/modules/omnius/src/service/connection/stream.rs b/modules/omnius/src/service/connection/stream.rs new file mode 100644 index 0000000..af5f7e1 --- /dev/null +++ b/modules/omnius/src/service/connection/stream.rs @@ -0,0 +1,139 @@ +use std::sync::Arc; + +use anyhow::Context as _; +use async_trait::async_trait; +use futures_util::SinkExt; +use serde::{de::DeserializeOwned, Deserialize, Serialize}; +use tokio::{ + io::{AsyncRead, AsyncWrite}, + sync::Mutex as TokioMutex, +}; +use tokio_stream::StreamExt; +use tokio_util::bytes::Bytes; + +use crate::service::util::Cbor; + +#[derive(Clone)] +pub struct FramedStream { + pub reader: Arc>, + pub writer: Arc>, +} + +impl FramedStream { + pub fn new(reader: R, writer: W) -> Self + where + R: AsyncRead + Send + Sync + Unpin + 'static, + W: AsyncWrite + Send + Sync + Unpin + 'static, + { + let reader = Arc::new(TokioMutex::new(FramedReader::new(reader))); + let writer = Arc::new(TokioMutex::new(FramedWriter::new(writer))); + Self { reader, writer } + } +} + +#[async_trait] +pub trait AsyncSend { + async fn send(&mut self, buffer: Bytes) -> anyhow::Result<()>; +} +#[async_trait] +pub trait AsyncRecv { + async fn recv(&mut self) -> anyhow::Result; +} + +#[async_trait] +pub trait AsyncSendExt: AsyncSend { + async fn send_message(&mut self, item: T) -> anyhow::Result<()>; +} + +#[async_trait] +pub trait AsyncRecvExt: AsyncRecv { + async fn recv_message Deserialize<'a>>(&mut self) -> anyhow::Result; +} + +struct FramedReader +where + T: AsyncRead + Send + Sync + Unpin, +{ + framed: tokio_util::codec::FramedRead, +} + +impl FramedReader +where + T: AsyncRead + Send + Sync + Unpin, +{ + pub fn new(stream: T) -> Self { + let codec = tokio_util::codec::LengthDelimitedCodec::builder() + .max_frame_length(1024 * 1024 * 64) + .little_endian() + .new_codec(); + let framed = tokio_util::codec::FramedRead::new(stream, codec); + Self { framed } + } +} + +struct FramedWriter +where + T: AsyncWrite + Send + Sync + Unpin, +{ + framed: tokio_util::codec::FramedWrite, +} + +impl FramedWriter +where + T: AsyncWrite + Send + Sync + Unpin, +{ + pub fn new(stream: T) -> Self { + let codec = tokio_util::codec::LengthDelimitedCodec::builder() + .max_frame_length(1024 * 1024 * 64) + .little_endian() + .new_codec(); + let framed = tokio_util::codec::FramedWrite::new(stream, codec); + Self { framed } + } +} + +#[async_trait] +impl AsyncSend for FramedWriter +where + T: AsyncWrite + Send + Sync + Unpin, +{ + async fn send(&mut self, buffer: Bytes) -> anyhow::Result<()> { + self.framed.send(buffer).await.with_context(|| "Failed to send")?; + Ok(()) + } +} + +#[async_trait] +impl AsyncSendExt for T +where + T: ?Sized + Send + Sync + Unpin, +{ + async fn send_message(&mut self, item: TItem) -> anyhow::Result<()> { + let b = Cbor::serialize(item)?; + self.send(b).await?; + Ok(()) + } +} + +#[async_trait] +impl AsyncRecv for FramedReader +where + T: AsyncRead + Send + Sync + Unpin, +{ + async fn recv(&mut self) -> anyhow::Result { + let buffer = self.framed.next().await.ok_or(anyhow::anyhow!("Stream ended"))??.freeze(); + Ok(buffer) + } +} + +#[async_trait] +impl AsyncRecvExt for T +where + T: ?Sized + Send + Sync + Unpin, +{ + async fn recv_message(&mut self) -> anyhow::Result { + let b = self.recv().await?; + let item = Cbor::deserialize(b)?; + Ok(item) + } +} diff --git a/modules/omnius/src/service/util.rs b/modules/omnius/src/service/util.rs new file mode 100644 index 0000000..c866d7d --- /dev/null +++ b/modules/omnius/src/service/util.rs @@ -0,0 +1,3 @@ +mod cbor; + +pub use cbor::*; diff --git a/modules/omnius/src/service/util/cbor.rs b/modules/omnius/src/service/util/cbor.rs new file mode 100644 index 0000000..dec8a0b --- /dev/null +++ b/modules/omnius/src/service/util/cbor.rs @@ -0,0 +1,20 @@ +use serde::{de::DeserializeOwned, Serialize}; +use tokio_util::bytes::{Buf, BufMut, Bytes, BytesMut}; + +pub struct Cbor; + +impl Cbor { + pub fn serialize(item: T) -> anyhow::Result { + let buffer = BytesMut::new(); + let mut writer = buffer.writer(); + ciborium::ser::into_writer(&item, &mut writer)?; + let buffer = writer.into_inner().freeze(); + Ok(buffer) + } + + pub fn deserialize(b: Bytes) -> anyhow::Result { + let mut reader = b.reader(); + let item = ciborium::de::from_reader(&mut reader)?; + Ok(item) + } +}