commit c22db9f7777dba8c7213ac40688cec0767bbf164 Author: richnicky2005 Date: Mon Jul 7 21:05:14 2025 -0400 Initial commit diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..14fce56 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,5772 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "acto" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a026259da4f1a13b4af60cda453c392de64c58c12d239c560923e0382f42f2b9" +dependencies = [ + "parking_lot", + "pin-project-lite", + "rustc_version", + "smol_str", + "tokio", + "tracing", +] + +[[package]] +name = "addr2line" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "bytes", + "crypto-common", + "generic-array", +] + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anstream" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +dependencies = [ + "anstyle", + "windows-sys 0.52.0", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "arrayref" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" + +[[package]] +name = "arrayvec" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" + +[[package]] +name = "asn1-rs" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ad1373757efa0f70ec53939aabc7152e1591cb485208052993070ac8d2429d" +dependencies = [ + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7378575ff571966e99a744addeff0bff98b8ada0dedf1956d59e634db95eaac1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "async-trait" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "attohttpc" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d9a9bf8b79a749ee0b911b91b671cc2b6c670bdbc7e3dfd537576ddc94bb2a2" +dependencies = [ + "http 0.2.12", + "log", + "url", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backoff" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62ddb9cb1ec0a098ad4bbf9344d0713fa193ae1a80af55febcff2627b6a00c1" +dependencies = [ + "getrandom", + "instant", + "rand", +] + +[[package]] +name = "backtrace" +version = "0.3.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bao-tree" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f7a89a8ee5889d2593ae422ce6e1bb03e48a0e8a16e4fa0882dfcbe7e182ef" +dependencies = [ + "bytes", + "futures-lite 2.3.0", + "genawaiter", + "iroh-blake3", + "iroh-io", + "positioned-io", + "range-collections", + "self_cell", + "smallvec", +] + +[[package]] +name = "base16ct" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64ct" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" + +[[package]] +name = "binary-merge" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597bb81c80a54b6a4381b23faba8d7774b144c94cbd1d6fe3f1329bd776554ab" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bounded-integer" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78a6932c88f1d2c29533a3b8a5f5a2f84cc19c3339b431677c3160c5c2e6ca85" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +dependencies = [ + "serde", +] + +[[package]] +name = "cc" +version = "1.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" + +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + +[[package]] +name = "chacha20" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits", + "serde", + "wasm-bindgen", + "windows-targets 0.52.5", +] + +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", + "zeroize", +] + +[[package]] +name = "clap" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "cobs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "console" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +dependencies = [ + "encode_unicode", + "lazy_static", + "libc", + "unicode-width", + "windows-sys 0.52.0", +] + +[[package]] +name = "const-oid" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "constant_time_eq" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" + +[[package]] +name = "cordyceps" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a" +dependencies = [ + "loom", + "tracing", +] + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +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 = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crypto-bigint" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" +dependencies = [ + "generic-array", + "rand_core", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "rand_core", + "typenum", +] + +[[package]] +name = "crypto_box" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16182b4f39a82ec8a6851155cc4c0cda3065bb1db33651726a29e1951de0f009" +dependencies = [ + "aead", + "chacha20", + "crypto_secretbox", + "curve25519-dalek", + "salsa20", + "serdect", + "subtle", + "zeroize", +] + +[[package]] +name = "crypto_secretbox" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d6cf87adf719ddf43a805e92c6870a531aedda35ff640442cbaf8674e141e1" +dependencies = [ + "aead", + "chacha20", + "cipher", + "generic-array", + "poly1305", + "salsa20", + "subtle", + "zeroize", +] + +[[package]] +name = "curve25519-dalek" +version = "4.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" +dependencies = [ + "cfg-if", + "cpufeatures", + "curve25519-dalek-derive", + "digest", + "fiat-crypto", + "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.68", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + +[[package]] +name = "der" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +dependencies = [ + "const-oid", + "der_derive", + "zeroize", +] + +[[package]] +name = "der-parser" +version = "9.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cd0a5c643689626bec213c4d8bd4d96acc8ffdb4ad4bb6bc16abf27d5f4b553" +dependencies = [ + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", +] + +[[package]] +name = "der_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive_more" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05" +dependencies = [ + "derive_more-impl", +] + +[[package]] +name = "derive_more-impl" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", + "unicode-xid", +] + +[[package]] +name = "diatomic-waker" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c" + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "const-oid", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "dlopen2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b4f5f101177ff01b8ec4ecc81eead416a8aa42819a2869311b3420fa114ffa" +dependencies = [ + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "document-features" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95249b50c6c185bee49034bcb378a49dc2b5dff0be90ff6616d31d64febab05d" +dependencies = [ + "litrs", +] + +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "duct" +version = "0.13.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" +dependencies = [ + "libc", + "once_cell", + "os_pipe", + "shared_child", +] + +[[package]] +name = "dyn-clone" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" + +[[package]] +name = "ecdsa" +version = "0.16.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" +dependencies = [ + "der", + "digest", + "elliptic-curve", + "rfc6979", + "signature", + "spki", +] + +[[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 = "educe" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0042ff8246a363dbe77d2ceedb073339e85a804b9a47636c6e016a9a32c05f" +dependencies = [ + "enum-ordinalize", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "elliptic-curve" +version = "0.13.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" +dependencies = [ + "base16ct", + "crypto-bigint", + "digest", + "ff", + "generic-array", + "group", + "pkcs8", + "rand_core", + "sec1", + "subtle", + "zeroize", +] + +[[package]] +name = "embedded-io" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced" + +[[package]] +name = "encode_unicode" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "enum-ordinalize" +version = "3.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee" +dependencies = [ + "num-bigint", + "num-traits", + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "enumflags2" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "erased-serde" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c138974f9d5e7fe373eb04df7cae98833802ae4b11c24ac7039a21d5af4b26c" +dependencies = [ + "serde", +] + +[[package]] +name = "erased_set" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76a5aa24577083f8190ad401e376b55887c7cd9083ae95d83ceec5d28ea78125" + +[[package]] +name = "errno" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3492acde4c3fc54c845eaab3eed8bd00c7a7d881f78bfc801e43a93dec1331ae" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" +dependencies = [ + "event-listener 5.4.0", + "pin-project-lite", +] + +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "ff" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" +dependencies = [ + "rand_core", + "subtle", +] + +[[package]] +name = "fiat-crypto" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" + +[[package]] +name = "filetime" +version = "0.2.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", +] + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fsevent-sys" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +dependencies = [ + "libc", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-buffered" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe940397c8b744b9c2c974791c2c08bca2c3242ce0290393249e98f215a00472" +dependencies = [ + "cordyceps", + "diatomic-waker", + "futures-core", + "pin-project-lite", + "spin", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-concurrency" +version = "7.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b14ac911e85d57c5ea6eef76d7b4d4a3177ecd15f4bea2e61927e9e3823e19f" +dependencies = [ + "bitvec", + "futures-buffered", + "futures-core", + "futures-lite 1.13.0", + "pin-project", + "slab", + "smallvec", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.1.0", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "genawaiter" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" +dependencies = [ + "futures-core", + "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 1.0.109", +] + +[[package]] +name = "generator" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" +dependencies = [ + "cc", + "cfg-if", + "libc", + "log", + "rustversion", + "windows 0.61.3", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", + "zeroize", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "governor" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" +dependencies = [ + "cfg-if", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand", + "smallvec", + "spinning_top", +] + +[[package]] +name = "group" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" +dependencies = [ + "ff", + "rand_core", + "subtle", +] + +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.12", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "h2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9421a676d1b147b16b82c9225157dc629087ef8ec4d5e2960f9437a90dac0a5" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "hashlink" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "headers" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" +dependencies = [ + "base64 0.21.7", + "bytes", + "headers-core", + "http 0.2.12", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" +dependencies = [ + "http 0.2.12", +] + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hickory-proto" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07698b8420e2f0d6447a436ba999ec85d8fbf2a398bbd737b82cac4a2e96e512" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-proto" +version = "0.25.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8270a1857fb962b9914aafd46a89a187a4e63d0eb4190c327e7c7b8256a2d055" +dependencies = [ + "async-recursion", + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.5.0", + "ipnet", + "once_cell", + "rand", + "thiserror", + "time", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.25.0-alpha.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c110355b5703070d9e29c344d79818a7cde3de9c27fc35750defea6074b0ad" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto 0.25.0-alpha.2", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "hmac-sha1" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b05da5b9e5d4720bfb691eebb2b9d42da3570745da71eac8a1f5bb7e59aab88" +dependencies = [ + "hmac", + "sha1", +] + +[[package]] +name = "hmac-sha256" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3688e69b38018fec1557254f64c8dc2cc8ec502890182f395dbb0aa997aa5735" + +[[package]] +name = "hostname" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c731c3e10504cc8ed35cfe2f1db4c9274c3d35fa486e3b31df46f068ef3e867" +dependencies = [ + "libc", + "match_cfg", + "winapi", +] + +[[package]] +name = "hostname-validator" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f558a64ac9af88b5ba400d99b579451af0d39c6d360980045b91aac966d705e2" + +[[package]] +name = "http" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http 0.2.12", + "pin-project-lite", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http 1.1.0", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "0.14.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.3.26", + "http 0.2.12", + "http-body 0.4.6", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4fe55fb7a772d59a5ff1dfbff4fe0258d19b89fec4b233e75d35d5d2316badc" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.10", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper 1.4.0", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.4.0", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core 0.52.0", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "igd-next" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b0d7d4541def58a37bf8efc559683f21edce7c82f0d866c93ac21f7e098f93" +dependencies = [ + "async-trait", + "attohttpc", + "bytes", + "futures", + "http 1.1.0", + "http-body-util", + "hyper 1.4.0", + "hyper-util", + "log", + "rand", + "tokio", + "url", + "xmltree", +] + +[[package]] +name = "indexmap" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", +] + +[[package]] +name = "indicatif" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +dependencies = [ + "console", + "instant", + "number_prefix", + "portable-atomic", + "unicode-width", +] + +[[package]] +name = "inotify" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +dependencies = [ + "bitflags 1.3.2", + "inotify-sys", + "libc", +] + +[[package]] +name = "inotify-sys" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" +dependencies = [ + "libc", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "inplace-vec-builder" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf64c2edc8226891a71f127587a2861b132d2b942310843814d5001d99a1d307" +dependencies = [ + "smallvec", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2", + "widestring", + "windows-sys 0.48.0", + "winreg 0.50.0", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "iroh" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47cbc2cde0ac94db88a2f0442cf0d18f1f59403cc21c81f7994a6287e78e60dd" +dependencies = [ + "anyhow", + "async-channel", + "bao-tree", + "bytes", + "derive_more", + "futures-buffered", + "futures-lite 2.3.0", + "futures-util", + "genawaiter", + "hex", + "iroh-base", + "iroh-blobs", + "iroh-docs", + "iroh-gossip", + "iroh-io", + "iroh-metrics", + "iroh-net", + "iroh-quinn", + "iroh-router", + "nested_enum_utils", + "num_cpus", + "parking_lot", + "portable-atomic", + "postcard", + "quic-rpc", + "quic-rpc-derive", + "rand", + "ref-cast", + "serde", + "serde-error", + "strum 0.25.0", + "tempfile", + "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", + "url", + "walkdir", +] + +[[package]] +name = "iroh-base" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c21fd8eb71f166a172a9779c2244db992218e9a9bd929b9df6fc355d2b630c9" +dependencies = [ + "aead", + "anyhow", + "crypto_box", + "data-encoding", + "derive_more", + "ed25519-dalek", + "getrandom", + "hex", + "iroh-blake3", + "once_cell", + "postcard", + "rand", + "rand_core", + "redb 2.1.1", + "serde", + "ssh-key", + "thiserror", + "ttl_cache", + "url", + "zeroize", +] + +[[package]] +name = "iroh-blake3" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbba31f40a650f58fa28dd585a8ca76d8ae3ba63aacab4c8269004a0c803930" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if", + "constant_time_eq", +] + +[[package]] +name = "iroh-blobs" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cce615635f60b5a01f6d066084cc0fca8281df594b6b735840d4796a06422604" +dependencies = [ + "anyhow", + "async-channel", + "bao-tree", + "bytes", + "chrono", + "derive_more", + "futures-buffered", + "futures-lite 2.3.0", + "genawaiter", + "hashlink", + "hex", + "iroh-base", + "iroh-io", + "iroh-metrics", + "iroh-net", + "iroh-quinn", + "iroh-router", + "num_cpus", + "oneshot", + "parking_lot", + "pin-project", + "postcard", + "rand", + "range-collections", + "redb 1.5.1", + "redb 2.1.1", + "reflink-copy", + "self_cell", + "serde", + "serde-error", + "smallvec", + "tempfile", + "thiserror", + "tokio", + "tokio-util", + "tracing", + "tracing-futures", +] + +[[package]] +name = "iroh-docs" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b4e9283e9a05a1e1c2b702ea743445a8e41ffd651deccddc2884d05f941db58" +dependencies = [ + "anyhow", + "async-channel", + "bytes", + "derive_more", + "ed25519-dalek", + "futures-buffered", + "futures-lite 2.3.0", + "futures-util", + "hex", + "iroh-base", + "iroh-blake3", + "iroh-blobs", + "iroh-gossip", + "iroh-metrics", + "iroh-net", + "iroh-router", + "lru", + "num_enum", + "postcard", + "rand", + "rand_core", + "redb 1.5.1", + "redb 2.1.1", + "self_cell", + "serde", + "strum 0.25.0", + "tempfile", + "thiserror", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", +] + +[[package]] +name = "iroh-gossip" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c078057037f0e741c5ef285c67fd9cfdb928163dd046fb547089898bdb02990e" +dependencies = [ + "anyhow", + "async-channel", + "bytes", + "derive_more", + "ed25519-dalek", + "futures-concurrency", + "futures-lite 2.3.0", + "futures-util", + "indexmap", + "iroh-base", + "iroh-blake3", + "iroh-metrics", + "iroh-net", + "iroh-router", + "nested_enum_utils", + "postcard", + "quic-rpc", + "quic-rpc-derive", + "rand", + "rand_core", + "serde", + "serde-error", + "strum 0.26.3", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "iroh-io" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d1047ad5ca29ab4ff316b6830d86e7ea52cea54325e4d4a849692e1274b498" +dependencies = [ + "bytes", + "futures-lite 2.3.0", + "pin-project", + "smallvec", + "tokio", +] + +[[package]] +name = "iroh-metrics" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0d40f2ee3997489d47403d204a06514ed65373d224b5b43a8ea133f543e5db1" +dependencies = [ + "anyhow", + "erased_set", + "http-body-util", + "hyper 1.4.0", + "hyper-util", + "once_cell", + "prometheus-client", + "reqwest", + "serde", + "struct_iterable", + "time", + "tokio", + "tracing", +] + +[[package]] +name = "iroh-net" +version = "0.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3840888c255de51bfa56d5a0c3ebe1fba63f9568ce97733b34548c4394313558" +dependencies = [ + "anyhow", + "backoff", + "base64 0.22.1", + "bytes", + "der", + "derive_more", + "duct", + "futures-buffered", + "futures-concurrency", + "futures-lite 2.3.0", + "futures-sink", + "futures-util", + "genawaiter", + "governor", + "hex", + "hickory-proto 0.25.0-alpha.2", + "hickory-resolver", + "hostname", + "http 1.1.0", + "http-body-util", + "hyper 1.4.0", + "hyper-util", + "igd-next", + "iroh-base", + "iroh-metrics", + "iroh-quinn", + "iroh-quinn-proto", + "iroh-quinn-udp", + "libc", + "netdev", + "netlink-packet-core", + "netlink-packet-route", + "netlink-sys", + "netwatch", + "num_enum", + "once_cell", + "parking_lot", + "pin-project", + "pkarr", + "portmapper", + "postcard", + "rand", + "rcgen", + "reqwest", + "ring", + "rtnetlink", + "rustls", + "rustls-webpki", + "serde", + "smallvec", + "socket2", + "strum 0.26.3", + "stun-rs", + "surge-ping", + "swarm-discovery", + "thiserror", + "time", + "tokio", + "tokio-rustls", + "tokio-stream", + "tokio-tungstenite", + "tokio-tungstenite-wasm", + "tokio-util", + "tracing", + "tungstenite", + "url", + "watchable", + "webpki-roots", + "windows 0.51.1", + "wmi", + "x509-parser", + "z32", +] + +[[package]] +name = "iroh-quinn" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35ba75a5c57cff299d2d7ca1ddee053f66339d1756bd79ec637bcad5aa61100e" +dependencies = [ + "bytes", + "iroh-quinn-proto", + "iroh-quinn-udp", + "pin-project-lite", + "rustc-hash 2.1.1", + "rustls", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "iroh-quinn-proto" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2c869ba52683d3d067c83ab4c00a2fda18eaf13b1434d4c1352f428674d4a5d" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash 2.1.1", + "rustls", + "rustls-platform-verifier", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "iroh-quinn-udp" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c53afaa1049f7c83ea1331f5ebb9e6ebc5fdd69c468b7a22dd598b02c9bcc973" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "iroh-router" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1fd18ec6325dd3f01625f12c01acff50a4374ee1ab708e7b2078885fd63ad30" +dependencies = [ + "anyhow", + "futures-buffered", + "futures-lite 2.3.0", + "futures-util", + "iroh-net", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "iroh_sync" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "bytes", + "clap", + "futures-lite 2.3.0", + "futures-util", + "indicatif", + "iroh", + "notify", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", + "tracing-subscriber", + "uuid", + "warp", +] + +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "jni" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6df18c2e3db7e453d3c6ac5b3e9d5182664d28788126d39b91f2d1e22b017ec" +dependencies = [ + "cesu8", + "combine", + "jni-sys", + "log", + "thiserror", + "walkdir", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "kqueue" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac30106d7dce88daf4a3fcb4879ea939476d5074a9b7ddd0fb97fa4bed5596a" +dependencies = [ + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[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.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" + +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "loom" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" +dependencies = [ + "cfg-if", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "lru" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "mainline" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b751ffb57303217bcae8f490eee6044a5b40eadf6ca05ff476cad37e7b7970d" +dependencies = [ + "bytes", + "crc", + "ed25519-dalek", + "flume", + "lru", + "rand", + "serde", + "serde_bencode", + "serde_bytes", + "sha1_smol", + "thiserror", + "tracing", +] + +[[package]] +name = "match_cfg" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "md5" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" + +[[package]] +name = "memalloc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "multer" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http 0.2.12", + "httparse", + "log", + "memchr", + "mime", + "spin", + "version_check", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + +[[package]] +name = "nested_enum_utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f256ef99e7ac37428ef98c89bef9d84b590172de4bbfbe81b68a4cd3abadb32" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "netdev" +version = "0.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7516ad2c46cc25da098ed7d6b9a0cbe9e1fbffbd04b1596148b95f2841179c83" +dependencies = [ + "dlopen2", + "libc", + "memalloc", + "netlink-packet-core", + "netlink-packet-route", + "netlink-sys", + "once_cell", + "system-configuration", + "windows-sys 0.52.0", +] + +[[package]] +name = "netlink-packet-core" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72724faf704479d67b388da142b186f916188505e7e0b26719019c525882eda4" +dependencies = [ + "anyhow", + "byteorder", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-route" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053998cea5a306971f88580d0829e90f270f940befd7cf928da179d4187a5a66" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "byteorder", + "libc", + "netlink-packet-core", + "netlink-packet-utils", +] + +[[package]] +name = "netlink-packet-utils" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ede8a08c71ad5a95cdd0e4e52facd37190977039a4704eb82a283f713747d34" +dependencies = [ + "anyhow", + "byteorder", + "paste", + "thiserror", +] + +[[package]] +name = "netlink-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b33524dc0968bfad349684447bfce6db937a9ac3332a1fe60c0c5a5ce63f21" +dependencies = [ + "bytes", + "futures", + "log", + "netlink-packet-core", + "netlink-sys", + "thiserror", + "tokio", +] + +[[package]] +name = "netlink-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "416060d346fbaf1f23f9512963e3e878f1a78e707cb699ba9215761754244307" +dependencies = [ + "bytes", + "futures", + "libc", + "log", + "tokio", +] + +[[package]] +name = "netwatch" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a639d52c0996ac640e2a7052a5265c8f71efdbdadc83188435ffc358b7ca931" +dependencies = [ + "anyhow", + "bytes", + "derive_more", + "futures-lite 2.3.0", + "futures-sink", + "futures-util", + "libc", + "netdev", + "netlink-packet-core", + "netlink-packet-route", + "netlink-sys", + "once_cell", + "rtnetlink", + "serde", + "socket2", + "thiserror", + "time", + "tokio", + "tracing", + "windows 0.51.1", + "wmi", +] + +[[package]] +name = "nix" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", +] + +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[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 = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + +[[package]] +name = "notify" +version = "6.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +dependencies = [ + "bitflags 2.6.0", + "crossbeam-channel", + "filetime", + "fsevent-sys", + "inotify", + "kqueue", + "libc", + "log", + "mio 0.8.11", + "walkdir", + "windows-sys 0.48.0", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", + "libm", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "num_enum" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "number_prefix" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" + +[[package]] +name = "object" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +dependencies = [ + "memchr", +] + +[[package]] +name = "oid-registry" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c958dd45046245b9c3c2547369bb634eb461670b2e7e0de552905801a648d1d" +dependencies = [ + "asn1-rs", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "oneshot" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce411919553d3f9fa53a0880544cda985a112117a0444d5ff1e870a893d6ea" + +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "os_pipe" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29d73ba8daf8fac13b0501d1abeddcfe21ba7401ada61a819144b6c2a4f32209" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p384" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + +[[package]] +name = "p521" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2" +dependencies = [ + "base16ct", + "ecdsa", + "elliptic-curve", + "primeorder", + "rand_core", + "sha2", +] + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.5.2", + "smallvec", + "windows-targets 0.52.5", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pem" +version = "3.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +dependencies = [ + "base64 0.22.1", + "serde", +] + +[[package]] +name = "pem-rfc7468" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" +dependencies = [ + "base64ct", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "pest_meta" +version = "2.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkarr" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d2197a648cb1c6d2d062d6456a6273ee82272b7d838da75e4a9a1232dfc4699" +dependencies = [ + "bytes", + "document-features", + "dyn-clone", + "ed25519-dalek", + "flume", + "futures", + "js-sys", + "lru", + "mainline", + "self_cell", + "simple-dns", + "thiserror", + "tracing", + "ureq", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "z32", +] + +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + +[[package]] +name = "pnet_base" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c" +dependencies = [ + "no-std-net", +] + +[[package]] +name = "pnet_macros" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn 2.0.68", +] + +[[package]] +name = "pnet_macros_support" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56" +dependencies = [ + "pnet_base", +] + +[[package]] +name = "pnet_packet" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a005825396b7fe7a38a8e288dbc342d5034dac80c15212436424fef8ea90ba" +dependencies = [ + "glob", + "pnet_base", + "pnet_macros", + "pnet_macros_support", +] + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + +[[package]] +name = "portable-atomic" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" + +[[package]] +name = "portmapper" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d60045fdcfe8ff6b781cf1027fdbb08ed319d93aff7da4bedc018e3bc92226" +dependencies = [ + "anyhow", + "base64 0.22.1", + "bytes", + "derive_more", + "futures-lite 2.3.0", + "futures-util", + "igd-next", + "iroh-metrics", + "libc", + "netwatch", + "num_enum", + "rand", + "serde", + "smallvec", + "socket2", + "thiserror", + "time", + "tokio", + "tokio-util", + "tracing", + "url", +] + +[[package]] +name = "positioned-io" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccabfeeb89c73adf4081f0dca7f8e28dbda90981a222ceea37f619e93ea6afe9" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "postcard" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55c51ee6c0db07e68448e336cf8ea4131a620edefebf9893e759b2d793420f8" +dependencies = [ + "cobs", + "const_format", + "embedded-io", + "postcard-derive", + "serde", +] + +[[package]] +name = "postcard-derive" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc4b01218787dd4420daf63875163a787a78294ad48a24e9f6fa8c6507759a79" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "precis-core" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d73e9dd26361c32e7cd13d1032bb01c4e26a23287274e8a4e2f228cf2c9ff77b" +dependencies = [ + "precis-tools", + "ucd-parse", + "unicode-normalization", +] + +[[package]] +name = "precis-profiles" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bde4bd6624c60cb0abe2bea1dbdbb9085f629a853861e64df4abb099f8076ad4" +dependencies = [ + "lazy_static", + "precis-core", + "precis-tools", + "unicode-normalization", +] + +[[package]] +name = "precis-tools" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d07ecadec70b0f560f09abf815ae0ee1a940d38d2354c938ba7229ac7c9f5f52" +dependencies = [ + "lazy_static", + "regex", + "ucd-parse", +] + +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + +[[package]] +name = "proc-macro-crate" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +dependencies = [ + "toml_edit", +] + +[[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 1.0.109", + "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 1.0.109", + "syn-mid", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prometheus-client" +version = "0.22.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1ca959da22a332509f2a73ae9e5f23f9dcfc31fd3a54d71f159495bd5909baa" +dependencies = [ + "dtoa", + "itoa", + "parking_lot", + "prometheus-client-derive-encode", +] + +[[package]] +name = "prometheus-client-derive-encode" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "quanta" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5167a477619228a0b284fac2674e3c388cba90631d7b7de620e6f1fcd08da5" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", +] + +[[package]] +name = "quic-rpc" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8431b2e7c22929347b61a354d4936d71fe7ab1e6b0475dc50e98276970dfec" +dependencies = [ + "anyhow", + "bincode", + "derive_more", + "educe", + "flume", + "futures-lite 2.3.0", + "futures-sink", + "futures-util", + "hex", + "iroh-quinn", + "pin-project", + "serde", + "slab", + "tokio", + "tokio-serde", + "tokio-util", + "tracing", +] + +[[package]] +name = "quic-rpc-derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403bc8506c847468e00170dbbbfe2c54d13b090031bcbe474cd3faea021cbd9f" +dependencies = [ + "proc-macro2", + "quic-rpc", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash 1.1.0", + "rustls", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash 1.1.0", + "rustls", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +dependencies = [ + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "quoted-string-parser" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dc75379cdb451d001f1cb667a9f74e8b355e9df84cc5193513cbe62b96fc5e9" +dependencies = [ + "pest", + "pest_derive", +] + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "range-collections" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca9edd21e2db51000ac63eccddabba622f826e631a60be7bade9bd6a76b69537" +dependencies = [ + "binary-merge", + "inplace-vec-builder", + "ref-cast", + "smallvec", +] + +[[package]] +name = "raw-cpuid" +version = "11.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "rcgen" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48406db8ac1f3cbc7dcdb56ec355343817958a356ff430259bb07baf7607e1e1" +dependencies = [ + "pem", + "ring", + "time", + "yasna", +] + +[[package]] +name = "redb" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7f82ecd6ba647a39dd1a7172b8a1cd9453c0adee6da20cb553d83a9a460fa5" +dependencies = [ + "libc", +] + +[[package]] +name = "redb" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6dd20d3cdeb9c7d2366a0b16b93b35b75aec15309fbeb7ce477138c9f68c8c0" +dependencies = [ + "libc", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "ref-cast" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf0a6f84d5f1d581da8b41b47ec8600871962f2a528115b542b362d4b744931" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "reflink-copy" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d731e7e3ebfcf422d96b8473e507d5b64790900dd5464772d38d1da9da24d3a" +dependencies = [ + "cfg-if", + "rustix", + "windows 0.57.0", +] + +[[package]] +name = "regex" +version = "1.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.4", +] + +[[package]] +name = "regex-lite" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" + +[[package]] +name = "reqwest" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.4.0", + "hyper-rustls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "once_cell", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", + "winreg 0.52.0", +] + +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + +[[package]] +name = "rfc6979" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" +dependencies = [ + "hmac", + "subtle", +] + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "sha2", + "signature", + "spki", + "subtle", + "zeroize", +] + +[[package]] +name = "rtnetlink" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a552eb82d19f38c3beed3f786bd23aa434ceb9ac43ab44419ca6d67a7e186c0" +dependencies = [ + "futures", + "log", + "netlink-packet-core", + "netlink-packet-route", + "netlink-packet-utils", + "netlink-proto", + "netlink-sys", + "nix", + "thiserror", + "tokio", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rusticata-macros" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" +dependencies = [ + "nom", +] + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.6.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.23.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +dependencies = [ + "log", + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + +[[package]] +name = "rustls-platform-verifier" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afbb878bdfdf63a336a5e63561b1835e7a8c91524f51621db870169eac84b490" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-roots", + "winapi", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.102.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "scoped-tls" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sec1" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +dependencies = [ + "base16ct", + "der", + "generic-array", + "pkcs8", + "subtle", + "zeroize", +] + +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "core-foundation-sys", + "libc", + "num-bigint", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-error" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "342110fb7a5d801060c885da03bf91bfa7c7ca936deafcc64bb6706375605d47" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_bencode" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a70dfc7b7438b99896e7f8992363ab8e2c4ba26aa5ec675d32d1c3c2c33d413e" +dependencies = [ + "serde", + "serde_bytes", +] + +[[package]] +name = "serde_bytes" +version = "0.11.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.203" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "serde_json" +version = "1.0.120" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serdect" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +dependencies = [ + "base16ct", + "serde", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha1_smol" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shared_child" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d94659ad3c2137fef23ae75b03d5241d633f8acded53d672decfa0e6e0caef" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "signature" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" +dependencies = [ + "digest", + "rand_core", +] + +[[package]] +name = "simple-dns" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01607fe2e61894468c6dc0b26103abb073fb08b79a3d9e4b6d76a1a341549958" +dependencies = [ + "bitflags 2.6.0", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] + +[[package]] +name = "smol_str" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad6c857cbab2627dcf01ec85a623ca4e7dcb5691cbaa3d7fb7653671f0d09c9" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spki" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" +dependencies = [ + "base64ct", + "der", +] + +[[package]] +name = "ssh-cipher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f" +dependencies = [ + "cipher", + "ssh-encoding", +] + +[[package]] +name = "ssh-encoding" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15" +dependencies = [ + "base64ct", + "pem-rfc7468", + "sha2", +] + +[[package]] +name = "ssh-key" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca9b366a80cf18bb6406f4cf4d10aebfb46140a8c0c33f666a144c5c76ecbafc" +dependencies = [ + "ed25519-dalek", + "p256", + "p384", + "p521", + "rand_core", + "rsa", + "sec1", + "sha2", + "signature", + "ssh-cipher", + "ssh-encoding", + "subtle", + "zeroize", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "struct_iterable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "849a064c6470a650b72e41fa6c057879b68f804d113af92900f27574828e7712" +dependencies = [ + "struct_iterable_derive", + "struct_iterable_internal", +] + +[[package]] +name = "struct_iterable_derive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bb939ce88a43ea4e9d012f2f6b4cc789deb2db9d47bad697952a85d6978662c" +dependencies = [ + "erased-serde", + "proc-macro2", + "quote", + "struct_iterable_internal", + "syn 2.0.68", +] + +[[package]] +name = "struct_iterable_internal" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9426b2a0c03e6cc2ea8dbc0168dbbf943f88755e409fb91bcb8f6a268305f4a" + +[[package]] +name = "strum" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" +dependencies = [ + "strum_macros 0.25.3", +] + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + +[[package]] +name = "strum_macros" +version = "0.25.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.68", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.68", +] + +[[package]] +name = "stun-rs" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0adebf9fb8fba5c39ee34092b0383f247e4d1255b98fcffec94b4b797b85b677" +dependencies = [ + "base64 0.22.1", + "bounded-integer", + "byteorder", + "crc", + "enumflags2", + "fallible-iterator", + "hmac-sha1", + "hmac-sha256", + "hostname-validator", + "lazy_static", + "md5", + "paste", + "precis-core", + "precis-profiles", + "quoted-string-parser", + "rand", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "surge-ping" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efbf95ce4c7c5b311d2ce3f088af2b93edef0f09727fa50fbe03c7a979afce77" +dependencies = [ + "hex", + "parking_lot", + "pnet_packet", + "rand", + "socket2", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "swarm-discovery" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39769914108ae68e261d85ceac7bce7095947130f79c29d4535e9b31fc702a40" +dependencies = [ + "acto", + "anyhow", + "hickory-proto 0.24.1", + "rand", + "socket2", + "tokio", + "tracing", +] + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "901fa70d88b9d6c98022e23b4136f9f3e54e4662c3bc1bd1d84a42a9a0f0c1e9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn-mid" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea305d57546cc8cd04feb14b62ec84bf17f50e3f7b12560d7bfa9265f39d9ed" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "system-configuration" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bc6ee10a9b4fcf576e9b0819d95ec16f4d2c02d39fd83ac1c8789785c4a42" +dependencies = [ + "bitflags 2.6.0", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tap" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand 2.1.0", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "thiserror" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tinyvec" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c55115c6fbe2d2bef26eb09ad74bde02d8255476fc0c7b515ef09fbb35742d82" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75ef51a33ef1da925cea3e4eb122833cb377c61439ca401b770f54902b806779" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio 1.0.3", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +dependencies = [ + "rustls", + "rustls-pki-types", + "tokio", +] + +[[package]] +name = "tokio-serde" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "911a61637386b789af998ee23f50aa30d5fd7edcec8d6d3dedae5e5815205466" +dependencies = [ + "bincode", + "bytes", + "educe", + "futures-core", + "futures-sink", + "pin-project", + "serde", +] + +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite", +] + +[[package]] +name = "tokio-tungstenite-wasm" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e57a65894797a018b28345fa298a00c450a574aa9671e50b18218a6292a55ac" +dependencies = [ + "futures-channel", + "futures-util", + "http 1.1.0", + "httparse", + "js-sys", + "thiserror", + "tokio", + "tokio-tungstenite", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "tokio-util" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "futures-util", + "hashbrown 0.15.4", + "pin-project-lite", + "slab", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" + +[[package]] +name = "toml_edit" +version = "0.22.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[package]] +name = "ttl_cache" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4189890526f0168710b6ee65ceaedf1460c48a14318ceec933cb26baa492096a" +dependencies = [ + "linked-hash-map", +] + +[[package]] +name = "tungstenite" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" +dependencies = [ + "byteorder", + "bytes", + "data-encoding", + "http 1.1.0", + "httparse", + "log", + "rand", + "sha1", + "thiserror", + "url", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-parse" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06ff81122fcbf4df4c1660b15f7e3336058e7aec14437c9f85c6b31a0f279b9" +dependencies = [ + "regex-lite", +] + +[[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.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-width" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "ureq" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" +dependencies = [ + "base64 0.22.1", + "log", + "once_cell", + "rustls", + "rustls-pki-types", + "url", + "webpki-roots", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna 0.5.0", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + +[[package]] +name = "uuid" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5de17fd2f7da591098415cff336e12965a28061ddace43b59cb3c430179c9439" +dependencies = [ + "getrandom", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317211a0dc0ceedd78fb2ca9a44aed3d7b9b26f81870d485c07122b4350673b7" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "warp" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "headers", + "http 0.2.12", + "hyper 0.14.32", + "log", + "mime", + "mime_guess", + "multer", + "percent-encoding", + "pin-project", + "scoped-tls", + "serde", + "serde_json", + "serde_urlencoded", + "tokio", + "tokio-tungstenite", + "tokio-util", + "tower-service", + "tracing", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.68", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "watchable" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45b42a2f611916b5965120a9cde2b60f2db4454826dd9ad5e6f47c24a5b3b259" +dependencies = [ + "event-listener 4.0.3", + "futures-util", + "parking_lot", + "thiserror", +] + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core 0.51.1", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" +dependencies = [ + "windows-core 0.52.0", + "windows-implement 0.52.0", + "windows-interface 0.52.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core 0.57.0", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement 0.57.0", + "windows-interface 0.57.0", + "windows-result 0.1.2", + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement 0.60.0", + "windows-interface 0.59.1", + "windows-link", + "windows-result 0.3.4", + "windows-strings", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-interface" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd" +dependencies = [ + "memchr", +] + +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + +[[package]] +name = "wmi" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f0a4062ca522aad4705a2948fd4061b3857537990202a8ddd5af21607f79a" +dependencies = [ + "chrono", + "futures", + "log", + "serde", + "thiserror", + "windows 0.52.0", +] + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "x509-parser" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcbc162f30700d6f3f82a24bf7cc62ffe7caea42c0b2cba8bf7f3ae50cf51f69" +dependencies = [ + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "rusticata-macros", + "thiserror", + "time", +] + +[[package]] +name = "xml-rs" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" + +[[package]] +name = "xmltree" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7d8a75eaf6557bb84a65ace8609883db44a29951042ada9b393151532e41fcb" +dependencies = [ + "xml-rs", +] + +[[package]] +name = "yasna" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" +dependencies = [ + "time", +] + +[[package]] +name = "z32" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edb37266251c28b03d08162174a91c3a092e3bd4f476f8205ee1c507b78b7bdc" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.68", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9f746b2 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "iroh_sync" +version = "0.1.0" +edition = "2021" + +[dependencies] +# Main Iroh crate - use the latest stable version +iroh = "0.28" + +# Async runtime and utilities +tokio = { version = "1.35", features = ["full"] } +tokio-stream = { version = "0.1", features = ["net"] } +futures-lite = "2.0" +futures-util = "0.3" +async-trait = "0.1" + +# Error handling and serialization +anyhow = "1.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +bytes = "1.5" + +# File watching +notify = "6.1" + +# CLI and logging +clap = { version = "4.4", features = ["derive"] } +tracing = "0.1" +tracing-subscriber = { version = "0.3", features = ["env-filter"] } + +# Other utilities +indicatif = "0.17" +uuid = { version = "1.0", features = ["v4"] } + +#web dependencies +warp = "0.3" +tokio-util = { version = "0.7", features = ["io"] } + + +[[bin]] +name = "iroh_sync" +path = "src/main.rs" + +[[example]] +name = "simple_sync" +path = "examples/simple_sync.rs" \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 0000000..bb575ad --- /dev/null +++ b/Readme.md @@ -0,0 +1,4 @@ +Run: Cargo run --release +Web Interface: +Local: http://localhost:3030 +Mobile: http://YOUR_PC_IP:3030 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..01a1230 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,407 @@ +mod sync_dir; + +use std::{env, fs, io, thread, time}; +use std::collections::HashMap; +use std::fs::File; +use std::io::{Read, stdin, Write}; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use futures_lite::AsyncReadExt; +use tokio_stream::{Stream, StreamExt}; +use anyhow; +use std::time::Duration; +use iroh::base::node_addr::AddrInfoOptions; +use iroh::client::Doc; +use iroh::client::docs::{LiveEvent, ShareMode}; +use iroh::docs::store::Query; +use iroh::node::Node; +use tokio::sync::Mutex; +use std::sync::mpsc::{channel, TryRecvError}; +use iroh::blobs::store::fs::Store; +use iroh::docs::{Author, AuthorId, ContentStatus}; +use iroh::net::key; +use iroh::node; +use notify::{Event, EventKind, RecursiveMode, Watcher, RecommendedWatcher}; +use crate::sync_dir::SyncDir; +use tracing_subscriber::EnvFilter; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + // Initialize logging + tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env() + .add_directive("info".parse().unwrap())) + .init(); + + let args: Vec = env::args().skip(1).collect(); + + // Check if user wants help + if args.is_empty() || args[0] == "--help" || args[0] == "-h" { + println!("Usage: {} [ticket] [--web-port PORT] [--skip-diagnostics]", env::args().next().unwrap()); + println!(" sync-directory: Directory to sync"); + println!(" ticket: Optional ticket to connect to existing document"); + println!(" --web-port PORT: Port for web interface (default: 3030)"); + println!(" --skip-diagnostics: Skip the initial diagnostic checks"); + println!("\nWeb interface will be available at:"); + println!(" Local: http://localhost:PORT"); + println!(" Mobile: http://YOUR_PC_IP:PORT"); + println!("\nExample: {} ./my-sync-folder --web-port 8080", env::args().next().unwrap()); + return Ok(()); + } + + let base_path = env::current_dir().unwrap().join(args[0].parse::().unwrap()); + println!("📁 BASE_PATH: {:?}", base_path); + + // Check if directory exists + if !base_path.exists() { + println!("❌ ERROR: Directory does not exist: {:?}", base_path); + println!("Creating directory..."); + fs::create_dir_all(&base_path)?; + println!("✅ Directory created!"); + } + + // Parse command line arguments + let mut ticket_arg = None; + let mut web_port = 3030u16; + let mut skip_diagnostics = false; + + let mut i = 1; + while i < args.len() { + match args[i].as_str() { + "--web-port" => { + if i + 1 < args.len() { + web_port = args[i + 1].parse::().unwrap_or(3030); + i += 2; + } else { + println!("⚠️ Warning: --web-port requires a port number, using default 3030"); + i += 1; + } + }, + "--skip-diagnostics" => { + skip_diagnostics = true; + i += 1; + }, + arg if !arg.starts_with("--") && ticket_arg.is_none() => { + ticket_arg = Some(arg.to_string()); + i += 1; + }, + _ => { + i += 1; + } + } + } + + println!("🔧 Creating SyncDir..."); + + // Create SyncDir + let sync_dir = if let Some(ticket) = ticket_arg { + println!("🎫 Using provided ticket: {}", &ticket[..50.min(ticket.len())]); // Show first 50 chars + SyncDir::new(base_path.clone(), Some(ticket)).await? + } else { + println!("📄 Creating new document (no ticket provided)"); + SyncDir::new(base_path.clone(), None).await? + }; + + println!("✅ SyncDir created successfully!"); + println!("🆔 Node ID: {}", sync_dir.node_id()); + println!("📄 Namespace: {}", sync_dir.namespace_id().await?); + + let sync_dir = Arc::new(Mutex::new(sync_dir)); + + println!("📂 Loading local files..."); + let sync_dir_clone = Arc::clone(&sync_dir); + { + let sync_dir_lock = sync_dir_clone.lock().await; + (*sync_dir_lock).load_local_files().await?; + } + println!("✅ Local files loaded!"); + + // Run diagnostic checks unless skipped + if !skip_diagnostics { + println!("🔍 Running diagnostic checks..."); + let sync_dir_lock = sync_dir_clone.lock().await; + + // Check for conflicts + (*sync_dir_lock).check_entry_conflicts().await?; + + // Comprehensive listing + (*sync_dir_lock).list_all_entries_detailed().await?; + + // Test adding a specific missing file (if it exists) + let test_file_path = base_path.join("emptymails/INBOX/new/email_369"); + if test_file_path.exists() { + (*sync_dir_lock).test_add_missing_file("email_369").await?; + } + + // Show debug contents + println!("📋 Document contents:"); + (*sync_dir_lock).debug_contents().await?; + + println!("🔧 Adding all missing files..."); + (*sync_dir_lock).add_missing_files().await?; + + println!("📊 Comparing disk files with document entries..."); + (*sync_dir_lock).compare_disk_vs_document().await?; + + // Show final debug contents + println!("📋 Final document contents:"); + (*sync_dir_lock).debug_contents().await?; + + drop(sync_dir_lock); + println!("✅ Diagnostics complete!"); + } else { + println!("⏩ Skipping diagnostics (--skip-diagnostics flag used)"); + } + + // Start web interface + println!("🌐 Starting web interface on port {}...", web_port); + let sync_dir_web = Arc::clone(&sync_dir); + let web_handle = tokio::spawn(async move { + if let Err(e) = crate::sync_dir::start_web_interface(sync_dir_web, web_port).await { + eprintln!("❌ Web interface error: {}", e); + } + }); + + // Subscribe to document events + println!("📡 Subscribing to document events..."); + let mut stream = { + let lock = sync_dir.lock().await; + lock.subscribe().await? + }; + println!("✅ Subscribed to document events!"); + + // Get info for startup summary + let (node_id_short, namespace_short, folder_name) = { + let lock = sync_dir.lock().await; + let node_id = lock.node_id().to_string(); + let namespace = lock.namespace_id().await?.to_string(); + let folder = base_path.file_name().unwrap_or_default().to_string_lossy().to_string(); + (node_id[..8].to_string(), namespace[..8].to_string(), folder) + }; + + // Print startup summary + println!("\n╔══════════════════════════════════════╗"); + println!("║ 🔄 IROH FILE SYNC ACTIVE ║"); + println!("╠══════════════════════════════════════╣"); + println!("║ 🌐 Web Interface: ║"); + println!("║ Local: http://localhost:{} ║", web_port); + println!("║ Mobile: http://YOUR_PC_IP:{} ║", web_port); + println!("║ ║"); + println!("║ 📁 Sync Folder: {:20} ║", folder_name); + println!("║ 🆔 Node ID: {}... ║", node_id_short); + println!("║ 📄 Document: {}... ║", namespace_short); + println!("║ ║"); + println!("║ 💡 Tips: ║"); + println!("║ • Find your PC IP: ipconfig ║"); + println!("║ • Type 'q' + Enter to quit ║"); + println!("║ • Generate tickets in web UI ║"); + println!("╚══════════════════════════════════════╝"); + println!(); + + // Handle document events + let sync_dir_clone_stream = Arc::clone(&sync_dir); + let stream_task = tokio::spawn(async move { + while let Some(item) = stream.next().await { + match item { + Ok(value) => { + println!("📡 Remote event: {:?}", value); + match value { + LiveEvent::InsertRemote { content_status, entry, .. } => { + if content_status == ContentStatus::Complete { + let sync_dir_lock = sync_dir_clone_stream.lock().await; + if let Err(e) = (*sync_dir_lock).write_remote_entry(entry.clone()).await { + eprintln!("❌ Failed to write remote entry: {}", e); + } + drop(sync_dir_lock); + } else { + let sync_dir_lock = sync_dir_clone_stream.lock().await; + if let Err(e) = (*sync_dir_lock).handle_pending_entry(entry.clone()).await { + eprintln!("❌ Failed to handle pending entry: {}", e); + } + drop(sync_dir_lock); + } + } + LiveEvent::ContentReady { .. } => { + let sync_dir_lock = sync_dir_clone_stream.lock().await; + if let Err(e) = (*sync_dir_lock).process_pending_entries().await { + eprintln!("❌ Failed to process pending entries: {}", e); + } + drop(sync_dir_lock); + } + LiveEvent::PendingContentReady => { + let sync_dir_lock = sync_dir_clone_stream.lock().await; + if let Err(e) = (*sync_dir_lock).process_pending_entries().await { + eprintln!("❌ Failed to process pending entries: {}", e); + } + drop(sync_dir_lock); + } + _ => {} + } + } + Err(e) => eprintln!("❌ Stream error: {}", e), + } + } + }); + + // File system watcher + let sync_dir_clone_watcher = Arc::clone(&sync_dir); + let watcher_base_path = base_path.clone(); + let watcher_task = tokio::spawn(async move { + println!("👀 Starting file system watcher..."); + let (tx, rx) = channel(); + let mut watcher = RecommendedWatcher::new( + move |res: Result| { + if let Ok(event) = res { + let _ = tx.send(event); + } + }, + notify::Config::default() + ).unwrap(); + + if let Err(e) = watcher.watch(&watcher_base_path, RecursiveMode::Recursive) { + eprintln!("❌ Failed to start file watcher: {}", e); + return; + } + + loop { + match rx.try_recv() { + Ok(event) => { + println!("📁 File event: {:?}", event); + let sync_dir_lock = sync_dir_clone_watcher.lock().await; + + for path in event.paths { + match event.kind { + EventKind::Create(_) => { + if let Err(e) = (*sync_dir_lock).handle_local_change(path.clone()).await { + if !e.to_string().contains("newer entry exists") { + eprintln!("❌ Failed to handle file creation {:?}: {}", path, e); + } + } + } + EventKind::Modify(_) => { + if let Err(e) = (*sync_dir_lock).handle_local_change(path.clone()).await { + if !e.to_string().contains("newer entry exists") { + eprintln!("❌ Failed to handle file modification {:?}: {}", path, e); + } + } + } + EventKind::Remove(_) => { + if let Err(e) = (*sync_dir_lock).handle_local_delete(path.clone()).await { + eprintln!("❌ Failed to handle file deletion {:?}: {}", path, e); + } + } + _ => {} + } + } + drop(sync_dir_lock); + } + Err(e) => match e { + TryRecvError::Empty => { + tokio::time::sleep(Duration::from_millis(100)).await; + } + TryRecvError::Disconnected => { + println!("📁 File watcher disconnected"); + break; + } + }, + } + } + }); + + // Enhanced input handling with commands + println!("🎮 Available commands:"); + println!(" q - Quit the application"); + println!(" s - Show current status"); + println!(" d - Show debug info"); + println!(" f - Force refresh files"); + println!(" h - Show help"); + println!(); + + let mut input = String::new(); + loop { + print!("iroh-sync> "); + io::stdout().flush().unwrap(); + + input.clear(); + match io::stdin().read_line(&mut input) { + Ok(0) => break, // EOF + Ok(_) => { + match input.trim() { + "q" | "quit" | "exit" => { + println!("\n🛑 Shutting down..."); + break; + } + "s" | "status" => { + let lock = sync_dir.lock().await; + match lock.get_sync_status().await { + Ok(status) => { + println!("📊 Status:"); + println!(" 🆔 Node ID: {}", status.node_id); + println!(" 📄 Document: {}", status.namespace_id); + println!(" 👥 Connected Peers: {}", status.connected_peers); + println!(" 📁 Files: {}", status.total_files); + println!(" 📂 Directories: {}", status.total_directories); + } + Err(e) => println!("❌ Failed to get status: {}", e), + } + drop(lock); + } + "d" | "debug" => { + let lock = sync_dir.lock().await; + if let Err(e) = lock.debug_contents().await { + println!("❌ Failed to show debug info: {}", e); + } + drop(lock); + } + "f" | "refresh" => { + println!("🔄 Force refreshing files..."); + let lock = sync_dir.lock().await; + if let Err(e) = lock.load_local_files().await { + println!("❌ Failed to refresh files: {}", e); + } else { + println!("✅ Files refreshed!"); + } + drop(lock); + } + "h" | "help" => { + println!("🎮 Available commands:"); + println!(" q, quit, exit - Quit the application"); + println!(" s, status - Show current sync status"); + println!(" d, debug - Show debug information"); + println!(" f, refresh - Force refresh local files"); + println!(" h, help - Show this help"); + } + "" => { + // Empty line, just continue + } + cmd => { + println!("❓ Unknown command: '{}'. Type 'h' for help.", cmd); + } + } + } + Err(e) => { + eprintln!("❌ Failed to read input: {}", e); + break; + } + } + } + + // Cleanup + println!("🧹 Cleaning up..."); + + // Cancel tasks + stream_task.abort(); + watcher_task.abort(); + web_handle.abort(); + + // Shutdown sync system + let sync_dir_clone = Arc::clone(&sync_dir); + let sync_dir_lock = sync_dir_clone.lock().await; + if let Err(e) = (*sync_dir_lock).shutdown().await { + eprintln!("❌ Shutdown error: {}", e); + } + drop(sync_dir_lock); + + println!("✅ Shutdown complete! Goodbye!"); + Ok(()) +} \ No newline at end of file diff --git a/src/sync_dir.rs b/src/sync_dir.rs new file mode 100644 index 0000000..3870c06 --- /dev/null +++ b/src/sync_dir.rs @@ -0,0 +1,1874 @@ +use std::collections::{HashMap, HashSet}; +use std::fs; +use std::path::{Path, PathBuf}; +use std::sync::Arc; +use std::time::{Duration, Instant}; + +use anyhow::{Context, Result}; +use bytes::Bytes; +use futures_lite::{Stream, StreamExt}; +use tokio::sync::Mutex; +use tokio::io::AsyncReadExt; +use tracing::{debug, error, info, warn}; + +use warp::Filter; +use serde::{Deserialize, Serialize}; +use futures_util::TryStreamExt; +use tokio_util::io::StreamReader; + +// Updated imports for iroh 0.28 +use iroh::{ + base::{ + node_addr::AddrInfoOptions, + ticket::Ticket, + }, + client::{ + blobs::{WrapOption, AddProgress}, + docs::{Doc, Entry, LiveEvent, ShareMode}, + Iroh, + }, + docs::{ + Author, AuthorId, ContentStatus, DocTicket, NamespaceId, + store::Query, + }, + net::{NodeId, NodeAddr}, + node::{Node, Builder as NodeBuilder}, + blobs::Hash, +}; + +/// File metadata stored in docs +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +pub struct FileMetadata { + pub size: u64, + pub modified: u64, +} + +#[derive(Serialize)] +pub struct FileInfo { + pub name: String, + pub size: u64, + pub is_directory: bool, + pub path: String, +} + +#[derive(Serialize)] +pub struct SyncStatus { + pub node_id: String, + pub namespace_id: String, + pub connected_peers: usize, + pub total_files: usize, + pub total_directories: usize, +} + +#[derive(Deserialize)] +pub struct ConnectRequest { + pub ticket: String, +} + +/// Main sync directory handler +pub struct SyncDir { + base_path: PathBuf, + node: Node, + client: Iroh, + author: AuthorId, + doc: Arc>, + // Track pending entries waiting for content + pending_entries: Arc>>, + // Track recently written files to ignore file watcher events + recently_written: Arc>>, + // Track connected peers + connected_peers: Arc>>, + failed_files: Arc>>, +} + +impl SyncDir { + /// Create a new SyncDir instance + pub async fn new(base_path: PathBuf, ticket: Option) -> Result { + info!("Initializing SyncDir at {:?}", base_path); + + // Create data directory in current working directory, not in sync directory + let data_path = std::env::current_dir()?.join(".iroh-sync"); + fs::create_dir_all(&data_path)?; + info!("Using data directory: {:?}", data_path); + + // Create the node + let node = Node::persistent(&data_path) + .await? + .enable_docs() + .spawn() + .await?; + + let cloned_node = node.clone(); + let client = cloned_node.client(); + + // Get or create author + let author = client.authors().default().await?; + info!("Using author: {}", author); + + // Get or create document + let doc = match ticket { + Some(ticket_str) => { + info!("Importing from ticket: {}", ticket_str); + let ticket: DocTicket = ticket_str.parse() + .context("Failed to parse document ticket")?; + + client.docs().import(ticket).await? + } + None => { + info!("Creating new document"); + let doc = client.docs().create().await?; + + // Generate sharing ticket + let ticket = doc.share(ShareMode::Write, AddrInfoOptions::RelayAndAddresses).await?; + println!("=== DOCUMENT TICKET ==="); + println!("{}", ticket); + println!("Save this ticket to share with other peers!"); + println!("======================="); + info!("Created new doc with ticket: {}", ticket); + + doc + } + }; + + let doc = Arc::new(Mutex::new(doc)); + + Ok(SyncDir { + base_path, + node, + client: client.clone(), + author, + doc, + pending_entries: Arc::new(Mutex::new(HashMap::new())), + recently_written: Arc::new(Mutex::new(HashMap::new())), + connected_peers: Arc::new(Mutex::new(HashSet::new())), + failed_files: Arc::new(Mutex::new(Vec::new())), + }) + } + + /// Load all local files into the sync system + pub async fn load_local_files(&self) -> Result<()> { + info!("Loading local files from {:?}", self.base_path); + self.scan_and_add_directory(&self.base_path).await?; + info!("Local file loading complete"); + Ok(()) + } + + /// Recursively scan and add files from a directory + async fn scan_and_add_directory(&self, dir_path: &Path) -> Result<()> { + info!("Scanning directory: {:?}", dir_path); + let entries = fs::read_dir(dir_path)?; + let mut file_count = 0; + let mut dir_count = 0; + let mut skipped_count = 0; + + for entry in entries { + let entry = entry?; + let path = entry.path(); + + // Add detailed logging for each file + info!("Processing: {:?}", path); + + let metadata = match entry.metadata() { + Ok(m) => m, + Err(e) => { + error!("Failed to get metadata for {:?}: {}", path, e); + skipped_count += 1; + continue; + } + }; + + if metadata.is_dir() { + dir_count += 1; + if let Err(e) = self.add_directory_to_sync(&path).await { + if !e.to_string().contains("newer entry exists") { + error!("Failed to add directory {:?}: {}", path, e); + skipped_count += 1; + } + } + Box::pin(self.scan_and_add_directory(&path)).await?; + } else if metadata.is_file() { + file_count += 1; + // Log file details + info!("Adding file: {:?} (size: {} bytes)", path, metadata.len()); + + if let Err(e) = self.add_file_to_sync(&path).await { + if !e.to_string().contains("newer entry exists") { + error!("Failed to add file {:?}: {}", path, e); + skipped_count += 1; + } + } + } else { + info!("Skipping special file type: {:?}", path); + skipped_count += 1; + } + } + + info!("Directory scan complete for {:?}: {} files, {} dirs, {} skipped", + dir_path, file_count, dir_count, skipped_count); + Ok(()) +} + + /// Add a directory to the sync system + async fn add_directory_to_sync(&self, dir_path: &Path) -> Result<()> { + let relative_path = self.get_relative_path(dir_path)?; + let key = format!("d{}", relative_path.to_string_lossy()); // Use "d" prefix for directories + + // Check if this directory entry already exists + if self.entry_exists(&key).await? { + debug!("Directory entry already exists: {}", relative_path.display()); + return Ok(()); + } + + // Store directory marker with minimal content + let doc = self.doc.lock().await; + match doc.set_bytes(self.author, key.clone(), vec![0u8]).await { + Ok(_hash) => { + info!("Added directory: {}", relative_path.display()); + } + Err(e) if e.to_string().contains("newer entry exists") => { + debug!("Directory entry already exists (detected during write): {}", relative_path.display()); + } + Err(e) => { + error!("Failed to add directory {:?}: {}", dir_path, e); + return Err(e.into()); + } + } + drop(doc); + + Ok(()) + } + + /// Add a single file to the sync system + async fn add_file_to_sync(&self, file_path: &Path) -> Result<()> { + let relative_path = self.get_relative_path(file_path)?; + let key = relative_path.to_string_lossy().to_string(); + + info!("Attempting to add file: {} (full path: {:?})", key, file_path); + + // Skip Windows Zone.Identifier files + if key.ends_with(":Zone.Identifier") { + debug!("Skipping Zone.Identifier file: {}", key); + return Ok(()); + } + + // Check for other problematic patterns + if key.contains('\0') { + warn!("Skipping file with null character: {:?}", file_path); + return Ok(()); + } + + // Read file content with better error handling + let content = match fs::read(file_path) { + Ok(c) => c, + Err(e) => { + error!("Failed to read file {:?}: {}", file_path, e); + return Err(e.into()); + } + }; + + info!("Read file successfully: {} ({} bytes)", key, content.len()); + + // Handle empty files - Iroh doesn't allow completely empty entries + let content_to_store = if content.is_empty() { + vec![0u8] // Single null byte as placeholder + } else { + content + }; + + // Check if this entry already exists with the same content + if let Ok(true) = self.entry_exists_with_content(&key, &content_to_store).await { + debug!("File entry already exists with same content: {}", key); + return Ok(()); + } + + // Store content directly in doc (for iroh 0.28) + let doc = self.doc.lock().await; + match doc.set_bytes(self.author, key.clone(), content_to_store).await { + Ok(_hash) => { + info!("Added file: {}", key); + } + Err(e) if e.to_string().contains("newer entry exists") => { + debug!("File entry already exists (detected during write): {}", key); + } + Err(e) => { + error!("Failed to add file {:?}: {}", file_path, e); + return Err(e.into()); + } + } + drop(doc); + + Ok(()) // This was missing! +} + + +// Add this method to report failed files +pub async fn report_failed_files(&self) -> Result<()> { + let failed = self.failed_files.lock().await; + if failed.is_empty() { + println!("No failed files recorded during loading."); + } else { + println!("\n=== FAILED FILES REPORT ==="); + println!("Total failed files: {}", failed.len()); + for (file, reason) in failed.iter() { + println!(" - {}: {}", file, reason); + } + println!("=== END REPORT ===\n"); + } + Ok(()) +} + /// Download a blob from connected peers - Fixed for Iroh 0.28 + async fn download_blob(&self, hash: Hash) -> Result> { + info!("Attempting to download blob: {}", hash); + + // Get list of connected peers + let peers = self.connected_peers.lock().await.clone(); + + if peers.is_empty() { + return Err(anyhow::anyhow!("No connected peers to download from")); + } + + // Try to download from each connected peer + for peer_id in peers { + info!("Trying to download from peer: {}", peer_id); + + // Create a NodeAddr with just the peer ID + // The node should already know how to reach this peer since they're connected + let node_addr = iroh::net::NodeAddr::new(peer_id); + + match self.client.blobs().download(hash, node_addr).await { + Ok(mut progress) => { + // Wait for download to complete by consuming the stream + while let Some(event) = progress.next().await { + match event { + Ok(progress_event) => { + debug!("Download progress: {:?}", progress_event); + } + Err(e) => { + warn!("Download progress error: {}", e); + } + } + } + + // After the progress stream completes, the blob should be available + match self.client.blobs().read(hash).await { + Ok(mut reader) => { + let mut content = Vec::new(); + reader.read_to_end(&mut content).await?; + info!("Successfully downloaded blob: {} ({} bytes) from peer {}", hash, content.len(), peer_id); + return Ok(content); + } + Err(e) => { + warn!("Failed to read blob after download from peer {}: {}", peer_id, e); + continue; // Try next peer + } + } + } + Err(e) => { + warn!("Failed to start blob download from peer {}: {}", peer_id, e); + continue; // Try next peer + } + } + } + + Err(anyhow::anyhow!("Failed to download blob from any connected peer")) + } + + /// Write a received entry to the local filesystem - with directory support + pub async fn write_remote_entry(&self, entry: Entry) -> Result<()> { + let key = String::from_utf8_lossy(entry.key()).to_string(); + info!("Processing remote entry: {}", key); + + // Check if this is a directory entry (starts with "d") + if key.starts_with("d") { + // Extract the directory path (remove "d" prefix) + let dir_path = &key[1..]; + let full_dir_path = self.base_path.join(dir_path); + + // Create the directory + fs::create_dir_all(&full_dir_path)?; + + // Track that we just created this directory + let mut recently_written = self.recently_written.lock().await; + recently_written.insert(full_dir_path.clone(), Instant::now()); + drop(recently_written); + + info!("Created directory: {}", full_dir_path.display()); + return Ok(()); + } + + // Handle file entries + let content: Vec = { + let doc = self.doc.lock().await; + match entry.content_bytes(&*doc).await { + Ok(bytes_content) => { + bytes_content.to_vec() + } + Err(e) => { + error!("Failed to get content for {}: {}", key, e); + drop(doc); + + let hash = entry.content_hash(); + info!("Content not available locally, downloading blob: {}", hash); + + match self.download_blob(hash).await { + Ok(downloaded_content) => downloaded_content, + Err(download_err) => { + error!("Failed to download blob: {}", download_err); + return Err(download_err); + } + } + } + } + }; + + // Handle empty file placeholder + let actual_content = if content == vec![0u8] { + // This was an empty file stored with placeholder + Vec::new() + } else { + content + }; + + // Construct the full file path + let file_path = self.base_path.join(&key); + + // Create parent directories if needed + if let Some(parent) = file_path.parent() { + fs::create_dir_all(parent)?; + } + + // Write the file + fs::write(&file_path, &actual_content)?; + + // Track that we just wrote this file + let mut recently_written = self.recently_written.lock().await; + recently_written.insert(file_path.clone(), Instant::now()); + drop(recently_written); + + info!("Wrote file: {} ({} bytes)", file_path.display(), actual_content.len()); + Ok(()) + } + + /// Handle pending entries - store them for later processing + pub async fn handle_pending_entry(&self, entry: Entry) -> Result<()> { + let key = String::from_utf8_lossy(entry.key()).to_string(); + let mut pending = self.pending_entries.lock().await; + pending.insert(key.clone(), entry); + info!("Stored pending entry: {}", key); + Ok(()) + } + + /// Process all pending entries when content becomes ready + pub async fn process_pending_entries(&self) -> Result<()> { + let mut pending = self.pending_entries.lock().await; + let entries_to_process: Vec<_> = pending.drain().collect(); + drop(pending); + + info!("Processing {} pending entries", entries_to_process.len()); + + let mut failed_entries = Vec::new(); + + for (key, entry) in entries_to_process { + match self.write_remote_entry(entry.clone()).await { + Ok(()) => { + info!("Successfully processed pending entry: {}", key); + } + Err(e) => { + error!("Failed to process pending entry {}: {}", key, e); + // Re-add to pending if it's because of no connected peers + if e.to_string().contains("No connected peers") { + failed_entries.push((key, entry)); + } + } + } + } + + // Re-add failed entries back to pending + if !failed_entries.is_empty() { + let mut pending = self.pending_entries.lock().await; + for (key, entry) in failed_entries { + pending.insert(key, entry); + } + info!("Re-added {} entries to pending due to no connected peers", pending.len()); + } + + Ok(()) + } + + /// Track a connected peer + pub async fn add_peer(&self, peer_id: NodeId) { + let mut peers = self.connected_peers.lock().await; + peers.insert(peer_id); + info!("Added connected peer: {}", peer_id); + } + + /// Remove a disconnected peer + pub async fn remove_peer(&self, peer_id: NodeId) { + let mut peers = self.connected_peers.lock().await; + peers.remove(&peer_id); + info!("Removed disconnected peer: {}", peer_id); + } + + /// Handle local file and directory changes + pub async fn handle_local_change(&self, path: PathBuf) -> Result<()> { + // Check if this file was recently written by us (ignore for 2 seconds) + if self.was_recently_written(&path).await { + debug!("Ignoring file watcher event for recently written file: {:?}", path); + return Ok(()); + } + + if path.is_file() { + if let Err(e) = self.add_file_to_sync(&path).await { + // Only log as error if it's not a "newer entry exists" issue + if !e.to_string().contains("newer entry exists") { + error!("Failed to handle file change {:?}: {}", path, e); + } + } + } else if path.is_dir() { + if let Err(e) = self.add_directory_to_sync(&path).await { + // Only log as error if it's not a "newer entry exists" issue + if !e.to_string().contains("newer entry exists") { + error!("Failed to handle directory change {:?}: {}", path, e); + } + } + } + Ok(()) + } + + /// Check if a file was recently written by the sync system + async fn was_recently_written(&self, path: &Path) -> bool { + let mut recently_written = self.recently_written.lock().await; + + // Clean up old entries (older than 2 seconds) + let now = Instant::now(); + recently_written.retain(|_, time| now.duration_since(*time) < Duration::from_secs(2)); + + // Check if this path was recently written + recently_written.contains_key(path) + } + + /// Handle local file and directory deletion + pub async fn handle_local_delete(&self, path: PathBuf) -> Result<()> { + let relative_path = self.get_relative_path(&path)?; + + // Try both file and directory keys (since we don't know which it was) + let file_key = relative_path.to_string_lossy().to_string(); + let dir_key = format!("d{}", relative_path.to_string_lossy()); + + info!("Removing: {}", relative_path.display()); + + let doc = self.doc.lock().await; + + // Try to delete as file first + if let Err(_) = doc.del(self.author, file_key.clone()).await { + // If file deletion fails, try as directory + let _ = doc.del(self.author, dir_key.clone()).await; + } + + drop(doc); + + Ok(()) + } + + /// Handle file rename + pub async fn handle_rename(&self, src: PathBuf, dst: PathBuf) -> Result<()> { + info!("Renaming: {:?} -> {:?}", src, dst); + + // Delete old entry + self.handle_local_delete(src).await?; + + // Add new entry + if dst.is_file() { + self.handle_local_change(dst).await?; + } else if dst.is_dir() { + self.handle_local_change(dst).await?; + } + + Ok(()) + } + + /// Check if an entry exists in the document + async fn entry_exists(&self, key: &str) -> Result { + let doc = self.doc.lock().await; + let mut entries = doc.get_many(Query::single_latest_per_key().key_exact(key.to_string())).await?; + let exists = entries.next().await.is_some(); + drop(doc); + Ok(exists) + } + + /// Check if an entry exists with the same content + async fn entry_exists_with_content(&self, key: &str, content: &[u8]) -> Result { + let doc = self.doc.lock().await; + let mut entries = doc.get_many(Query::single_latest_per_key().key_exact(key.to_string())).await?; + + if let Some(entry_result) = entries.next().await { + match entry_result { + Ok(entry) => { + match entry.content_bytes(&*doc).await { + Ok(existing_content) => { + let exists_with_same_content = existing_content.as_ref() == content; + drop(doc); + return Ok(exists_with_same_content); + } + Err(_) => { + drop(doc); + return Ok(false); + } + } + } + Err(_) => { + drop(doc); + return Ok(false); + } + } + } + + drop(doc); + Ok(false) + } + + /// Get relative path from base + fn get_relative_path(&self, path: &Path) -> Result { + path.strip_prefix(&self.base_path) + .map(|p| p.to_path_buf()) + .context("Failed to get relative path") + } + + /// Subscribe to document events + pub async fn subscribe(&self) -> Result>> { + let doc = self.doc.lock().await; + let stream = doc.subscribe().await?; + drop(doc); + Ok(stream) + } + + /// Get the node ID + pub fn node_id(&self) -> NodeId { + self.node.node_id() + } + + /// Get the document namespace ID + pub async fn namespace_id(&self) -> Result { + let doc = self.doc.lock().await; + Ok(doc.id()) + } + + /// Shutdown the sync system + pub async fn shutdown(&self) -> Result<()> { + info!("Shutting down sync system..."); + + // Shutdown node (clone it since shutdown takes ownership) + self.node.clone().shutdown().await?; + + info!("Shutdown complete"); + Ok(()) + } + + /// Debug: show document contents + pub async fn debug_contents(&self) -> Result<()> { + let doc = self.doc.lock().await; + + // IMPORTANT: Use Query::all() instead of Query::single_latest_per_key() + // to see ALL entries, not just the latest per key + let mut entries = doc.get_many(Query::all()).await?; + let mut file_count = 0; + let mut dir_count = 0; + let mut total_count = 0; + + println!("\n=== DOCUMENT CONTENTS ==="); + while let Some(entry) = entries.next().await { + match entry { + Ok(e) => { + total_count += 1; + let key = String::from_utf8_lossy(e.key()); + let entry_type = if key.starts_with("d") { + dir_count += 1; + "DIR " + } else { + file_count += 1; + "FILE" + }; + + // For now, let's see ALL entries to debug + println!(" [{}] {} {} (author: {})", + total_count, + entry_type, + key, + &e.author().to_string()[..8] // Show first 8 chars of author ID + ); + } + Err(e) => println!(" Error reading entry: {}", e), + } + } + + println!("\nFiles: {}, Directories: {}, Total: {}", file_count, dir_count, total_count); + println!("========================\n"); + + drop(doc); + Ok(()) +} +/// Add this temporary debug function to SyncDir +pub async fn debug_missing_files(&self) -> Result<()> { + println!("\n=== INVESTIGATING MISSING FILES ==="); + + let doc = self.doc.lock().await; + + // Try different query methods + println!("\n1. Using Query::all():"); + let mut all_entries = doc.get_many(Query::all()).await?; + let mut count_all = 0; + while let Some(entry) = all_entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()); + if key.contains("email_369") { + println!(" FOUND via Query::all(): {}", key); + } + } + count_all += 1; + } + println!(" Total entries with Query::all(): {}", count_all); + + // Try with single_latest_per_key + println!("\n2. Using Query::single_latest_per_key():"); + let mut latest_entries = doc.get_many(Query::single_latest_per_key()).await?; + let mut count_latest = 0; + let mut found_369 = false; + while let Some(entry) = latest_entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()); + if key.contains("email_369") { + println!(" FOUND via Query::single_latest_per_key(): {}", key); + println!(" Author: {}", e.author()); + println!(" Timestamp: {:?}", e.timestamp()); + found_369 = true; + } + } + count_latest += 1; + } + println!(" Total entries with Query::single_latest_per_key(): {}", count_latest); + + if !found_369 { + println!("\n3. Trying direct key query for email_369:"); + let key = "emptymails/INBOX/new/email_369"; + let mut direct_query = doc.get_many(Query::single_latest_per_key().key_exact(key)).await?; + if let Some(entry_result) = direct_query.next().await { + match entry_result { + Ok(e) => { + println!(" FOUND via direct key query!"); + println!(" Key: {}", String::from_utf8_lossy(e.key())); + println!(" Author: {}", e.author()); + println!(" Hash: {}", e.content_hash()); + println!(" Timestamp: {:?}", e.timestamp()); + } + Err(e) => { + println!(" ERROR in direct query: {}", e); + } + } + } else { + println!(" NOT FOUND via direct key query"); + } + } + + // Check for files with similar patterns + println!("\n4. Checking pattern of missing files in INBOX/new:"); + let mut email_files: Vec<(u32, String)> = Vec::new(); + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()); + if key.contains("emptymails/INBOX/new/email_") && !key.contains("Zone.Identifier") { + // Extract the number + if let Some(num_str) = key.split("email_").nth(1) { + if let Ok(num) = num_str.parse::() { + email_files.push((num, key.to_string())); + } + } + } + } + } + + email_files.sort_by_key(|k| k.0); + + println!("\n Email files found (sorted by number):"); + let mut last_num = 0; + for (num, key) in &email_files { + if last_num > 0 && *num > last_num + 1 { + println!(" --- GAP: missing {} to {} ---", last_num + 1, num - 1); + } + println!(" {}: {}", num, key); + last_num = *num; + } + + drop(doc); + println!("\n=== END INVESTIGATION ===\n"); + Ok(()) +} + +pub async fn compare_disk_vs_document(&self) -> Result<()> { + println!("\n=== DISK vs DOCUMENT COMPARISON ==="); + + // First, count files on disk + let mut disk_files = HashSet::new(); + let mut disk_dirs = HashSet::new(); + let mut zone_identifier_count = 0; + + self.scan_disk_recursive(&self.base_path, &mut disk_files, &mut disk_dirs, &mut zone_identifier_count)?; + + println!("\nDISK STATISTICS:"); + println!(" Total files on disk: {}", disk_files.len() + zone_identifier_count); + println!(" Zone.Identifier files: {}", zone_identifier_count); + println!(" Actual content files: {}", disk_files.len()); + println!(" Directories: {}", disk_dirs.len()); + + // Now count entries in the document + let doc = self.doc.lock().await; + let mut doc_files = HashSet::new(); + let mut doc_dirs = HashSet::new(); + + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()).to_string(); + if key.starts_with("d") { + doc_dirs.insert(key[1..].to_string()); + } else { + doc_files.insert(key); + } + } + } + drop(doc); + + println!("\nDOCUMENT STATISTICS:"); + println!(" Files in document: {}", doc_files.len()); + println!(" Directories in document: {}", doc_dirs.len()); + println!(" Total entries: {}", doc_files.len() + doc_dirs.len()); + + // Find differences + println!("\nDIFFERENCES:"); + println!(" Files on disk but not in doc: {}", disk_files.difference(&doc_files).count()); + println!(" Files in doc but not on disk: {}", doc_files.difference(&disk_files).count()); + + // Show missing files + let missing_from_doc: Vec<_> = disk_files.difference(&doc_files).collect(); + if !missing_from_doc.is_empty() { + println!("\nFILES ON DISK BUT MISSING FROM DOCUMENT:"); + // Group by directory for easier reading + let mut by_dir: std::collections::HashMap> = std::collections::HashMap::new(); + for file in missing_from_doc { + let dir = file.rsplitn(2, '/').nth(1).unwrap_or("root").to_string(); + by_dir.entry(dir).or_insert_with(Vec::new).push(file.clone()); + } + + for (dir, mut files) in by_dir { + files.sort(); + println!("\n In {}:", dir); + for file in files { + println!(" - {}", file); + } + } + } + + // Check for the specific problem area + println!("\n=== INBOX/new SPECIFIC ANALYSIS ==="); + let inbox_prefix = "emptymails/INBOX/new/"; + let disk_inbox: Vec<_> = disk_files.iter() + .filter(|f| f.starts_with(inbox_prefix)) + .collect(); + let doc_inbox: Vec<_> = doc_files.iter() + .filter(|f| f.starts_with(inbox_prefix)) + .collect(); + + println!(" Files in INBOX/new on disk: {}", disk_inbox.len()); + println!(" Files in INBOX/new in document: {}", doc_inbox.len()); + + // Extract email numbers and find gaps + let mut disk_email_nums: Vec = Vec::new(); + let mut doc_email_nums: Vec = Vec::new(); + + for file in disk_inbox { + if let Some(num_str) = file.strip_prefix(&format!("{}email_", inbox_prefix)) { + if let Ok(num) = num_str.parse::() { + disk_email_nums.push(num); + } + } + } + + for file in doc_inbox { + if let Some(num_str) = file.strip_prefix(&format!("{}email_", inbox_prefix)) { + if let Ok(num) = num_str.parse::() { + doc_email_nums.push(num); + } + } + } + + disk_email_nums.sort(); + doc_email_nums.sort(); + + println!("\n Email number ranges:"); + if !disk_email_nums.is_empty() { + println!(" On disk: {} to {}", disk_email_nums.first().unwrap(), disk_email_nums.last().unwrap()); + } + if !doc_email_nums.is_empty() { + println!(" In document: {} to {}", doc_email_nums.first().unwrap(), doc_email_nums.last().unwrap()); + } + + println!("\n=== END COMPARISON ===\n"); + Ok(()) +} + +/// Helper function to recursively scan disk +fn scan_disk_recursive( + &self, + dir_path: &Path, + files: &mut HashSet, + dirs: &mut HashSet, + zone_identifier_count: &mut usize, +) -> Result<()> { + let entries = fs::read_dir(dir_path)?; + + for entry in entries { + let entry = entry?; + let path = entry.path(); + let metadata = entry.metadata()?; + + if metadata.is_dir() { + let relative = self.get_relative_path(&path)?; + dirs.insert(relative.to_string_lossy().to_string()); + self.scan_disk_recursive(&path, files, dirs, zone_identifier_count)?; + } else if metadata.is_file() { + let relative = self.get_relative_path(&path)?; + let relative_str = relative.to_string_lossy().to_string(); + + if relative_str.ends_with(":Zone.Identifier") { + *zone_identifier_count += 1; + } else { + files.insert(relative_str); + } + } + } + + Ok(()) +} + +/// Analyze missing files in detail +pub async fn analyze_missing_files(&self) -> Result<()> { + println!("\n=== DETAILED MISSING FILE ANALYSIS ==="); + + // Get all files from disk + let mut disk_files = HashSet::new(); + let mut disk_dirs = HashSet::new(); + let mut zone_count = 0; + self.scan_disk_recursive(&self.base_path, &mut disk_files, &mut disk_dirs, &mut zone_count)?; + + // Get all files from document + let doc = self.doc.lock().await; + let mut doc_files = HashSet::new(); + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()).to_string(); + if !key.starts_with("d") { + doc_files.insert(key); + } + } + } + drop(doc); + + // Focus on INBOX/new + let inbox_prefix = "emptymails/INBOX/new/"; + let missing_inbox: Vec = disk_files.difference(&doc_files) + .filter(|f| f.starts_with(inbox_prefix)) + .cloned() + .collect(); + + println!("Total missing files in INBOX/new: {}", missing_inbox.len()); + + // Analyze patterns + let mut missing_by_size: std::collections::HashMap> = std::collections::HashMap::new(); + let mut size_errors = 0; + let mut total_size_missing = 0u64; + + for file in &missing_inbox { + let full_path = self.base_path.join(file); + match fs::metadata(&full_path) { + Ok(meta) => { + let size = meta.len(); + total_size_missing += size; + let size_category = match size { + 0 => "empty (0 bytes)".to_string(), + 1..=1024 => "tiny (1B-1KB)".to_string(), + 1025..=102400 => "small (1KB-100KB)".to_string(), + 102401..=1048576 => "medium (100KB-1MB)".to_string(), + _ => format!("large (>1MB, exactly {} bytes)", size), + }; + missing_by_size.entry(size_category).or_insert_with(Vec::new).push(file.clone()); + } + Err(e) => { + println!("ERROR reading metadata for {}: {}", file, e); + size_errors += 1; + } + } + } + + println!("\nMissing files by size category:"); + for (category, files) in &missing_by_size { + println!(" {}: {} files", category, files.len()); + // Show a few examples + for file in files.iter().take(3) { + println!(" - {}", file); + } + if files.len() > 3 { + println!(" ... and {} more", files.len() - 3); + } + } + + println!("\nTotal size of missing files: {} bytes ({:.2} MB)", + total_size_missing, total_size_missing as f64 / 1_048_576.0); + + // Check if these files have anything special in common + println!("\nChecking file patterns:"); + + // Extract email numbers from missing files + let mut missing_numbers: Vec = Vec::new(); + for file in &missing_inbox { + if let Some(num_str) = file.strip_prefix(&format!("{}email_", inbox_prefix)) { + if let Ok(num) = num_str.parse::() { + missing_numbers.push(num); + } + } + } + missing_numbers.sort(); + + // Find continuous ranges + if !missing_numbers.is_empty() { + println!("\nMissing email numbers (showing ranges):"); + let mut ranges = Vec::new(); + let mut start = missing_numbers[0]; + let mut end = missing_numbers[0]; + + for &num in &missing_numbers[1..] { + if num == end + 1 { + end = num; + } else { + ranges.push((start, end)); + start = num; + end = num; + } + } + ranges.push((start, end)); + + for (start, end) in ranges { + if start == end { + println!(" - {}", start); + } else { + println!(" - {} to {} ({} files)", start, end, end - start + 1); + } + } + } + + // Try to read a few missing files to check content + println!("\nSampling missing files to check readability:"); + for file in missing_inbox.iter().take(5) { + let full_path = self.base_path.join(file); + print!(" {}: ", file); + match fs::read(&full_path) { + Ok(content) => { + println!("Readable, {} bytes, starts with: {:?}", + content.len(), + String::from_utf8_lossy(&content[..content.len().min(50)])); + } + Err(e) => { + println!("ERROR reading: {}", e); + } + } + } + + println!("\n=== END ANALYSIS ===\n"); + Ok(()) +} + +/// Check if there are multiple versions or conflicts for entries +pub async fn check_entry_conflicts(&self) -> Result<()> { + println!("\n=== CHECKING FOR ENTRY CONFLICTS ==="); + + let doc = self.doc.lock().await; + + // First, let's check a specific missing file + let test_key = "emptymails/INBOX/new/email_369"; + println!("\n1. Checking all versions of {}", test_key); + + // Use Query::all() to get ALL entries, not just latest + let mut all_entries = doc.get_many(Query::all().key_exact(test_key)).await?; + let mut version_count = 0; + + while let Some(entry) = all_entries.next().await { + if let Ok(e) = entry { + version_count += 1; + println!(" Version {}: author={}, timestamp={:?}, hash={}", + version_count, + &e.author().to_string()[..8], + e.timestamp(), + e.content_hash()); + } + } + + if version_count == 0 { + println!(" NO VERSIONS FOUND for {}", test_key); + } + + // Now check if we have multiple authors + println!("\n2. Checking authors in the document"); + let mut authors = HashSet::new(); + let mut entries_by_author: HashMap = HashMap::new(); + + let mut all_entries = doc.get_many(Query::all()).await?; + while let Some(entry) = all_entries.next().await { + if let Ok(e) = entry { + let author_str = e.author().to_string(); + authors.insert(e.author()); + *entries_by_author.entry(author_str).or_insert(0) += 1; + } + } + + println!(" Found {} different authors:", authors.len()); + for (author, count) in &entries_by_author { + println!(" - {}: {} entries", &author[..8], count); + } + + // Check if our current author matches + println!("\n3. Current author: {}", &self.author.to_string()[..8]); + + // Let's check the difference between Query::all() and Query::single_latest_per_key() + println!("\n4. Comparing query methods for INBOX/new files"); + + let mut all_inbox_entries = HashMap::new(); + let mut latest_inbox_entries = HashMap::new(); + + // Get ALL entries + let mut entries = doc.get_many(Query::all()).await?; + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()).to_string(); + if key.starts_with("emptymails/INBOX/new/email_") && !key.contains("Zone") { + all_inbox_entries.entry(key.clone()) + .or_insert_with(Vec::new) + .push(e.author()); + } + } + } + + // Get LATEST entries + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()).to_string(); + if key.starts_with("emptymails/INBOX/new/email_") && !key.contains("Zone") { + latest_inbox_entries.insert(key, e.author()); + } + } + } + + println!(" Query::all() found {} unique INBOX/new files", all_inbox_entries.len()); + println!(" Query::single_latest_per_key() found {} INBOX/new files", latest_inbox_entries.len()); + + // Find files that exist in all but not in latest + let mut missing_from_latest = 0; + for (key, authors) in &all_inbox_entries { + if !latest_inbox_entries.contains_key(key) { + missing_from_latest += 1; + println!(" File {} has {} versions but missing from latest!", key, authors.len()); + } + } + + if missing_from_latest > 0 { + println!("\n WARNING: {} files exist but aren't returned by single_latest_per_key!", missing_from_latest); + println!(" This might be due to timestamp conflicts or author issues."); + } + + // Let's also check if we're using the wrong query in debug_contents + println!("\n5. Testing different query filters"); + + // Try with author filter + let mut author_filtered = doc.get_many(Query::all().author(self.author)).await?; + let mut author_count = 0; + while let Some(_) = author_filtered.next().await { + author_count += 1; + } + println!(" Entries by current author: {}", author_count); + + drop(doc); + println!("\n=== END CONFLICT CHECK ===\n"); + Ok(()) +} + +/// List ALL entries in the document with full details +pub async fn list_all_entries_detailed(&self) -> Result<()> { + println!("\n=== COMPREHENSIVE ENTRY LISTING ==="); + + let doc = self.doc.lock().await; + + // Test 1: Count with different query methods + println!("1. Entry counts by query method:"); + + let mut count_all = 0; + let mut entries = doc.get_many(Query::all()).await?; + while let Some(_) = entries.next().await { + count_all += 1; + } + println!(" Query::all(): {} entries", count_all); + + let mut count_latest = 0; + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + while let Some(_) = entries.next().await { + count_latest += 1; + } + println!(" Query::single_latest_per_key(): {} entries", count_latest); + + let mut count_author = 0; + let mut entries = doc.get_many(Query::all().author(self.author)).await?; + while let Some(_) = entries.next().await { + count_author += 1; + } + println!(" Query::all().author(current): {} entries", count_author); + + // Test 2: List files in INBOX/new with all methods + println!("\n2. INBOX/new files by query method:"); + + let mut inbox_files_all = HashSet::new(); + let mut entries = doc.get_many(Query::all()).await?; + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()).to_string(); + if key.starts_with("emptymails/INBOX/new/email_") && !key.contains("Zone") { + inbox_files_all.insert(key); + } + } + } + + let mut inbox_files_latest = HashSet::new(); + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()).to_string(); + if key.starts_with("emptymails/INBOX/new/email_") && !key.contains("Zone") { + inbox_files_latest.insert(key); + } + } + } + + println!(" Query::all() found: {} INBOX/new files", inbox_files_all.len()); + println!(" Query::single_latest_per_key() found: {} INBOX/new files", inbox_files_latest.len()); + + // Show differences + let only_in_all: Vec<_> = inbox_files_all.difference(&inbox_files_latest).collect(); + if !only_in_all.is_empty() { + println!("\n Files found by Query::all() but NOT by single_latest_per_key:"); + for file in only_in_all.iter().take(10) { + println!(" - {}", file); + } + if only_in_all.len() > 10 { + println!(" ... and {} more", only_in_all.len() - 10); + } + } + + // Test 3: Check specific missing file with raw key query + println!("\n3. Direct key lookup for email_369:"); + let test_key = "emptymails/INBOX/new/email_369"; + + // Try exact key with all entries + let mut found = false; + let mut entries = doc.get_many(Query::key_exact(test_key)).await?; + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + found = true; + println!(" FOUND: author={}, timestamp={:?}", + &e.author().to_string()[..8], e.timestamp()); + } + } + + if !found { + println!(" NOT FOUND with Query::key_exact()"); + + // Try prefix search + let mut entries = doc.get_many(Query::key_prefix("emptymails/INBOX/new/email_369")).await?; + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()); + println!(" Found with prefix search: {}", key); + } + } + } + + drop(doc); + println!("\n=== END COMPREHENSIVE LISTING ===\n"); + Ok(()) +} + +/// Test adding a specific missing file with detailed diagnostics +pub async fn test_add_missing_file(&self, file_name: &str) -> Result<()> { + println!("\n=== TESTING ADD FOR {} ===", file_name); + + let file_path = self.base_path.join("emptymails/INBOX/new").join(file_name); + let key = format!("emptymails/INBOX/new/{}", file_name); + + // Step 1: Check if file exists on disk + if !file_path.exists() { + println!("ERROR: File does not exist on disk!"); + return Ok(()); + } + + let metadata = fs::metadata(&file_path)?; + println!("1. File exists on disk: {} bytes", metadata.len()); + + // Step 2: Read the file + let content = fs::read(&file_path)?; + println!("2. File read successfully: {} bytes", content.len()); + + // Step 3: Check if it already exists in the document + println!("3. Checking if already in document..."); + let doc = self.doc.lock().await; + + let mut existing = doc.get_many(Query::all().key_exact(&key)).await?; + let mut exists = false; + while let Some(entry) = existing.next().await { + if let Ok(e) = entry { + exists = true; + println!(" FOUND existing entry: author={}, timestamp={:?}", + &e.author().to_string()[..8], e.timestamp()); + } + } + + if exists { + println!(" File already exists in document!"); + drop(doc); + return Ok(()); + } + + println!(" File NOT in document, attempting to add..."); + + // Step 4: Try to add it + let content_to_store = if content.is_empty() { vec![0u8] } else { content }; + + match doc.set_bytes(self.author, key.clone(), content_to_store).await { + Ok(hash) => { + println!("4. SUCCESS: Added with hash: {}", hash); + } + Err(e) => { + println!("4. ERROR: Failed to add: {}", e); + drop(doc); + return Ok(()); + } + } + + // Step 5: Verify it was added + println!("5. Verifying addition..."); + let mut verify = doc.get_many(Query::all().key_exact(&key)).await?; + let mut verified = false; + + while let Some(entry) = verify.next().await { + if let Ok(e) = entry { + verified = true; + println!(" VERIFIED: Entry exists with author={}", &e.author().to_string()[..8]); + } + } + + if !verified { + println!(" ERROR: Entry not found after adding!"); + } + + // Step 6: Check with different query methods + println!("6. Checking with different queries..."); + + let with_latest = doc.get_many(Query::single_latest_per_key().key_exact(&key)).await? + .next().await.is_some(); + println!(" Found with single_latest_per_key: {}", with_latest); + + let with_author = doc.get_many(Query::all().author(self.author).key_exact(&key)).await? + .next().await.is_some(); + println!(" Found with author filter: {}", with_author); + + drop(doc); + println!("=== END TEST ===\n"); + Ok(()) +} + +/// Add all missing files from disk to the document +pub async fn add_missing_files(&self) -> Result<()> { + println!("\n=== ADDING MISSING FILES ==="); + + // First, get all files from disk + let mut disk_files = HashSet::new(); + let mut disk_dirs = HashSet::new(); + let mut zone_count = 0; + self.scan_disk_recursive(&self.base_path, &mut disk_files, &mut disk_dirs, &mut zone_count)?; + + // Get all files from document + let doc = self.doc.lock().await; + let mut doc_files = HashSet::new(); + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()).to_string(); + if !key.starts_with("d") { + doc_files.insert(key); + } + } + } + drop(doc); + + // Find missing files + let missing_files: Vec = disk_files.difference(&doc_files).cloned().collect(); + println!("Found {} missing files", missing_files.len()); + + // Add each missing file + let mut success_count = 0; + let mut fail_count = 0; + + for (index, file_key) in missing_files.iter().enumerate() { + let file_path = self.base_path.join(file_key); + + // Progress indicator + if index % 10 == 0 { + println!("Progress: {}/{} files processed...", index, missing_files.len()); + } + + // Try to add the file + match self.add_file_to_sync(&file_path).await { + Ok(()) => { + success_count += 1; + info!("Added missing file: {}", file_key); + } + Err(e) => { + fail_count += 1; + error!("Failed to add {}: {}", file_key, e); + } + } + } + + println!("\n=== MISSING FILES ADDITION COMPLETE ==="); + println!("Successfully added: {} files", success_count); + println!("Failed to add: {} files", fail_count); + + // Verify new counts + let doc = self.doc.lock().await; + let mut new_count = 0; + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + while let Some(_) = entries.next().await { + new_count += 1; + } + drop(doc); + + println!("Total entries in document now: {}", new_count); + println!("=== END ===\n"); + + Ok(()) +} + +/// Alternative: Re-scan a specific directory thoroughly +pub async fn rescan_directory(&self, dir_path: &Path) -> Result<()> { + println!("\n=== RE-SCANNING DIRECTORY: {:?} ===", dir_path); + + let full_path = if dir_path.is_absolute() { + dir_path.to_path_buf() + } else { + self.base_path.join(dir_path) + }; + + if !full_path.exists() { + println!("ERROR: Directory does not exist!"); + return Ok(()); + } + + let mut added_count = 0; + let mut skipped_count = 0; + let mut error_count = 0; + + // Read directory entries + let entries = fs::read_dir(&full_path)?; + + for entry in entries { + let entry = entry?; + let path = entry.path(); + + if entry.metadata()?.is_file() { + let file_name = entry.file_name().to_string_lossy().to_string(); + + // Skip Zone.Identifier files + if file_name.ends_with(":Zone.Identifier") { + continue; + } + + // Check if already exists + let relative_path = self.get_relative_path(&path)?; + let key = relative_path.to_string_lossy().to_string(); + + if self.entry_exists(&key).await? { + skipped_count += 1; + debug!("File already exists: {}", key); + continue; + } + + // Try to add + match self.add_file_to_sync(&path).await { + Ok(()) => { + added_count += 1; + println!("Added: {}", key); + } + Err(e) => { + error_count += 1; + error!("Failed to add {}: {}", key, e); + } + } + } + } + + println!("\n=== RE-SCAN COMPLETE ==="); + println!("Added: {} files", added_count); + println!("Skipped (already exist): {} files", skipped_count); + println!("Errors: {} files", error_count); + println!("=== END ===\n"); + + Ok(()) +} +pub async fn get_sync_status(&self) -> Result { + let doc = self.doc.lock().await; + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + let mut file_count = 0; + let mut dir_count = 0; + + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()); + if key.starts_with("d") { + dir_count += 1; + } else { + file_count += 1; + } + } + } + drop(doc); + + let connected_peers = self.connected_peers.lock().await.len(); + + Ok(SyncStatus { + node_id: self.node_id().to_string(), + namespace_id: self.namespace_id().await?.to_string(), + connected_peers, + total_files: file_count, + total_directories: dir_count, + }) + } + + /// List files for web interface + pub async fn list_files_for_web(&self) -> Result> { + let mut files = Vec::new(); + let doc = self.doc.lock().await; + let mut entries = doc.get_many(Query::single_latest_per_key()).await?; + + while let Some(entry) = entries.next().await { + if let Ok(e) = entry { + let key = String::from_utf8_lossy(e.key()).to_string(); + + if key.starts_with("d") { + // Directory + let dir_path = &key[1..]; // Remove "d" prefix + files.push(FileInfo { + name: dir_path.split('/').last().unwrap_or(&dir_path).to_string(), + size: 0, + is_directory: true, + path: dir_path.to_string(), + }); + } else { + // File - skip Zone.Identifier files + if key.ends_with(":Zone.Identifier") { + continue; + } + + let size = match e.content_bytes(&*doc).await { + Ok(content) => { + if content.as_ref() == &[0u8] { + 0 // Empty file placeholder + } else { + content.len() as u64 + } + } + Err(_) => 0, + }; + + files.push(FileInfo { + name: key.split('/').last().unwrap_or(&key).to_string(), + size, + is_directory: false, + path: key, + }); + } + } + } + + drop(doc); + + // Sort: directories first, then files, both alphabetically + files.sort_by(|a, b| { + match (a.is_directory, b.is_directory) { + (true, false) => std::cmp::Ordering::Less, + (false, true) => std::cmp::Ordering::Greater, + _ => a.name.cmp(&b.name), + } + }); + + Ok(files) + } + + /// Download a file for web interface + pub async fn download_file_for_web(&self, file_path: String) -> Result { + let doc = self.doc.lock().await; + let mut entries = doc.get_many(Query::single_latest_per_key().key_exact(&file_path)).await + .map_err(|_| warp::reject::reject())?; + + if let Some(entry_result) = entries.next().await { + match entry_result { + Ok(entry) => { + match entry.content_bytes(&*doc).await { + Ok(content) => { + let actual_content = if content.as_ref() == &[0u8] { + // Empty file + Vec::new() + } else { + content.to_vec() + }; + + let filename = file_path.split('/').last().unwrap_or("download"); + + Ok(warp::reply::with_header( + warp::reply::with_header( + actual_content, + "content-disposition", + format!("attachment; filename=\"{}\"", filename), + ), + "content-type", + "application/octet-stream", + )) + } + Err(_) => Err(warp::reject::reject()), + } + } + Err(_) => Err(warp::reject::reject()), + } + } else { + Err(warp::reject::reject()) + } + } + + /// Handle file upload from web interface + pub async fn handle_file_upload(&self, mut form: warp::multipart::FormData) -> Result { + let mut uploaded_files = Vec::new(); + + // Fix the ambiguous try_next call by using the specific trait + while let Some(part) = futures_util::TryStreamExt::try_next(&mut form).await.map_err(|_| warp::reject::reject())? { + if part.name() == "file" { + let filename = part.filename().unwrap_or("unnamed_file").to_string(); + + // Skip hidden/system files + if filename.starts_with('.') || filename.contains(":Zone.Identifier") { + continue; + } + + let stream = part.stream(); + let mut reader = StreamReader::new( + stream.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e)) + ); + + // Read file content + let mut content = Vec::new(); + tokio::io::AsyncReadExt::read_to_end(&mut reader, &mut content) + .await + .map_err(|_| warp::reject::reject())?; + + // Save to sync directory + let file_path = self.base_path.join(&filename); + + // Create parent directories if needed + if let Some(parent) = file_path.parent() { + tokio::fs::create_dir_all(parent) + .await + .map_err(|_| warp::reject::reject())?; + } + + tokio::fs::write(&file_path, &content) + .await + .map_err(|_| warp::reject::reject())?; + + // Add to sync system + self.add_file_to_sync(&file_path) + .await + .map_err(|_| warp::reject::reject())?; + + uploaded_files.push(filename); + info!("Uploaded file via web: {:?}", file_path); + } + } + + if uploaded_files.is_empty() { + return Err(warp::reject::reject()); + } + + Ok(warp::reply::json(&format!("Uploaded {} file(s): {}", + uploaded_files.len(), + uploaded_files.join(", ") + ))) + } + + /// Connect to another peer using a ticket + pub async fn connect_with_ticket(&self, ticket_str: String) -> Result<()> { + info!("Attempting to connect with ticket: {}", ticket_str); + + // Parse the ticket + let ticket: iroh::docs::DocTicket = ticket_str.parse() + .context("Failed to parse document ticket")?; + + // Import the document (this connects to the peer) + let _imported_doc = self.client.docs().import(ticket).await + .context("Failed to import document from ticket")?; + + info!("Successfully connected via ticket"); + Ok(()) + } + + /// Generate a new sharing ticket + pub async fn generate_ticket(&self) -> Result { + let doc = self.doc.lock().await; + let ticket = doc.share(ShareMode::Write, AddrInfoOptions::RelayAndAddresses).await?; + drop(doc); + Ok(ticket.to_string()) + } +} + +/// Start web interface - this is a standalone function, not a method +pub async fn start_web_interface(sync_dir: Arc>, port: u16) -> Result<()> { + info!("Starting web interface on port {}", port); + + // CORS for mobile browsers + let cors = warp::cors() + .allow_any_origin() + .allow_headers(vec!["content-type", "authorization"]) + .allow_methods(vec!["GET", "POST", "PUT", "DELETE", "OPTIONS"]); + + // Status endpoint + let sync_dir_status = Arc::clone(&sync_dir); + let status = warp::path("api") + .and(warp::path("status")) + .and(warp::get()) + .and_then(move || { + let sync_dir = Arc::clone(&sync_dir_status); + async move { + match sync_dir.lock().await.get_sync_status().await { + Ok(status) => Ok(warp::reply::json(&status)), + Err(_) => Err(warp::reject::reject()), + } + } + }); + + // File list endpoint + let sync_dir_files = Arc::clone(&sync_dir); + let files = warp::path("api") + .and(warp::path("files")) + .and(warp::get()) + .and_then(move || { + let sync_dir = Arc::clone(&sync_dir_files); + async move { + match sync_dir.lock().await.list_files_for_web().await { + Ok(files) => Ok(warp::reply::json(&files)), + Err(_) => Err(warp::reject::reject()), + } + } + }); + + // File download endpoint + let sync_dir_download = Arc::clone(&sync_dir); + let download = warp::path("api") + .and(warp::path("download")) + .and(warp::path::param::()) + .and(warp::get()) + .and_then(move |file_path: String| { + let sync_dir = Arc::clone(&sync_dir_download); + async move { + sync_dir.lock().await.download_file_for_web(file_path).await + } + }); + + // File upload endpoint + let sync_dir_upload = Arc::clone(&sync_dir); + let upload = warp::path("api") + .and(warp::path("upload")) + .and(warp::post()) + .and(warp::multipart::form().max_length(100 * 1024 * 1024)) // 100MB limit + .and_then(move |form: warp::multipart::FormData| { + let sync_dir = Arc::clone(&sync_dir_upload); + async move { + sync_dir.lock().await.handle_file_upload(form).await + } + }); + + // Connect via ticket endpoint + let sync_dir_connect = Arc::clone(&sync_dir); + let connect = warp::path("api") + .and(warp::path("connect")) + .and(warp::post()) + .and(warp::body::json()) + .and_then(move |req: ConnectRequest| { + let sync_dir = Arc::clone(&sync_dir_connect); + async move { + match sync_dir.lock().await.connect_with_ticket(req.ticket).await { + Ok(_) => Ok(warp::reply::json(&"Connected successfully")), + Err(e) => { + error!("Connection failed: {}", e); + Err(warp::reject::reject()) + } + } + } + }); + + // Generate ticket endpoint + let sync_dir_ticket = Arc::clone(&sync_dir); + let ticket = warp::path("api") + .and(warp::path("ticket")) + .and(warp::get()) + .and_then(move || { + let sync_dir = Arc::clone(&sync_dir_ticket); + async move { + match sync_dir.lock().await.generate_ticket().await { + Ok(ticket) => Ok(warp::reply::json(&ticket)), + Err(_) => Err(warp::reject::reject()), + } + } + }); + + // Serve static HTML file + let index = warp::get() + .and(warp::path::end()) + .and_then(|| async { + Ok::<_, warp::Rejection>(warp::reply::html(include_str!("../web/index.html"))) + }); + + let routes = status + .or(files) + .or(download) + .or(upload) + .or(connect) + .or(ticket) + .or(index) + .with(cors); + + println!("\n=== WEB INTERFACE STARTED ==="); + println!("🌐 Local: http://localhost:{}", port); + println!("📱 Mobile: http://YOUR_PC_IP:{}", port); + println!("===============================\n"); + + warp::serve(routes) + .run(([0, 0, 0, 0], port)) + .await; + + Ok(()) +} + diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..ee109c8 --- /dev/null +++ b/web/index.html @@ -0,0 +1,687 @@ + + + + + + Iroh File Sync + + + +
+
+

🔄 Iroh Sync

+
+
+ + Connecting... +
+
+
+
+
0
+
Files
+
+
+
0
+
Peers
+
+
+
+ +
+ +
+

🎫 Share & Connect

+ + + +
or
+ +
+ +
+ +
+ + +
+

📤 Upload Files

+
+
📁
+
Tap to select files
+
or drag & drop here
+
+ + +
+ + +
+

📋 Synced Files

+
+
Loading files...
+
+ +
+
+
+ + + + \ No newline at end of file diff --git a/web/index.html:Zone.Identifier b/web/index.html:Zone.Identifier new file mode 100644 index 0000000..e69de29