From 5850c3e8a39c5c6d05798668c27a88eeb3c8c5e2 Mon Sep 17 00:00:00 2001 From: lygn128 Date: Thu, 5 Jun 2025 10:00:00 +0000 Subject: [PATCH] bucket replication --- .gitignore | 2 +- Cargo.lock | 11059 ------------------ bucket_replicate_test.md | 45 + build_rustfs.sh | 21 + common/common/src/bucket_stats.rs | 73 + common/common/src/last_minute.rs | 132 +- common/common/src/lib.rs | 1 + crypto/src/encdec/decrypt.rs | 91 + ecstore/Cargo.toml | 11 +- ecstore/src/bucket/metadata.rs | 12 +- ecstore/src/bucket/metadata_sys.rs | 19 +- ecstore/src/bucket/mod.rs | 3 +- ecstore/src/bucket/replication/datatypes.rs | 27 + ecstore/src/bucket/replication/mod.rs | 1 + ecstore/src/bucket/tagging/mod.rs | 1 + ecstore/src/bucket/target/mod.rs | 79 +- ecstore/src/cmd/bucket_replication.rs | 2744 +++++ ecstore/src/cmd/bucket_replication_utils.rs | 55 + ecstore/src/cmd/bucket_targets.rs | 864 ++ ecstore/src/cmd/bucketreplicationhandler.rs | 0 ecstore/src/cmd/mod.rs | 2 + ecstore/src/disk/local.rs | 2 +- ecstore/src/heal/data_scanner.rs | 102 +- ecstore/src/lib.rs | 1 + ecstore/src/peer.rs | 40 +- ecstore/src/store.rs | 2 +- ecstore/src/store_api.rs | 14 +- ecstore/src/xhttp.rs | 1 + rustfs/Cargo.toml | 20 + rustfs/src/admin/handlers.rs | 284 +- rustfs/src/admin/mod.rs | 51 + rustfs/src/admin/router.rs | 3 +- rustfs/src/grpc.rs | 4 + rustfs/src/main.rs | 6 + rustfs/src/storage/ecfs.rs | 111 +- rustfs/src/storage/error.rs | 11 +- 36 files changed, 4748 insertions(+), 11146 deletions(-) delete mode 100644 Cargo.lock create mode 100644 bucket_replicate_test.md create mode 100755 build_rustfs.sh create mode 100644 common/common/src/bucket_stats.rs create mode 100644 ecstore/src/bucket/replication/datatypes.rs create mode 100644 ecstore/src/bucket/replication/mod.rs create mode 100644 ecstore/src/cmd/bucket_replication.rs create mode 100644 ecstore/src/cmd/bucket_replication_utils.rs create mode 100644 ecstore/src/cmd/bucket_targets.rs create mode 100644 ecstore/src/cmd/bucketreplicationhandler.rs create mode 100644 ecstore/src/cmd/mod.rs diff --git a/.gitignore b/.gitignore index 8eb6191c..ef532b66 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,4 @@ deploy/certs/* .rustfs.sys .cargo profile.json -.docker/openobserve-otel/data \ No newline at end of file +.docker/openobserve-otel/data diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index fdc90b69..00000000 --- a/Cargo.lock +++ /dev/null @@ -1,11059 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common 0.1.6", - "generic-array", -] - -[[package]] -name = "aes" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "aes-gcm" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - -[[package]] -name = "ahash" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" -dependencies = [ - "getrandom 0.2.15", - "once_cell", - "version_check", -] - -[[package]] -name = "ahash" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" -dependencies = [ - "cfg-if", - "const-random", - "getrandom 0.2.15", - "once_cell", - "version_check", - "zerocopy 0.7.35", -] - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "alloc-no-stdlib" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" - -[[package]] -name = "alloc-stdlib" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" -dependencies = [ - "alloc-no-stdlib", -] - -[[package]] -name = "allocator-api2" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" - -[[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.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" - -[[package]] -name = "anstyle-parse" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" -dependencies = [ - "anstyle", - "once_cell", - "windows-sys 0.59.0", -] - -[[package]] -name = "anyhow" -version = "1.0.98" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" - -[[package]] -name = "api" -version = "0.0.1" -dependencies = [ - "async-trait", - "bytes", - "chrono", - "common", - "datafusion", - "ecstore", - "futures", - "futures-core", - "http", - "object_store", - "pin-project-lite", - "s3s", - "snafu", - "tokio", - "tokio-util", - "tracing", - "transform-stream", - "url", -] - -[[package]] -name = "appauth" -version = "0.0.1" -dependencies = [ - "base64-simd", - "common", - "hex-simd", - "rand 0.8.5", - "rsa", - "serde", - "serde_json", -] - -[[package]] -name = "arbitrary" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" -dependencies = [ - "derive_arbitrary", -] - -[[package]] -name = "arc-swap" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" - -[[package]] -name = "argon2" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" -dependencies = [ - "base64ct", - "blake2", - "cpufeatures", - "password-hash", -] - -[[package]] -name = "arraydeque" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d902e3d592a523def97af8f317b08ce16b7ab854c1985a0c671e6f15cebc236" - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "arrow" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ec52ba94edeed950e4a41f75d35376df196e8cb04437f7280a5aa49f20f796" -dependencies = [ - "arrow-arith", - "arrow-array", - "arrow-buffer", - "arrow-cast", - "arrow-csv", - "arrow-data", - "arrow-ipc", - "arrow-json", - "arrow-ord", - "arrow-row", - "arrow-schema", - "arrow-select", - "arrow-string", -] - -[[package]] -name = "arrow-arith" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc766fdacaf804cb10c7c70580254fcdb5d55cdfda2bc57b02baf5223a3af9e" -dependencies = [ - "arrow-array", - "arrow-buffer", - "arrow-data", - "arrow-schema", - "chrono", - "num", -] - -[[package]] -name = "arrow-array" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12fcdb3f1d03f69d3ec26ac67645a8fe3f878d77b5ebb0b15d64a116c212985" -dependencies = [ - "ahash 0.8.11", - "arrow-buffer", - "arrow-data", - "arrow-schema", - "chrono", - "chrono-tz", - "half", - "hashbrown 0.15.2", - "num", -] - -[[package]] -name = "arrow-buffer" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "263f4801ff1839ef53ebd06f99a56cecd1dbaf314ec893d93168e2e860e0291c" -dependencies = [ - "bytes", - "half", - "num", -] - -[[package]] -name = "arrow-cast" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede6175fbc039dfc946a61c1b6d42fd682fcecf5ab5d148fbe7667705798cac9" -dependencies = [ - "arrow-array", - "arrow-buffer", - "arrow-data", - "arrow-schema", - "arrow-select", - "atoi", - "base64 0.22.1", - "chrono", - "comfy-table", - "half", - "lexical-core", - "num", - "ryu", -] - -[[package]] -name = "arrow-csv" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1644877d8bc9a0ef022d9153dc29375c2bda244c39aec05a91d0e87ccf77995f" -dependencies = [ - "arrow-array", - "arrow-cast", - "arrow-schema", - "chrono", - "csv", - "csv-core", - "lazy_static", - "regex", -] - -[[package]] -name = "arrow-data" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61cfdd7d99b4ff618f167e548b2411e5dd2c98c0ddebedd7df433d34c20a4429" -dependencies = [ - "arrow-buffer", - "arrow-schema", - "half", - "num", -] - -[[package]] -name = "arrow-ipc" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ff528658b521e33905334723b795ee56b393dbe9cf76c8b1f64b648c65a60c" -dependencies = [ - "arrow-array", - "arrow-buffer", - "arrow-data", - "arrow-schema", - "flatbuffers 24.12.23", - "lz4_flex", -] - -[[package]] -name = "arrow-json" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee5b4ca98a7fb2efb9ab3309a5d1c88b5116997ff93f3147efdc1062a6158e9" -dependencies = [ - "arrow-array", - "arrow-buffer", - "arrow-cast", - "arrow-data", - "arrow-schema", - "chrono", - "half", - "indexmap 2.9.0", - "lexical-core", - "memchr", - "num", - "serde", - "serde_json", - "simdutf8", -] - -[[package]] -name = "arrow-ord" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a3334a743bd2a1479dbc635540617a3923b4b2f6870f37357339e6b5363c21" -dependencies = [ - "arrow-array", - "arrow-buffer", - "arrow-data", - "arrow-schema", - "arrow-select", -] - -[[package]] -name = "arrow-row" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d1d7a7291d2c5107e92140f75257a99343956871f3d3ab33a7b41532f79cb68" -dependencies = [ - "arrow-array", - "arrow-buffer", - "arrow-data", - "arrow-schema", - "half", -] - -[[package]] -name = "arrow-schema" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cfaf5e440be44db5413b75b72c2a87c1f8f0627117d110264048f2969b99e9" - -[[package]] -name = "arrow-select" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69efcd706420e52cd44f5c4358d279801993846d1c2a8e52111853d61d55a619" -dependencies = [ - "ahash 0.8.11", - "arrow-array", - "arrow-buffer", - "arrow-data", - "arrow-schema", - "num", -] - -[[package]] -name = "arrow-string" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a21546b337ab304a32cfc0770f671db7411787586b45b78b4593ae78e64e2b03" -dependencies = [ - "arrow-array", - "arrow-buffer", - "arrow-data", - "arrow-schema", - "arrow-select", - "memchr", - "num", - "regex", - "regex-syntax 0.8.5", -] - -[[package]] -name = "ashpd" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd884d7c72877a94102c3715f3b1cd09ff4fac28221add3e57cfbe25c236d093" -dependencies = [ - "enumflags2", - "futures-channel", - "futures-util", - "rand 0.8.5", - "serde", - "serde_repr", - "tokio", - "url", - "zbus 4.4.0", -] - -[[package]] -name = "ashpd" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6cbdf310d77fd3aaee6ea2093db7011dc2d35d2eb3481e5607f1f8d942ed99df" -dependencies = [ - "enumflags2", - "futures-channel", - "futures-util", - "rand 0.9.1", - "raw-window-handle 0.6.2", - "serde", - "serde_repr", - "tokio", - "url", - "zbus 5.5.0", -] - -[[package]] -name = "async-broadcast" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[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-compression" -version = "0.4.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06575e6a9673580f52661c92107baabffbf41e2141373441cbcdc47cb733003c" -dependencies = [ - "bzip2", - "flate2", - "futures-core", - "memchr", - "pin-project-lite", - "tokio", - "xz2", - "zstd", - "zstd-safe", -] - -[[package]] -name = "async-io" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43a2b323ccce0a1d90b449fd71f2a06ca7faa7c54c2751f06c9bd851fc061059" -dependencies = [ - "async-lock", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix 0.38.44", - "slab", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] - -[[package]] -name = "async-process" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" -dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix 0.38.44", - "tracing", -] - -[[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.100", -] - -[[package]] -name = "async-signal" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix 0.38.44", - "signal-hook-registry", - "slab", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - -[[package]] -name = "async-trait" -version = "0.1.88" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "async_zip" -version = "0.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b9f7252833d5ed4b00aa9604b563529dd5e11de9c23615de2dcdf91eb87b52" -dependencies = [ - "crc32fast", - "futures-lite", - "pin-project", - "thiserror 1.0.69", - "tokio", - "tokio-util", -] - -[[package]] -name = "atk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" -dependencies = [ - "atk-sys", - "glib", - "libc", -] - -[[package]] -name = "atk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "atoi" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" -dependencies = [ - "num-traits", -] - -[[package]] -name = "atomic-waker" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" - -[[package]] -name = "atomic_enum" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99e1aca718ea7b89985790c94aad72d77533063fe00bc497bb79a7c2dae6a661" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "autocfg" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" - -[[package]] -name = "aws-lc-rs" -version = "1.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b756939cb2f8dc900aa6dcd505e6e2428e9cae7ff7b028c49e3946efa70878" -dependencies = [ - "aws-lc-sys", - "zeroize", -] - -[[package]] -name = "aws-lc-sys" -version = "0.28.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ddeb19ee86cb16ecfc871e5b0660aff6285760957aaedda6284cf0e790d3769" -dependencies = [ - "bindgen", - "cc", - "cmake", - "dunce", - "fs_extra", -] - -[[package]] -name = "axum" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" -dependencies = [ - "axum-core", - "bytes", - "form_urlencoded", - "futures-util", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-util", - "itoa 1.0.15", - "matchit", - "memchr", - "mime", - "percent-encoding", - "pin-project-lite", - "rustversion", - "serde", - "serde_json", - "serde_path_to_error", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tower 0.5.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-core" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "sync_wrapper", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "axum-extra" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45bf463831f5131b7d3c756525b305d40f1185b688565648a92e1392ca35713d" -dependencies = [ - "axum", - "axum-core", - "bytes", - "futures-util", - "http", - "http-body", - "http-body-util", - "mime", - "pin-project-lite", - "rustversion", - "serde", - "tower 0.5.2", - "tower-layer", - "tower-service", -] - -[[package]] -name = "axum-server" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495c05f60d6df0093e8fb6e74aa5846a0ad06abaf96d76166283720bf740f8ab" -dependencies = [ - "arc-swap", - "bytes", - "fs-err", - "http", - "http-body", - "hyper", - "hyper-util", - "pin-project-lite", - "rustls 0.23.27", - "rustls-pemfile", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.2", - "tower-service", -] - -[[package]] -name = "backon" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd0b50b1b78dbadd44ab18b3c794e496f3a139abb9fbc27d9c94c4eebbb96496" -dependencies = [ - "fastrand", - "gloo-timers", - "tokio", -] - -[[package]] -name = "backtrace" -version = "0.3.74" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - -[[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 = "base64-simd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "339abbe78e73178762e23bea9dfd08e697eb3f3301cd4be981c0f78ba5859195" -dependencies = [ - "outref", - "vsimd", -] - -[[package]] -name = "base64ct" -version = "1.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" - -[[package]] -name = "bigdecimal" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a22f228ab7a1b23027ccc6c350b72868017af7ea8356fbdf19f8d991c690013" -dependencies = [ - "autocfg", - "libm", - "num-bigint", - "num-integer", - "num-traits", -] - -[[package]] -name = "bindgen" -version = "0.69.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088" -dependencies = [ - "bitflags 2.9.0", - "cexpr", - "clang-sys", - "itertools 0.12.1", - "lazy_static", - "lazycell", - "log", - "prettyplease", - "proc-macro2", - "quote", - "regex", - "rustc-hash 1.1.0", - "shlex", - "syn 2.0.100", - "which", -] - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "bitflags" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" -dependencies = [ - "serde", -] - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "blake3" -version = "1.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" -dependencies = [ - "arrayref", - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", -] - -[[package]] -name = "block" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" - -[[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 = "block-buffer" -version = "0.11.0-rc.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a229bfd78e4827c91b9b95784f69492c1b77c1ab75a45a8a037b139215086f94" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2 0.5.2", -] - -[[package]] -name = "block2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "340d2f0bdb2a43c1d3cd40513185b2bd7def0aa1052f956455114bc98f82dcf2" -dependencies = [ - "objc2 0.6.1", -] - -[[package]] -name = "blocking" -version = "1.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" -dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", -] - -[[package]] -name = "brotli" -version = "7.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", -] - -[[package]] -name = "brotli-decompressor" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a334ef7c9e23abf0ce748e8cd309037da93e606ad52eb372e4ce327a0dcfbdfd" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", -] - -[[package]] -name = "bumpalo" -version = "3.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" - -[[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" - -[[package]] -name = "bytesize" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c8f83209414aacf0eeae3cf730b18d6981697fba62f200fcfb92b9f082acba" - -[[package]] -name = "bytestring" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" -dependencies = [ - "bytes", -] - -[[package]] -name = "bzip2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49ecfb22d906f800d4fe833b6282cf4dc1c298f5057ca0b5445e5c209735ca47" -dependencies = [ - "bzip2-sys", -] - -[[package]] -name = "bzip2-sys" -version = "0.1.13+1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225bff33b2141874fe80d71e07d6eec4f85c5c216453dd96388240f96e1acc14" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "cairo-rs" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" -dependencies = [ - "bitflags 2.9.0", - "cairo-sys-rs", - "glib", - "libc", - "once_cell", - "thiserror 1.0.69", -] - -[[package]] -name = "cairo-sys-rs" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" -dependencies = [ - "glib-sys", - "libc", - "system-deps", -] - -[[package]] -name = "camino" -version = "1.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo-platform" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea" -dependencies = [ - "serde", -] - -[[package]] -name = "cargo_metadata" -version = "0.19.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd5eb614ed4c27c5d706420e4320fbe3216ab31fa1c33cd8246ac36dae4479ba" -dependencies = [ - "camino", - "cargo-platform", - "semver", - "serde", - "serde_json", - "thiserror 2.0.12", -] - -[[package]] -name = "cc" -version = "1.2.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" -dependencies = [ - "jobserver", - "libc", - "shlex", -] - -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - -[[package]] -name = "cexpr" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" -dependencies = [ - "nom 7.1.3", -] - -[[package]] -name = "cfb" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" -dependencies = [ - "byteorder", - "fnv", - "uuid", -] - -[[package]] -name = "cfg-expr" -version = "0.15.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" -dependencies = [ - "smallvec", - "target-lexicon", -] - -[[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 = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - -[[package]] -name = "chrono" -version = "0.4.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" -dependencies = [ - "android-tzdata", - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", -] - -[[package]] -name = "chrono-tz" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3" -dependencies = [ - "chrono", - "chrono-tz-build", - "phf 0.11.3", -] - -[[package]] -name = "chrono-tz-build" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402" -dependencies = [ - "parse-zoneinfo", - "phf_codegen 0.11.3", -] - -[[package]] -name = "ciborium" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" -dependencies = [ - "ciborium-io", - "ciborium-ll", - "serde", -] - -[[package]] -name = "ciborium-io" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" - -[[package]] -name = "ciborium-ll" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" -dependencies = [ - "ciborium-io", - "half", -] - -[[package]] -name = "cipher" -version = "0.4.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" -dependencies = [ - "crypto-common 0.1.6", - "inout", - "zeroize", -] - -[[package]] -name = "clang-sys" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" -dependencies = [ - "glob", - "libc", - "libloading 0.8.6", -] - -[[package]] -name = "clap" -version = "4.5.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd60e63e9be68e5fb56422e397cf9baddded06dae1d2e523401542383bc72a9f" -dependencies = [ - "clap_builder", - "clap_derive", -] - -[[package]] -name = "clap_builder" -version = "4.5.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89cc6392a1f72bbeb820d71f32108f61fdaf18bc526e1d23954168a67759ef51" -dependencies = [ - "anstream", - "anstyle", - "clap_lex", - "strsim", -] - -[[package]] -name = "clap_derive" -version = "4.5.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "clap_lex" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" - -[[package]] -name = "cmake" -version = "0.1.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0" -dependencies = [ - "cc", -] - -[[package]] -name = "cocoa" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" -dependencies = [ - "bitflags 1.3.2", - "block", - "cocoa-foundation 0.1.2", - "core-foundation 0.9.4", - "core-graphics 0.23.2", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" -dependencies = [ - "bitflags 2.9.0", - "block", - "cocoa-foundation 0.2.0", - "core-foundation 0.10.0", - "core-graphics 0.24.0", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" -dependencies = [ - "bitflags 1.3.2", - "block", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d" -dependencies = [ - "bitflags 2.9.0", - "block", - "core-foundation 0.10.0", - "core-graphics-types 0.2.0", - "libc", - "objc", -] - -[[package]] -name = "colorchoice" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" - -[[package]] -name = "combine" -version = "4.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" -dependencies = [ - "bytes", - "memchr", -] - -[[package]] -name = "comfy-table" -version = "7.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a65ebfec4fb190b6f90e944a817d60499ee0744e582530e2c9900a22e591d9a" -dependencies = [ - "unicode-segmentation", - "unicode-width", -] - -[[package]] -name = "common" -version = "0.0.1" -dependencies = [ - "async-trait", - "lazy_static", - "scopeguard", - "tokio", - "tonic 0.13.1", - "tracing-error", -] - -[[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 = "config" -version = "0.15.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595aae20e65c3be792d05818e8c63025294ac3cb7e200f11459063a352a6ef80" -dependencies = [ - "async-trait", - "convert_case 0.6.0", - "json5", - "pathdiff", - "ron", - "rust-ini", - "serde", - "serde_json", - "toml", - "winnow 0.7.6", - "yaml-rust2", -] - -[[package]] -name = "console_error_panic_hook" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] - -[[package]] -name = "const-oid" -version = "0.9.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" - -[[package]] -name = "const-oid" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dabb6555f92fb9ee4140454eb5dcd14c7960e1225c6d1a6cc361f032947713e" - -[[package]] -name = "const-random" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" -dependencies = [ - "const-random-macro", -] - -[[package]] -name = "const-random-macro" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" -dependencies = [ - "getrandom 0.2.15", - "once_cell", - "tiny-keccak", -] - -[[package]] -name = "const-serialize" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08259976d62c715c4826cb4a3d64a3a9e5c5f68f964ff6087319857f569f93a6" -dependencies = [ - "const-serialize-macro", - "serde", -] - -[[package]] -name = "const-serialize-macro" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04382d0d9df7434af6b1b49ea1a026ef39df1b0738b1cc373368cf175354f6eb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "const-str" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e991226a70654b49d34de5ed064885f0bef0348a8e70018b8ff1ac80aa984a2" -dependencies = [ - "const-str-proc-macro", -] - -[[package]] -name = "const-str-proc-macro" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d1c4c3cb85e5856b34e829af0035d7154f8c2889b15bbf43c8a6c6786dcab5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "const_format" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" -dependencies = [ - "const_format_proc_macros", -] - -[[package]] -name = "const_format_proc_macros" -version = "0.2.34" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" -dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", -] - -[[package]] -name = "constant_time_eq" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" - -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - -[[package]] -name = "convert_case" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" -dependencies = [ - "unicode-segmentation", -] - -[[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" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "core-foundation-sys" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" - -[[package]] -name = "core-graphics" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" -dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", - "core-graphics-types 0.2.0", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" -dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", - "libc", -] - -[[package]] -name = "cpufeatures" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" -dependencies = [ - "libc", -] - -[[package]] -name = "crc" -version = "3.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" -dependencies = [ - "crc-catalog", -] - -[[package]] -name = "crc-catalog" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" - -[[package]] -name = "crc32c" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a47af21622d091a8f0fb295b88bc886ac74efcc613efc19f5d0b21de5c89e47" -dependencies = [ - "rustc_version", -] - -[[package]] -name = "crc32fast" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "crc64fast-nvme" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4955638f00a809894c947f85a024020a20815b65a5eea633798ea7924edab2b3" -dependencies = [ - "crc", -] - -[[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-queue" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" -dependencies = [ - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" - -[[package]] -name = "crunchy" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929" - -[[package]] -name = "crypto" -version = "0.0.1" -dependencies = [ - "aes-gcm", - "argon2", - "cfg-if", - "chacha20poly1305", - "jsonwebtoken", - "pbkdf2", - "rand 0.8.5", - "serde_json", - "sha2 0.10.9", - "test-case", - "thiserror 2.0.12", - "time", -] - -[[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 0.6.4", - "typenum", -] - -[[package]] -name = "crypto-common" -version = "0.2.0-rc.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170d71b5b14dec99db7739f6fc7d6ec2db80b78c3acb77db48392ccc3d8a9ea0" -dependencies = [ - "hybrid-array", -] - -[[package]] -name = "cssparser" -version = "0.27.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "754b69d351cdc2d8ee09ae203db831e005560fc6030da058f86ad60c92a9cb0a" -dependencies = [ - "cssparser-macros", - "dtoa-short", - "itoa 0.4.8", - "matches", - "phf 0.8.0", - "proc-macro2", - "quote", - "smallvec", - "syn 1.0.109", -] - -[[package]] -name = "cssparser-macros" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" -dependencies = [ - "quote", - "syn 2.0.100", -] - -[[package]] -name = "csv" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" -dependencies = [ - "csv-core", - "itoa 1.0.15", - "ryu", - "serde", -] - -[[package]] -name = "csv-core" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" -dependencies = [ - "memchr", -] - -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core", - "darling_macro", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.100", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core", - "quote", - "syn 2.0.100", -] - -[[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 0.9.10", -] - -[[package]] -name = "dashmap" -version = "6.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" -dependencies = [ - "cfg-if", - "crossbeam-utils", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "data-encoding" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" - -[[package]] -name = "datafusion" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "914e6f9525599579abbd90b0f7a55afcaaaa40350b9e9ed52563f126dfe45fd3" -dependencies = [ - "arrow", - "arrow-ipc", - "arrow-schema", - "async-trait", - "bytes", - "bzip2", - "chrono", - "datafusion-catalog", - "datafusion-catalog-listing", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-datasource", - "datafusion-execution", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-functions", - "datafusion-functions-aggregate", - "datafusion-functions-nested", - "datafusion-functions-table", - "datafusion-functions-window", - "datafusion-macros", - "datafusion-optimizer", - "datafusion-physical-expr", - "datafusion-physical-expr-common", - "datafusion-physical-optimizer", - "datafusion-physical-plan", - "datafusion-sql", - "flate2", - "futures", - "itertools 0.14.0", - "log", - "object_store", - "parking_lot 0.12.3", - "parquet", - "rand 0.8.5", - "regex", - "sqlparser", - "tempfile", - "tokio", - "url", - "uuid", - "xz2", - "zstd", -] - -[[package]] -name = "datafusion-catalog" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "998a6549e6ee4ee3980e05590b2960446a56b343ea30199ef38acd0e0b9036e2" -dependencies = [ - "arrow", - "async-trait", - "dashmap 6.1.0", - "datafusion-common", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-plan", - "datafusion-sql", - "futures", - "itertools 0.14.0", - "log", - "parking_lot 0.12.3", -] - -[[package]] -name = "datafusion-catalog-listing" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ac10096a5b3c0d8a227176c0e543606860842e943594ccddb45cf42a526e43" -dependencies = [ - "arrow", - "async-trait", - "datafusion-catalog", - "datafusion-common", - "datafusion-datasource", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-expr", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "futures", - "log", - "object_store", - "tokio", -] - -[[package]] -name = "datafusion-common" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f53d7ec508e1b3f68bd301cee3f649834fad51eff9240d898a4b2614cfd0a7a" -dependencies = [ - "ahash 0.8.11", - "arrow", - "arrow-ipc", - "base64 0.22.1", - "half", - "hashbrown 0.14.5", - "indexmap 2.9.0", - "libc", - "log", - "object_store", - "parquet", - "paste", - "recursive", - "sqlparser", - "tokio", - "web-time", -] - -[[package]] -name = "datafusion-common-runtime" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0fcf41523b22e14cc349b01526e8b9f59206653037f2949a4adbfde5f8cb668" -dependencies = [ - "log", - "tokio", -] - -[[package]] -name = "datafusion-datasource" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf7f37ad8b6e88b46c7eeab3236147d32ea64b823544f498455a8d9042839c92" -dependencies = [ - "arrow", - "async-compression", - "async-trait", - "bytes", - "bzip2", - "chrono", - "datafusion-catalog", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-execution", - "datafusion-expr", - "datafusion-physical-expr", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "flate2", - "futures", - "glob", - "itertools 0.14.0", - "log", - "object_store", - "rand 0.8.5", - "tokio", - "tokio-util", - "url", - "xz2", - "zstd", -] - -[[package]] -name = "datafusion-doc" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7db7a0239fd060f359dc56c6e7db726abaa92babaed2fb2e91c3a8b2fff8b256" - -[[package]] -name = "datafusion-execution" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0938f9e5b6bc5782be4111cdfb70c02b7b5451bf34fd57e4de062a7f7c4e31f1" -dependencies = [ - "arrow", - "dashmap 6.1.0", - "datafusion-common", - "datafusion-expr", - "futures", - "log", - "object_store", - "parking_lot 0.12.3", - "rand 0.8.5", - "tempfile", - "url", -] - -[[package]] -name = "datafusion-expr" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b36c28b00b00019a8695ad7f1a53ee1673487b90322ecbd604e2cf32894eb14f" -dependencies = [ - "arrow", - "chrono", - "datafusion-common", - "datafusion-doc", - "datafusion-expr-common", - "datafusion-functions-aggregate-common", - "datafusion-functions-window-common", - "datafusion-physical-expr-common", - "indexmap 2.9.0", - "paste", - "recursive", - "serde_json", - "sqlparser", -] - -[[package]] -name = "datafusion-expr-common" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f0a851a436c5a2139189eb4617a54e6a9ccb9edc96c4b3c83b3bb7c58b950e" -dependencies = [ - "arrow", - "datafusion-common", - "indexmap 2.9.0", - "itertools 0.14.0", - "paste", -] - -[[package]] -name = "datafusion-functions" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3196e37d7b65469fb79fee4f05e5bb58a456831035f9a38aa5919aeb3298d40" -dependencies = [ - "arrow", - "arrow-buffer", - "base64 0.22.1", - "blake2", - "blake3", - "chrono", - "datafusion-common", - "datafusion-doc", - "datafusion-execution", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-macros", - "hex", - "itertools 0.14.0", - "log", - "md-5", - "rand 0.8.5", - "regex", - "sha2 0.10.9", - "unicode-segmentation", - "uuid", -] - -[[package]] -name = "datafusion-functions-aggregate" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfc2d074d5ee4d9354fdcc9283d5b2b9037849237ddecb8942a29144b77ca05" -dependencies = [ - "ahash 0.8.11", - "arrow", - "datafusion-common", - "datafusion-doc", - "datafusion-execution", - "datafusion-expr", - "datafusion-functions-aggregate-common", - "datafusion-macros", - "datafusion-physical-expr", - "datafusion-physical-expr-common", - "half", - "log", - "paste", -] - -[[package]] -name = "datafusion-functions-aggregate-common" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cbceba0f98d921309a9121b702bcd49289d383684cccabf9a92cda1602f3bbb" -dependencies = [ - "ahash 0.8.11", - "arrow", - "datafusion-common", - "datafusion-expr-common", - "datafusion-physical-expr-common", -] - -[[package]] -name = "datafusion-functions-nested" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170e27ce4baa27113ddf5f77f1a7ec484b0dbeda0c7abbd4bad3fc609c8ab71a" -dependencies = [ - "arrow", - "arrow-ord", - "datafusion-common", - "datafusion-doc", - "datafusion-execution", - "datafusion-expr", - "datafusion-functions", - "datafusion-functions-aggregate", - "datafusion-macros", - "datafusion-physical-expr-common", - "itertools 0.14.0", - "log", - "paste", -] - -[[package]] -name = "datafusion-functions-table" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d3a06a7f0817ded87b026a437e7e51de7f59d48173b0a4e803aa896a7bd6bb5" -dependencies = [ - "arrow", - "async-trait", - "datafusion-catalog", - "datafusion-common", - "datafusion-expr", - "datafusion-physical-plan", - "parking_lot 0.12.3", - "paste", -] - -[[package]] -name = "datafusion-functions-window" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6c608b66496a1e05e3d196131eb9bebea579eed1f59e88d962baf3dda853bc6" -dependencies = [ - "datafusion-common", - "datafusion-doc", - "datafusion-expr", - "datafusion-functions-window-common", - "datafusion-macros", - "datafusion-physical-expr", - "datafusion-physical-expr-common", - "log", - "paste", -] - -[[package]] -name = "datafusion-functions-window-common" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da2f9d83348957b4ad0cd87b5cb9445f2651863a36592fe5484d43b49a5f8d82" -dependencies = [ - "datafusion-common", - "datafusion-physical-expr-common", -] - -[[package]] -name = "datafusion-macros" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4800e1ff7ecf8f310887e9b54c9c444b8e215ccbc7b21c2f244cfae373b1ece7" -dependencies = [ - "datafusion-expr", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "datafusion-optimizer" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "971c51c54cd309001376fae752fb15a6b41750b6d1552345c46afbfb6458801b" -dependencies = [ - "arrow", - "chrono", - "datafusion-common", - "datafusion-expr", - "datafusion-physical-expr", - "indexmap 2.9.0", - "itertools 0.14.0", - "log", - "recursive", - "regex", - "regex-syntax 0.8.5", -] - -[[package]] -name = "datafusion-physical-expr" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1447c2c6bc8674a16be4786b4abf528c302803fafa186aa6275692570e64d85" -dependencies = [ - "ahash 0.8.11", - "arrow", - "datafusion-common", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-functions-aggregate-common", - "datafusion-physical-expr-common", - "half", - "hashbrown 0.14.5", - "indexmap 2.9.0", - "itertools 0.14.0", - "log", - "paste", - "petgraph", -] - -[[package]] -name = "datafusion-physical-expr-common" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f8c25dcd069073a75b3d2840a79d0f81e64bdd2c05f2d3d18939afb36a7dcb" -dependencies = [ - "ahash 0.8.11", - "arrow", - "datafusion-common", - "datafusion-expr-common", - "hashbrown 0.14.5", - "itertools 0.14.0", -] - -[[package]] -name = "datafusion-physical-optimizer" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68da5266b5b9847c11d1b3404ee96b1d423814e1973e1ad3789131e5ec912763" -dependencies = [ - "arrow", - "datafusion-common", - "datafusion-execution", - "datafusion-expr", - "datafusion-expr-common", - "datafusion-physical-expr", - "datafusion-physical-expr-common", - "datafusion-physical-plan", - "itertools 0.14.0", - "log", - "recursive", -] - -[[package]] -name = "datafusion-physical-plan" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88cc160df00e413e370b3b259c8ea7bfbebc134d32de16325950e9e923846b7f" -dependencies = [ - "ahash 0.8.11", - "arrow", - "arrow-ord", - "arrow-schema", - "async-trait", - "chrono", - "datafusion-common", - "datafusion-common-runtime", - "datafusion-execution", - "datafusion-expr", - "datafusion-functions-window-common", - "datafusion-physical-expr", - "datafusion-physical-expr-common", - "futures", - "half", - "hashbrown 0.14.5", - "indexmap 2.9.0", - "itertools 0.14.0", - "log", - "parking_lot 0.12.3", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "datafusion-sql" -version = "46.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "325a212b67b677c0eb91447bf9a11b630f9fc4f62d8e5d145bf859f5a6b29e64" -dependencies = [ - "arrow", - "bigdecimal", - "datafusion-common", - "datafusion-expr", - "indexmap 2.9.0", - "log", - "recursive", - "regex", - "sqlparser", -] - -[[package]] -name = "dbus" -version = "0.9.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bb21987b9fb1613058ba3843121dd18b163b254d8a6e797e144cbac14d96d1b" -dependencies = [ - "libc", - "libdbus-sys", - "winapi", -] - -[[package]] -name = "dbus-secret-service" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42a16374481d92aed73ae45b1f120207d8e71d24fb89f357fadbd8f946fd84b" -dependencies = [ - "dbus", - "futures-util", - "num", - "once_cell", - "rand 0.8.5", -] - -[[package]] -name = "deflate64" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b" - -[[package]] -name = "der" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" -dependencies = [ - "const-oid 0.9.6", - "pem-rfc7468", - "zeroize", -] - -[[package]] -name = "deranged" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" -dependencies = [ - "powerfmt", - "serde", -] - -[[package]] -name = "derive_arbitrary" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "derive_builder" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947" -dependencies = [ - "derive_builder_macro", -] - -[[package]] -name = "derive_builder_core" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "derive_builder_macro" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" -dependencies = [ - "derive_builder_core", - "syn 2.0.100", -] - -[[package]] -name = "derive_more" -version = "0.99.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3da29a38df43d6f156149c9b43ded5e018ddff2a855cf2cfd62e8cd7d079c69f" -dependencies = [ - "convert_case 0.4.0", - "proc-macro2", - "quote", - "rustc_version", - "syn 2.0.100", -] - -[[package]] -name = "digest" -version = "0.10.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" -dependencies = [ - "block-buffer 0.10.4", - "const-oid 0.9.6", - "crypto-common 0.1.6", - "subtle", -] - -[[package]] -name = "digest" -version = "0.11.0-pre.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c478574b20020306f98d61c8ca3322d762e1ff08117422ac6106438605ea516" -dependencies = [ - "block-buffer 0.11.0-rc.4", - "const-oid 0.10.1", - "crypto-common 0.2.0-rc.2", - "subtle", -] - -[[package]] -name = "dioxus" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a247114500f1a78e87022defa8173de847accfada8e8809dfae23a118a580c" -dependencies = [ - "dioxus-cli-config", - "dioxus-config-macro", - "dioxus-core", - "dioxus-core-macro", - "dioxus-desktop", - "dioxus-devtools", - "dioxus-document", - "dioxus-fullstack", - "dioxus-history", - "dioxus-hooks", - "dioxus-html", - "dioxus-logger", - "dioxus-mobile", - "dioxus-router", - "dioxus-signals", - "dioxus-web", - "manganis", - "warnings", -] - -[[package]] -name = "dioxus-cli-config" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdd16948f1ffdb068dd9a64812158073a4250e2af4e98ea31fdac0312e6bce86" -dependencies = [ - "wasm-bindgen", -] - -[[package]] -name = "dioxus-config-macro" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cbf582fbb1c32d34a1042ea675469065574109c95154468710a4d73ee98b49" -dependencies = [ - "proc-macro2", - "quote", -] - -[[package]] -name = "dioxus-core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c03f451a119e47433c16e2d8eb5b15bf7d6e6734eb1a4c47574e6711dadff8d" -dependencies = [ - "const_format", - "dioxus-core-types", - "futures-channel", - "futures-util", - "generational-box", - "longest-increasing-subsequence", - "rustc-hash 1.1.0", - "rustversion", - "serde", - "slab", - "slotmap", - "tracing", - "warnings", -] - -[[package]] -name = "dioxus-core-macro" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "105c954caaaedf8cd10f3d1ba576b01e18aa8d33ad435182125eefe488cf0064" -dependencies = [ - "convert_case 0.6.0", - "dioxus-rsx", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "dioxus-core-types" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91a82fccfa48574eb7aa183e297769540904694844598433a9eb55896ad9f93b" -dependencies = [ - "once_cell", -] - -[[package]] -name = "dioxus-desktop" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b0cca3e7a10a4a3df37ea52c4cc7a53e5c9233489e03ee3f2829471fc3099a" -dependencies = [ - "async-trait", - "base64 0.22.1", - "cocoa 0.25.0", - "core-foundation 0.9.4", - "dioxus-cli-config", - "dioxus-core", - "dioxus-devtools", - "dioxus-document", - "dioxus-history", - "dioxus-hooks", - "dioxus-html", - "dioxus-interpreter-js", - "dioxus-signals", - "dunce", - "futures-channel", - "futures-util", - "generational-box", - "global-hotkey", - "infer", - "jni", - "lazy-js-bundle", - "muda 0.11.5", - "ndk", - "ndk-context", - "ndk-sys", - "objc", - "objc_id", - "once_cell", - "rfd 0.14.1", - "rustc-hash 1.1.0", - "serde", - "serde_json", - "signal-hook", - "slab", - "tao", - "thiserror 1.0.69", - "tokio", - "tracing", - "tray-icon", - "urlencoding", - "webbrowser", - "wry", -] - -[[package]] -name = "dioxus-devtools" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712a7300f1e8181218187b03502044157eef04e0a25b518117c5ef9ae1096880" -dependencies = [ - "dioxus-core", - "dioxus-devtools-types", - "dioxus-signals", - "serde", - "serde_json", - "tracing", - "tungstenite", - "warnings", -] - -[[package]] -name = "dioxus-devtools-types" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f62434973c0c9c5a3bc42e9cd5e7070401c2062a437fb5528f318c3e42ebf4ff" -dependencies = [ - "dioxus-core", - "serde", -] - -[[package]] -name = "dioxus-document" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "802a2014d1662b6615eec0a275745822ee4fc66aacd9d0f2fb33d6c8da79b8f2" -dependencies = [ - "dioxus-core", - "dioxus-core-macro", - "dioxus-core-types", - "dioxus-html", - "futures-channel", - "futures-util", - "generational-box", - "lazy-js-bundle", - "serde", - "serde_json", - "tracing", -] - -[[package]] -name = "dioxus-fullstack" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe99b48a1348eec385b5c4bd3e80fd863b0d3b47257d34e2ddc58754dec5d128" -dependencies = [ - "base64 0.22.1", - "bytes", - "ciborium", - "dioxus-desktop", - "dioxus-devtools", - "dioxus-history", - "dioxus-lib", - "dioxus-mobile", - "dioxus-web", - "dioxus_server_macro", - "futures-channel", - "futures-util", - "generational-box", - "once_cell", - "serde", - "server_fn", - "tracing", - "web-sys", -] - -[[package]] -name = "dioxus-history" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ae4e22616c698f35b60727313134955d885de2d32e83689258e586ebc9b7909" -dependencies = [ - "dioxus-core", - "tracing", -] - -[[package]] -name = "dioxus-hooks" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "948e2b3f20d9d4b2c300aaa60281b1755f3298684448920b27106da5841896d0" -dependencies = [ - "dioxus-core", - "dioxus-signals", - "futures-channel", - "futures-util", - "generational-box", - "rustversion", - "slab", - "tracing", - "warnings", -] - -[[package]] -name = "dioxus-html" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c9a40e6fee20ce7990095492dedb6a753eebe05e67d28271a249de74dc796d" -dependencies = [ - "async-trait", - "dioxus-core", - "dioxus-core-macro", - "dioxus-core-types", - "dioxus-hooks", - "dioxus-html-internal-macro", - "enumset", - "euclid", - "futures-channel", - "generational-box", - "keyboard-types", - "lazy-js-bundle", - "rustversion", - "serde", - "serde_json", - "serde_repr", - "tracing", -] - -[[package]] -name = "dioxus-html-internal-macro" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ba87b53688a2c9f619ecdf4b3b955bc1f08bd0570a80a0d626c405f6d14a76" -dependencies = [ - "convert_case 0.6.0", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "dioxus-interpreter-js" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330707b10ca75cb0eb05f9e5f8d80217cd0d7e62116a8277ae363c1a09b57a22" -dependencies = [ - "dioxus-core", - "dioxus-core-types", - "dioxus-html", - "js-sys", - "lazy-js-bundle", - "rustc-hash 1.1.0", - "serde", - "sledgehammer_bindgen", - "sledgehammer_utils", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "dioxus-lib" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5405b71aa9b8b0c3e0d22728f12f34217ca5277792bd315878cc6ecab7301b72" -dependencies = [ - "dioxus-config-macro", - "dioxus-core", - "dioxus-core-macro", - "dioxus-document", - "dioxus-history", - "dioxus-hooks", - "dioxus-html", - "dioxus-rsx", - "dioxus-signals", - "warnings", -] - -[[package]] -name = "dioxus-logger" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "545961e752f6c8bf59c274951b3c8b18a106db6ad2f9e2035b29e1f2a3e899b1" -dependencies = [ - "console_error_panic_hook", - "dioxus-cli-config", - "tracing", - "tracing-subscriber", - "tracing-wasm", -] - -[[package]] -name = "dioxus-mobile" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d1295388909f427758993f32a571e0f8698d6ce0f125fa0e81b8bfdec3fa952" -dependencies = [ - "dioxus-cli-config", - "dioxus-desktop", - "dioxus-lib", - "jni", - "libc", - "once_cell", -] - -[[package]] -name = "dioxus-router" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7266a76fc9e4a91f56499d1d1aecfff7168952b6627a6008b4e9748d6bf863e4" -dependencies = [ - "dioxus-cli-config", - "dioxus-history", - "dioxus-lib", - "dioxus-router-macro", - "rustversion", - "tracing", - "url", - "urlencoding", -] - -[[package]] -name = "dioxus-router-macro" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2743ffb79e9a7d33d779c87d6deea2a6c047d0736012f95d63b909b83f0a6fd2" -dependencies = [ - "proc-macro2", - "quote", - "slab", - "syn 2.0.100", -] - -[[package]] -name = "dioxus-rsx" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb588e05800b5a7eb90b2f40fca5bbd7626e823fb5e1ba21e011de649b45aa1" -dependencies = [ - "proc-macro2", - "proc-macro2-diagnostics", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "dioxus-signals" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10e032dbb3a2c0386ec8b8ee59bc20b5aeb67038147c855801237b45b13d72ac" -dependencies = [ - "dioxus-core", - "futures-channel", - "futures-util", - "generational-box", - "once_cell", - "parking_lot 0.12.3", - "rustc-hash 1.1.0", - "tracing", - "warnings", -] - -[[package]] -name = "dioxus-web" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7c12475c3d360058b8afe1b68eb6dfc9cbb7dcd760aed37c5f85c561c83ed1" -dependencies = [ - "async-trait", - "ciborium", - "dioxus-cli-config", - "dioxus-core", - "dioxus-core-types", - "dioxus-devtools", - "dioxus-document", - "dioxus-history", - "dioxus-html", - "dioxus-interpreter-js", - "dioxus-signals", - "futures-channel", - "futures-util", - "generational-box", - "js-sys", - "lazy-js-bundle", - "rustc-hash 1.1.0", - "serde", - "serde-wasm-bindgen", - "serde_json", - "tracing", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "dioxus_server_macro" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "371a5b21989a06b53c5092e977b3f75d0e60a65a4c15a2aa1d07014c3b2dda97" -dependencies = [ - "proc-macro2", - "quote", - "server_fn_macro", - "syn 2.0.100", -] - -[[package]] -name = "dirs" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" -dependencies = [ - "dirs-sys", -] - -[[package]] -name = "dirs-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" -dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.59.0", -] - -[[package]] -name = "dispatch" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" - -[[package]] -name = "dispatch2" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a0d569e003ff27784e0e14e4a594048698e0c0f0b66cabcb51511be55a7caa0" -dependencies = [ - "bitflags 2.9.0", - "block2 0.6.1", - "libc", - "objc2 0.6.1", -] - -[[package]] -name = "dispatch2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" -dependencies = [ - "bitflags 2.9.0", - "objc2 0.6.1", -] - -[[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.100", -] - -[[package]] -name = "dlopen2" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1297103d2bbaea85724fcee6294c2d50b1081f9ad47d0f6f6f61eda65315a6" -dependencies = [ - "dlopen2_derive", - "libc", - "once_cell", - "winapi", -] - -[[package]] -name = "dlopen2_derive" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2b99bf03862d7f545ebc28ddd33a665b50865f4dfd84031a393823879bd4c54" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "dlv-list" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" -dependencies = [ - "const-random", -] - -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" - -[[package]] -name = "dpi" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" - -[[package]] -name = "dtoa" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" - -[[package]] -name = "dtoa-short" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" -dependencies = [ - "dtoa", -] - -[[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "e2e_test" -version = "0.0.1" -dependencies = [ - "common", - "ecstore", - "flatbuffers 25.2.10", - "futures", - "lazy_static", - "lock", - "madmin", - "protos", - "rmp-serde", - "serde", - "serde_json", - "tokio", - "tonic 0.13.1", - "tower 0.5.2", - "url", -] - -[[package]] -name = "ecstore" -version = "0.0.1" -dependencies = [ - "async-trait", - "backon", - "base64-simd", - "blake2", - "byteorder", - "bytes", - "bytesize", - "chrono", - "common", - "crc32fast", - "flatbuffers 25.2.10", - "futures", - "glob", - "hex-simd", - "highway", - "http", - "lazy_static", - "lock", - "madmin", - "md-5", - "netif", - "nix 0.30.1", - "num", - "num_cpus", - "path-absolutize", - "path-clean", - "pin-project-lite", - "policy", - "protos", - "rand 0.8.5", - "reed-solomon-erasure", - "regex", - "reqwest", - "rmp", - "rmp-serde", - "rustfs-config", - "s3s", - "s3s-policy", - "serde", - "serde_json", - "sha2 0.11.0-pre.5", - "shadow-rs", - "siphasher 1.0.1", - "smallvec", - "tempfile", - "thiserror 2.0.12", - "time", - "tokio", - "tokio-stream", - "tokio-util", - "tonic 0.13.1", - "tower 0.5.2", - "tracing", - "tracing-error", - "transform-stream", - "url", - "urlencoding", - "uuid", - "winapi", - "workers", - "xxhash-rust", -] - -[[package]] -name = "either" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" - -[[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 = "endi" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" - -[[package]] -name = "enumflags2" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba2f4b465f5318854c6f8dd686ede6c0a9dc67d4b1ac241cf0eb51521a309147" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4caf64a58d7a6d65ab00639b046ff54399a39f5f2554728895ace4b297cd79" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "enumset" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a4b049558765cef5f0c1a273c3fc57084d768b44d2f98127aef4cceb17293" -dependencies = [ - "enumset_derive", -] - -[[package]] -name = "enumset_derive" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c3b24c345d8c314966bdc1832f6c2635bfcce8e7cf363bd115987bba2ee242" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "equivalent" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" - -[[package]] -name = "erased-serde" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" -dependencies = [ - "serde", - "typeid", -] - -[[package]] -name = "errno" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "euclid" -version = "0.22.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" -dependencies = [ - "num-traits", - "serde", -] - -[[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", - "pin-project-lite", -] - -[[package]] -name = "fastrand" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" - -[[package]] -name = "fdeflate" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "field-offset" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" -dependencies = [ - "memoffset", - "rustc_version", -] - -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - -[[package]] -name = "flatbuffers" -version = "24.12.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1baf0dbf96932ec9a3038d57900329c015b0bfb7b63d904f3bc27e2b02a096" -dependencies = [ - "bitflags 1.3.2", - "rustc_version", -] - -[[package]] -name = "flatbuffers" -version = "25.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1045398c1bfd89168b5fd3f1fc11f6e70b34f6f66300c87d44d3de849463abf1" -dependencies = [ - "bitflags 2.9.0", - "rustc_version", -] - -[[package]] -name = "flate2" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" -dependencies = [ - "crc32fast", - "miniz_oxide", -] - -[[package]] -name = "flexi_logger" -version = "0.30.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb03342077df16d5b1400d7bed00156882846d7a479ff61a6f10594bcc3423d8" -dependencies = [ - "chrono", - "crossbeam-channel", - "crossbeam-queue", - "log", - "notify-debouncer-mini", - "nu-ansi-term 0.50.1", - "regex", - "serde", - "serde_derive", - "thiserror 2.0.12", - "toml", - "tracing", - "tracing-subscriber", -] - -[[package]] -name = "flume" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" -dependencies = [ - "futures-core", - "futures-sink", - "spin", -] - -[[package]] -name = "fnv" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" - -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - -[[package]] -name = "foreign-types" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" -dependencies = [ - "foreign-types-macros", - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "foreign-types-shared" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" - -[[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 = "fs-err" -version = "3.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f89bda4c2a21204059a977ed3bfe746677dfd137b83c339e702b0ac91d482aa" -dependencies = [ - "autocfg", - "tokio", -] - -[[package]] -name = "fs_extra" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" - -[[package]] -name = "fsevent-sys" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] - -[[package]] -name = "futf" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" -dependencies = [ - "mac", - "new_debug_unreachable", -] - -[[package]] -name = "futures" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" -dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", -] - -[[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-core" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" - -[[package]] -name = "futures-executor" -version = "0.3.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" -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 = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" -dependencies = [ - "fastrand", - "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.100", -] - -[[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-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 = "fxhash" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" -dependencies = [ - "byteorder", -] - -[[package]] -name = "gdk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" -dependencies = [ - "cairo-rs", - "gdk-pixbuf", - "gdk-sys", - "gio", - "glib", - "libc", - "pango", -] - -[[package]] -name = "gdk-pixbuf" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" -dependencies = [ - "gdk-pixbuf-sys", - "gio", - "glib", - "libc", - "once_cell", -] - -[[package]] -name = "gdk-pixbuf-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gdk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" -dependencies = [ - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "pkg-config", - "system-deps", -] - -[[package]] -name = "gdkwayland-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" -dependencies = [ - "gdk-sys", - "glib-sys", - "gobject-sys", - "libc", - "pkg-config", - "system-deps", -] - -[[package]] -name = "gdkx11" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3caa00e14351bebbc8183b3c36690327eb77c49abc2268dd4bd36b856db3fbfe" -dependencies = [ - "gdk", - "gdkx11-sys", - "gio", - "glib", - "libc", - "x11", -] - -[[package]] -name = "gdkx11-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" -dependencies = [ - "gdk-sys", - "glib-sys", - "libc", - "system-deps", - "x11", -] - -[[package]] -name = "generational-box" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a673cf4fb0ea6a91aa86c08695756dfe875277a912cdbf33db9a9f62d47ed82b" -dependencies = [ - "parking_lot 0.12.3", - "tracing", -] - -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "getrandom" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", -] - -[[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 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "getrandom" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" -dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", - "wasm-bindgen", -] - -[[package]] -name = "ghash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - -[[package]] -name = "gio" -version = "0.18.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" -dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-util", - "gio-sys", - "glib", - "libc", - "once_cell", - "pin-project-lite", - "smallvec", - "thiserror 1.0.69", -] - -[[package]] -name = "gio-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", - "winapi", -] - -[[package]] -name = "glib" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" -dependencies = [ - "bitflags 2.9.0", - "futures-channel", - "futures-core", - "futures-executor", - "futures-task", - "futures-util", - "gio-sys", - "glib-macros", - "glib-sys", - "gobject-sys", - "libc", - "memchr", - "once_cell", - "smallvec", - "thiserror 1.0.69", -] - -[[package]] -name = "glib-macros" -version = "0.18.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" -dependencies = [ - "heck 0.4.1", - "proc-macro-crate 2.0.0", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "glib-sys" -version = "0.18.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" -dependencies = [ - "libc", - "system-deps", -] - -[[package]] -name = "glob" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" - -[[package]] -name = "global-hotkey" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b436093d1598b05e3b7fddc097b2bad32763f53a1beb25ab6f9718c6a60acd09" -dependencies = [ - "bitflags 2.9.0", - "cocoa 0.25.0", - "crossbeam-channel", - "keyboard-types", - "objc", - "once_cell", - "thiserror 1.0.69", - "windows-sys 0.52.0", - "x11-dl", -] - -[[package]] -name = "gloo-net" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" -dependencies = [ - "futures-channel", - "futures-core", - "futures-sink", - "gloo-utils", - "http", - "js-sys", - "pin-project", - "serde", - "serde_json", - "thiserror 1.0.69", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "gloo-timers" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" -dependencies = [ - "futures-channel", - "futures-core", - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "gloo-utils" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" -dependencies = [ - "js-sys", - "serde", - "serde_json", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "gobject-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" -dependencies = [ - "glib-sys", - "libc", - "system-deps", -] - -[[package]] -name = "gtk" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" -dependencies = [ - "atk", - "cairo-rs", - "field-offset", - "futures-channel", - "gdk", - "gdk-pixbuf", - "gio", - "glib", - "gtk-sys", - "gtk3-macros", - "libc", - "pango", - "pkg-config", -] - -[[package]] -name = "gtk-sys" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" -dependencies = [ - "atk-sys", - "cairo-sys-rs", - "gdk-pixbuf-sys", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "pango-sys", - "system-deps", -] - -[[package]] -name = "gtk3-macros" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro-error", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "h2" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap 2.9.0", - "slab", - "tokio", - "tokio-util", - "tracing", -] - -[[package]] -name = "half" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" -dependencies = [ - "cfg-if", - "crunchy", - "num-traits", -] - -[[package]] -name = "hashbrown" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.8", -] - -[[package]] -name = "hashbrown" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash 0.8.11", - "allocator-api2", -] - -[[package]] -name = "hashbrown" -version = "0.15.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" -dependencies = [ - "foldhash", -] - -[[package]] -name = "hashlink" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" -dependencies = [ - "hashbrown 0.15.2", -] - -[[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 = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - -[[package]] -name = "hex" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" - -[[package]] -name = "hex-simd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f7685beb53fc20efc2605f32f5d51e9ba18b8ef237961d1760169d2290d3bee" -dependencies = [ - "outref", - "vsimd", -] - -[[package]] -name = "highway" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9040319a6910b901d5d49cbada4a99db52836a1b63228a05f7e2b7f8feef89b1" - -[[package]] -name = "hmac" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" -dependencies = [ - "digest 0.10.7", -] - -[[package]] -name = "hmac" -version = "0.13.0-pre.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62c11fc82c6b89c906b4d26b7b5a305d0b3aebd4b458dd1bd0a7ed98c548a28e" -dependencies = [ - "digest 0.11.0-pre.10", -] - -[[package]] -name = "home" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "html5ever" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bea68cab48b8459f17cf1c944c67ddc572d272d9f2b274140f223ecb1da4a3b7" -dependencies = [ - "log", - "mac", - "markup5ever", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "http" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" -dependencies = [ - "bytes", - "fnv", - "itoa 1.0.15", -] - -[[package]] -name = "http-body" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" -dependencies = [ - "bytes", - "http", -] - -[[package]] -name = "http-body-util" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" -dependencies = [ - "bytes", - "futures-core", - "http", - "http-body", - "pin-project-lite", -] - -[[package]] -name = "httparse" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" - -[[package]] -name = "httpdate" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" - -[[package]] -name = "humantime" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" - -[[package]] -name = "hybrid-array" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dab50e193aebe510fe0e40230145820e02f48dae0cf339ea4204e6e708ff7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "hyper" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" -dependencies = [ - "bytes", - "futures-channel", - "futures-util", - "h2", - "http", - "http-body", - "httparse", - "httpdate", - "itoa 1.0.15", - "pin-project-lite", - "smallvec", - "tokio", - "want", -] - -[[package]] -name = "hyper-rustls" -version = "0.27.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" -dependencies = [ - "futures-util", - "http", - "hyper", - "hyper-util", - "rustls 0.23.27", - "rustls-pki-types", - "tokio", - "tokio-rustls 0.26.2", - "tower-service", - "webpki-roots 0.26.8", -] - -[[package]] -name = "hyper-timeout" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" -dependencies = [ - "hyper", - "hyper-util", - "pin-project-lite", - "tokio", - "tower-service", -] - -[[package]] -name = "hyper-util" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c293b6b3d21eca78250dc7dbebd6b9210ec5530e038cbfe0661b5c47ab06e8" -dependencies = [ - "base64 0.22.1", - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "http", - "http-body", - "hyper", - "ipnet", - "libc", - "percent-encoding", - "pin-project-lite", - "socket2", - "system-configuration", - "tokio", - "tower-service", - "tracing", - "windows-registry", -] - -[[package]] -name = "iam" -version = "0.0.1" -dependencies = [ - "arc-swap", - "async-trait", - "base64-simd", - "common", - "crypto", - "ecstore", - "futures", - "ipnetwork", - "itertools 0.14.0", - "jsonwebtoken", - "lazy_static", - "madmin", - "policy", - "rand 0.8.5", - "regex", - "serde", - "serde_json", - "strum", - "test-case", - "thiserror 2.0.12", - "time", - "tokio", - "tracing", -] - -[[package]] -name = "iana-time-zone" -version = "0.1.63" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" -dependencies = [ - "android_system_properties", - "core-foundation-sys", - "iana-time-zone-haiku", - "js-sys", - "log", - "wasm-bindgen", - "windows-core 0.61.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 = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" - -[[package]] -name = "icu_properties" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "ident_case" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" - -[[package]] -name = "idna" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" -dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", -] - -[[package]] -name = "idna_adapter" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" -dependencies = [ - "icu_normalizer", - "icu_properties", -] - -[[package]] -name = "indexmap" -version = "1.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" -dependencies = [ - "autocfg", - "hashbrown 0.12.3", - "serde", -] - -[[package]] -name = "indexmap" -version = "2.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" -dependencies = [ - "equivalent", - "hashbrown 0.15.2", - "serde", -] - -[[package]] -name = "infer" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6c16b11a665b26aeeb9b1d7f954cdeb034be38dd00adab4f2ae921a8fee804" -dependencies = [ - "cfb", -] - -[[package]] -name = "inotify" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" -dependencies = [ - "bitflags 2.9.0", - "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.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" -dependencies = [ - "generic-array", -] - -[[package]] -name = "instant" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "integer-encoding" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bb03732005da905c88227371639bf1ad885cc712789c011c31c5fb3ab3ccf02" - -[[package]] -name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "ipnetwork" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf370abdafd54d13e54a620e8c3e1145f28e46cc9d704bc6d94414559df41763" -dependencies = [ - "serde", -] - -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "is_debug" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fe266d2e243c931d8190177f20bf7f24eed45e96f39e87dc49a27b32d12d407" - -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - -[[package]] -name = "itertools" -version = "0.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" -dependencies = [ - "either", -] - -[[package]] -name = "itoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "javascriptcore-rs" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" -dependencies = [ - "bitflags 1.3.2", - "glib", - "javascriptcore-rs-sys", -] - -[[package]] -name = "javascriptcore-rs-sys" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "jni" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" -dependencies = [ - "cesu8", - "cfg-if", - "combine", - "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", -] - -[[package]] -name = "jni-sys" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" - -[[package]] -name = "jobserver" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a" -dependencies = [ - "getrandom 0.3.2", - "libc", -] - -[[package]] -name = "js-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" -dependencies = [ - "once_cell", - "wasm-bindgen", -] - -[[package]] -name = "json5" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b0db21af676c1ce64250b5f40f3ce2cf27e4e47cb91ed91eb6fe9350b430c1" -dependencies = [ - "pest", - "pest_derive", - "serde", -] - -[[package]] -name = "jsonwebtoken" -version = "9.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" -dependencies = [ - "base64 0.22.1", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "keyboard-types" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" -dependencies = [ - "bitflags 2.9.0", - "serde", - "unicode-segmentation", -] - -[[package]] -name = "keyring" -version = "3.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1961983669d57bdfe6c0f3ef8e4c229b5ef751afcc7d87e4271d2f71f6ccfa8b" -dependencies = [ - "byteorder", - "dbus-secret-service", - "log", - "security-framework 2.11.1", - "security-framework 3.2.0", - "windows-sys 0.59.0", -] - -[[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 = "kuchikiki" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e4755b7b995046f510a7520c42b2fed58b77bd94d5a87a8eb43d2fd126da8" -dependencies = [ - "cssparser", - "html5ever", - "indexmap 1.9.3", - "matches", - "selectors", -] - -[[package]] -name = "lazy-js-bundle" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e49596223b9d9d4947a14a25c142a6e7d8ab3f27eb3ade269d238bb8b5c267e2" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" -dependencies = [ - "spin", -] - -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - -[[package]] -name = "lexical-core" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b765c31809609075565a70b4b71402281283aeda7ecaf4818ac14a7b2ade8958" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de6f9cb01fb0b08060209a057c048fcbab8717b4c1ecd2eac66ebfe39a65b0f2" -dependencies = [ - "lexical-parse-integer", - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-parse-integer" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72207aae22fc0a121ba7b6d479e42cbfea549af1479c3f3a4f12c70dd66df12e" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-util" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a82e24bf537fd24c177ffbbdc6ebcc8d54732c35b50a3f28cc3f4e4c949a0b3" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "lexical-write-float" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5afc668a27f460fb45a81a757b6bf2f43c2d7e30cb5a2dcd3abf294c78d62bd" -dependencies = [ - "lexical-util", - "lexical-write-integer", - "static_assertions", -] - -[[package]] -name = "lexical-write-integer" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629ddff1a914a836fb245616a7888b62903aae58fa771e1d83943035efa0f978" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "libappindicator" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" -dependencies = [ - "glib", - "gtk", - "gtk-sys", - "libappindicator-sys", - "log", -] - -[[package]] -name = "libappindicator-sys" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" -dependencies = [ - "gtk-sys", - "libloading 0.7.4", - "once_cell", -] - -[[package]] -name = "libc" -version = "0.2.172" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" - -[[package]] -name = "libdbus-sys" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06085512b750d640299b79be4bad3d2fa90a9c00b1fd9e1b46364f66f0485c72" -dependencies = [ - "pkg-config", -] - -[[package]] -name = "libloading" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" -dependencies = [ - "cfg-if", - "winapi", -] - -[[package]] -name = "libloading" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" -dependencies = [ - "cfg-if", - "windows-targets 0.52.6", -] - -[[package]] -name = "libm" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" - -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.9.0", - "libc", - "redox_syscall 0.5.11", -] - -[[package]] -name = "libsystemd" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c97a761fc86953c5b885422b22c891dbf5bcb9dcc99d0110d6ce4c052759f0" -dependencies = [ - "hmac 0.12.1", - "libc", - "log", - "nix 0.29.0", - "nom 8.0.0", - "once_cell", - "serde", - "sha2 0.10.9", - "thiserror 2.0.12", - "uuid", -] - -[[package]] -name = "libxdo" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00333b8756a3d28e78def82067a377de7fa61b24909000aeaa2b446a948d14db" -dependencies = [ - "libxdo-sys", -] - -[[package]] -name = "libxdo-sys" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212" -dependencies = [ - "libc", - "x11", -] - -[[package]] -name = "libz-sys" -version = "1.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - -[[package]] -name = "linux-raw-sys" -version = "0.4.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" - -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - -[[package]] -name = "litemap" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" - -[[package]] -name = "local-ip-address" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "656b3b27f8893f7bbf9485148ff9a65f019e3f33bd5cdc87c83cab16b3fd9ec8" -dependencies = [ - "libc", - "neli", - "thiserror 2.0.12", - "windows-sys 0.59.0", -] - -[[package]] -name = "lock" -version = "0.0.1" -dependencies = [ - "async-trait", - "backon", - "common", - "lazy_static", - "protos", - "rand 0.8.5", - "serde", - "serde_json", - "tokio", - "tonic 0.13.1", - "tracing", - "tracing-error", - "url", - "uuid", -] - -[[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.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" -dependencies = [ - "serde", - "value-bag", -] - -[[package]] -name = "longest-increasing-subsequence" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" - -[[package]] -name = "lru" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999beba7b6e8345721bd280141ed958096a2e4abdf74f67ff4ce49b4b54e47a" -dependencies = [ - "hashbrown 0.12.3", -] - -[[package]] -name = "lz4_flex" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" -dependencies = [ - "twox-hash", -] - -[[package]] -name = "lzma-rs" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" -dependencies = [ - "byteorder", - "crc", -] - -[[package]] -name = "lzma-sys" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27" -dependencies = [ - "cc", - "libc", - "pkg-config", -] - -[[package]] -name = "mac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" - -[[package]] -name = "madmin" -version = "0.0.1" -dependencies = [ - "chrono", - "common", - "humantime", - "hyper", - "s3s", - "serde", - "serde_json", - "time", - "tracing", -] - -[[package]] -name = "malloc_buf" -version = "0.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" -dependencies = [ - "libc", -] - -[[package]] -name = "manganis" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317af44b15e7605b85f04525449a3bb631753040156c9b318e6cba8a3ea4ef73" -dependencies = [ - "const-serialize", - "manganis-core", - "manganis-macro", -] - -[[package]] -name = "manganis-core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c38bee65cc725b2bba23b5dbb290f57c8be8fadbe2043fb7e2ce73022ea06519" -dependencies = [ - "const-serialize", - "dioxus-cli-config", - "dioxus-core-types", - "serde", -] - -[[package]] -name = "manganis-macro" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f4f71310913c40174d9f0cfcbcb127dad0329ecdb3945678a120db22d3d065" -dependencies = [ - "dunce", - "manganis-core", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "markup5ever" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2629bb1404f3d34c2e921f21fd34ba00b206124c81f65c50b43b6aaefeb016" -dependencies = [ - "log", - "phf 0.10.1", - "phf_codegen 0.10.0", - "string_cache", - "string_cache_codegen", - "tendril", -] - -[[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 = "matches" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" - -[[package]] -name = "matchit" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" - -[[package]] -name = "md-5" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" -dependencies = [ - "cfg-if", - "digest 0.10.7", -] - -[[package]] -name = "memchr" -version = "2.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" - -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - -[[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.8.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" -dependencies = [ - "adler2", - "simd-adler32", -] - -[[package]] -name = "mio" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.52.0", -] - -[[package]] -name = "muda" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c47e7625990fc1af2226ea4f34fb2412b03c12639fcb91868581eb3a6893453" -dependencies = [ - "cocoa 0.25.0", - "crossbeam-channel", - "gtk", - "keyboard-types", - "libxdo", - "objc", - "once_cell", - "png", - "thiserror 1.0.69", - "windows-sys 0.52.0", -] - -[[package]] -name = "muda" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdae9c00e61cc0579bcac625e8ad22104c60548a025bfc972dc83868a28e1484" -dependencies = [ - "crossbeam-channel", - "dpi", - "gtk", - "keyboard-types", - "libxdo", - "objc2 0.5.2", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", - "once_cell", - "png", - "thiserror 1.0.69", - "windows-sys 0.59.0", -] - -[[package]] -name = "multimap" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" - -[[package]] -name = "ndk" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" -dependencies = [ - "bitflags 2.9.0", - "jni-sys", - "log", - "ndk-sys", - "num_enum", - "raw-window-handle 0.6.2", - "thiserror 1.0.69", -] - -[[package]] -name = "ndk-context" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" - -[[package]] -name = "ndk-sys" -version = "0.6.0+11769913" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" -dependencies = [ - "jni-sys", -] - -[[package]] -name = "neli" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93062a0dce6da2517ea35f301dfc88184ce18d3601ec786a727a87bf535deca9" -dependencies = [ - "byteorder", - "libc", - "log", - "neli-proc-macros", -] - -[[package]] -name = "neli-proc-macros" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8034b7fbb6f9455b2a96c19e6edf8dc9fc34c70449938d8ee3b4df363f61fe" -dependencies = [ - "either", - "proc-macro2", - "quote", - "serde", - "syn 1.0.109", -] - -[[package]] -name = "netif" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29a01b9f018d6b7b277fef6c79fdbd9bf17bb2d1e298238055cafab49baa5ee" -dependencies = [ - "libc", - "winapi", -] - -[[package]] -name = "new_debug_unreachable" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" - -[[package]] -name = "nix" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "cfg_aliases", - "libc", - "memoffset", -] - -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "nodrop" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" - -[[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 = "nom" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" -dependencies = [ - "memchr", -] - -[[package]] -name = "notify" -version = "8.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" -dependencies = [ - "bitflags 2.9.0", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio", - "notify-types", - "walkdir", - "windows-sys 0.59.0", -] - -[[package]] -name = "notify-debouncer-mini" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a689eb4262184d9a1727f9087cd03883ea716682ab03ed24efec57d7716dccb8" -dependencies = [ - "log", - "notify", - "notify-types", - "tempfile", -] - -[[package]] -name = "notify-types" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e0826a989adedc2a244799e823aece04662b66609d96af8dff7ac6df9a8925d" - -[[package]] -name = "ntapi" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" -dependencies = [ - "winapi", -] - -[[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 = "nu-ansi-term" -version = "0.50.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "nugine-rust-utils" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04dcd9cfa92246a9c7ca0671e00733c4e9d77ee1fa0ae08c9a181b7c8802aea2" -dependencies = [ - "simdutf8", -] - -[[package]] -name = "num" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" -dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", -] - -[[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 0.8.5", - "smallvec", - "zeroize", -] - -[[package]] -name = "num-complex" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" -dependencies = [ - "num-traits", -] - -[[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-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "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 0.3.9", - "libc", -] - -[[package]] -name = "num_enum" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" -dependencies = [ - "num_enum_derive", -] - -[[package]] -name = "num_enum_derive" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" -dependencies = [ - "proc-macro-crate 3.3.0", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "num_threads" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" -dependencies = [ - "libc", -] - -[[package]] -name = "numeric_cast" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3c00a0c9600379bd32f8972de90676a7672cba3bf4886986bc05902afc1e093" - -[[package]] -name = "nvml-wrapper" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9bff0aa1d48904a1385ea2a8b97576fbdcbc9a3cfccd0d31fe978e1c4038c5" -dependencies = [ - "bitflags 2.9.0", - "libloading 0.8.6", - "nvml-wrapper-sys", - "static_assertions", - "thiserror 1.0.69", - "wrapcenum-derive", -] - -[[package]] -name = "nvml-wrapper-sys" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "698d45156f28781a4e79652b6ebe2eaa0589057d588d3aec1333f6466f13fcb5" -dependencies = [ - "libloading 0.8.6", -] - -[[package]] -name = "objc" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" -dependencies = [ - "malloc_buf", - "objc_exception", -] - -[[package]] -name = "objc-foundation" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" -dependencies = [ - "block", - "objc", - "objc_id", -] - -[[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" -dependencies = [ - "objc-sys", - "objc2-encode", -] - -[[package]] -name = "objc2" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" -dependencies = [ - "objc2-encode", -] - -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.9.0", - "block2 0.5.1", - "libc", - "objc2 0.5.2", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation 0.2.2", - "objc2-quartz-core", -] - -[[package]] -name = "objc2-app-kit" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" -dependencies = [ - "bitflags 2.9.0", - "block2 0.6.1", - "objc2 0.6.1", - "objc2-core-foundation", - "objc2-foundation 0.3.1", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.9.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-core-foundation" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" -dependencies = [ - "bitflags 2.9.0", - "dispatch2 0.3.0", - "objc2 0.6.1", -] - -[[package]] -name = "objc2-core-graphics" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" -dependencies = [ - "bitflags 2.9.0", - "objc2-core-foundation", -] - -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal", -] - -[[package]] -name = "objc2-encode" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" - -[[package]] -name = "objc2-foundation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" -dependencies = [ - "bitflags 2.9.0", - "block2 0.5.1", - "libc", - "objc2 0.5.2", -] - -[[package]] -name = "objc2-foundation" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" -dependencies = [ - "bitflags 2.9.0", - "block2 0.6.1", - "objc2 0.6.1", - "objc2-core-foundation", -] - -[[package]] -name = "objc2-io-kit" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71c1c64d6120e51cd86033f67176b1cb66780c2efe34dec55176f77befd93c0a" -dependencies = [ - "libc", - "objc2-core-foundation", -] - -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.9.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-quartz-core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" -dependencies = [ - "bitflags 2.9.0", - "block2 0.5.1", - "objc2 0.5.2", - "objc2-foundation 0.2.2", - "objc2-metal", -] - -[[package]] -name = "objc_exception" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4" -dependencies = [ - "cc", -] - -[[package]] -name = "objc_id" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" -dependencies = [ - "objc", -] - -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - -[[package]] -name = "object_store" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cfccb68961a56facde1163f9319e0d15743352344e7808a11795fb99698dcaf" -dependencies = [ - "async-trait", - "bytes", - "chrono", - "futures", - "humantime", - "itertools 0.13.0", - "parking_lot 0.12.3", - "percent-encoding", - "snafu", - "tokio", - "tracing", - "url", - "walkdir", -] - -[[package]] -name = "once_cell" -version = "1.21.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" - -[[package]] -name = "opentelemetry" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e87237e2775f74896f9ad219d26a2081751187eb7c9f5c58dde20a23b95d16c" -dependencies = [ - "futures-core", - "futures-sink", - "js-sys", - "pin-project-lite", - "thiserror 2.0.12", - "tracing", -] - -[[package]] -name = "opentelemetry-appender-tracing" -version = "0.29.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e716f864eb23007bdd9dc4aec381e188a1cee28eecf22066772b5fd822b9727d" -dependencies = [ - "opentelemetry", - "tracing", - "tracing-core", - "tracing-log", - "tracing-opentelemetry", - "tracing-subscriber", -] - -[[package]] -name = "opentelemetry-http" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46d7ab32b827b5b495bd90fa95a6cb65ccc293555dcc3199ae2937d2d237c8ed" -dependencies = [ - "async-trait", - "bytes", - "http", - "opentelemetry", - "reqwest", - "tracing", -] - -[[package]] -name = "opentelemetry-otlp" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d899720fe06916ccba71c01d04ecd77312734e2de3467fd30d9d580c8ce85656" -dependencies = [ - "futures-core", - "http", - "opentelemetry", - "opentelemetry-http", - "opentelemetry-proto", - "opentelemetry_sdk", - "prost", - "reqwest", - "thiserror 2.0.12", - "tokio", - "tonic 0.12.3", - "tracing", -] - -[[package]] -name = "opentelemetry-proto" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c40da242381435e18570d5b9d50aca2a4f4f4d8e146231adb4e7768023309b3" -dependencies = [ - "opentelemetry", - "opentelemetry_sdk", - "prost", - "tonic 0.12.3", -] - -[[package]] -name = "opentelemetry-semantic-conventions" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b29a9f89f1a954936d5aa92f19b2feec3c8f3971d3e96206640db7f9706ae3" - -[[package]] -name = "opentelemetry-stdout" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7e27d446dabd68610ef0b77d07b102ecde827a4596ea9c01a4d3811e945b286" -dependencies = [ - "chrono", - "futures-util", - "opentelemetry", - "opentelemetry_sdk", -] - -[[package]] -name = "opentelemetry_sdk" -version = "0.29.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afdefb21d1d47394abc1ba6c57363ab141be19e27cc70d0e422b7f303e4d290b" -dependencies = [ - "futures-channel", - "futures-executor", - "futures-util", - "glob", - "opentelemetry", - "percent-encoding", - "rand 0.9.1", - "serde_json", - "thiserror 2.0.12", - "tokio", - "tokio-stream", - "tracing", -] - -[[package]] -name = "option-ext" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" - -[[package]] -name = "ordered-float" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" -dependencies = [ - "num-traits", -] - -[[package]] -name = "ordered-multimap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" -dependencies = [ - "dlv-list", - "hashbrown 0.14.5", -] - -[[package]] -name = "ordered-stream" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" -dependencies = [ - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "outref" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" - -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - -[[package]] -name = "pango" -version = "0.18.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" -dependencies = [ - "gio", - "glib", - "libc", - "once_cell", - "pango-sys", -] - -[[package]] -name = "pango-sys" -version = "0.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" -dependencies = [ - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "parking" -version = "2.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" - -[[package]] -name = "parking_lot" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" -dependencies = [ - "instant", - "lock_api", - "parking_lot_core 0.8.6", -] - -[[package]] -name = "parking_lot" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api", - "parking_lot_core 0.9.10", -] - -[[package]] -name = "parking_lot_core" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" -dependencies = [ - "cfg-if", - "instant", - "libc", - "redox_syscall 0.2.16", - "smallvec", - "winapi", -] - -[[package]] -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.11", - "smallvec", - "windows-targets 0.52.6", -] - -[[package]] -name = "parquet" -version = "54.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfb15796ac6f56b429fd99e33ba133783ad75b27c36b4b5ce06f1f82cc97754e" -dependencies = [ - "ahash 0.8.11", - "arrow-array", - "arrow-buffer", - "arrow-cast", - "arrow-data", - "arrow-ipc", - "arrow-schema", - "arrow-select", - "base64 0.22.1", - "brotli", - "bytes", - "chrono", - "flate2", - "futures", - "half", - "hashbrown 0.15.2", - "lz4_flex", - "num", - "num-bigint", - "object_store", - "paste", - "seq-macro", - "simdutf8", - "snap", - "thrift", - "tokio", - "twox-hash", - "zstd", -] - -[[package]] -name = "parse-zoneinfo" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24" -dependencies = [ - "regex", -] - -[[package]] -name = "password-hash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" -dependencies = [ - "base64ct", - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - -[[package]] -name = "path-absolutize" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4af381fe79fa195b4909485d99f73a80792331df0625188e707854f0b3383f5" -dependencies = [ - "path-dedot", -] - -[[package]] -name = "path-clean" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17359afc20d7ab31fdb42bb844c8b3bb1dabd7dcf7e68428492da7f16966fcef" - -[[package]] -name = "path-dedot" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07ba0ad7e047712414213ff67533e6dd477af0a4e1d14fb52343e53d30ea9397" -dependencies = [ - "once_cell", -] - -[[package]] -name = "pathdiff" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3" - -[[package]] -name = "pbkdf2" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" -dependencies = [ - "digest 0.10.7", - "hmac 0.12.1", -] - -[[package]] -name = "pem" -version = "3.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" -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.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "198db74531d58c70a361c42201efde7e2591e976d518caf7662a47dc5720e7b6" -dependencies = [ - "memchr", - "thiserror 2.0.12", - "ucd-trie", -] - -[[package]] -name = "pest_derive" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d725d9cfd79e87dccc9341a2ef39d1b6f6353d68c4b33c177febbe1a402c97c5" -dependencies = [ - "pest", - "pest_generator", -] - -[[package]] -name = "pest_generator" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db7d01726be8ab66ab32f9df467ae8b1148906685bbe75c82d1e65d7f5b3f841" -dependencies = [ - "pest", - "pest_meta", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "pest_meta" -version = "2.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9f832470494906d1fca5329f8ab5791cc60beb230c74815dff541cbd2b5ca0" -dependencies = [ - "once_cell", - "pest", - "sha2 0.10.9", -] - -[[package]] -name = "petgraph" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" -dependencies = [ - "fixedbitset", - "indexmap 2.9.0", -] - -[[package]] -name = "phf" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" -dependencies = [ - "phf_macros", - "phf_shared 0.8.0", - "proc-macro-hack", -] - -[[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_shared 0.10.0", -] - -[[package]] -name = "phf" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" -dependencies = [ - "phf_shared 0.11.3", -] - -[[package]] -name = "phf_codegen" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", -] - -[[package]] -name = "phf_codegen" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb1c3a8bc4dd4e5cfce29b44ffc14bedd2ee294559a294e2a4d4c9e9a6a13cd" -dependencies = [ - "phf_generator 0.10.0", - "phf_shared 0.10.0", -] - -[[package]] -name = "phf_codegen" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", -] - -[[package]] -name = "phf_generator" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" -dependencies = [ - "phf_shared 0.8.0", - "rand 0.7.3", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" -dependencies = [ - "phf_shared 0.10.0", - "rand 0.8.5", -] - -[[package]] -name = "phf_generator" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" -dependencies = [ - "phf_shared 0.11.3", - "rand 0.8.5", -] - -[[package]] -name = "phf_macros" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6fde18ff429ffc8fe78e2bf7f8b7a5a5a6e2a8b58bc5a9ac69198bbda9189c" -dependencies = [ - "phf_generator 0.8.0", - "phf_shared 0.8.0", - "proc-macro-hack", - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "phf_shared" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" -dependencies = [ - "siphasher 0.3.11", -] - -[[package]] -name = "phf_shared" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher 0.3.11", -] - -[[package]] -name = "phf_shared" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" -dependencies = [ - "siphasher 1.0.1", -] - -[[package]] -name = "pin-project" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" - -[[package]] -name = "pin-utils" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" - -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - -[[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 = "pkg-config" -version = "0.3.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" - -[[package]] -name = "png" -version = "0.17.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" -dependencies = [ - "bitflags 1.3.2", - "crc32fast", - "fdeflate", - "flate2", - "miniz_oxide", -] - -[[package]] -name = "policy" -version = "0.0.1" -dependencies = [ - "arc-swap", - "async-trait", - "base64-simd", - "common", - "crypto", - "futures", - "ipnetwork", - "itertools 0.14.0", - "jsonwebtoken", - "lazy_static", - "madmin", - "rand 0.8.5", - "regex", - "serde", - "serde_json", - "strum", - "test-case", - "thiserror 2.0.12", - "time", - "tokio", - "tracing", -] - -[[package]] -name = "polling" -version = "3.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.4.0", - "pin-project-lite", - "rustix 0.38.44", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "pollster" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22686f4785f02a4fcc856d3b3bb19bf6c8160d103f7a99cc258bddd0251dc7f2" - -[[package]] -name = "pollster" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" - -[[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 = "polyval" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[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.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy 0.8.24", -] - -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - -[[package]] -name = "prettyplease" -version = "0.2.32" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" -dependencies = [ - "proc-macro2", - "syn 2.0.100", -] - -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", -] - -[[package]] -name = "proc-macro-crate" -version = "3.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" -dependencies = [ - "toml_edit 0.22.24", -] - -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2", - "quote", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2", - "quote", - "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.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "proc-macro2-diagnostics" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "version_check", -] - -[[package]] -name = "prost" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" -dependencies = [ - "bytes", - "prost-derive", -] - -[[package]] -name = "prost-build" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf" -dependencies = [ - "heck 0.5.0", - "itertools 0.14.0", - "log", - "multimap", - "once_cell", - "petgraph", - "prettyplease", - "prost", - "prost-types", - "regex", - "syn 2.0.100", - "tempfile", -] - -[[package]] -name = "prost-derive" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" -dependencies = [ - "anyhow", - "itertools 0.14.0", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "prost-types" -version = "0.13.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16" -dependencies = [ - "prost", -] - -[[package]] -name = "protobuf" -version = "3.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4" -dependencies = [ - "once_cell", - "protobuf-support", - "thiserror 1.0.69", -] - -[[package]] -name = "protobuf-support" -version = "3.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6" -dependencies = [ - "thiserror 1.0.69", -] - -[[package]] -name = "protos" -version = "0.0.1" -dependencies = [ - "common", - "flatbuffers 25.2.10", - "prost", - "prost-build", - "protobuf", - "tokio", - "tonic 0.13.1", - "tonic-build", - "tower 0.5.2", -] - -[[package]] -name = "psm" -version = "0.1.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f58e5423e24c18cc840e1c98370b3993c6649cd1678b4d24318bcf0a083cbe88" -dependencies = [ - "cc", -] - -[[package]] -name = "query" -version = "0.0.1" -dependencies = [ - "api", - "async-recursion", - "async-trait", - "datafusion", - "derive_builder", - "futures", - "lazy_static", - "parking_lot 0.12.3", - "s3s", - "snafu", - "tokio", - "tracing", -] - -[[package]] -name = "quick-xml" -version = "0.37.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ce8c88de324ff838700f36fb6ab86c96df0e3c4ab6ef3a9b2044465cce1369" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "quinn" -version = "0.11.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" -dependencies = [ - "bytes", - "cfg_aliases", - "pin-project-lite", - "quinn-proto", - "quinn-udp", - "rustc-hash 2.1.1", - "rustls 0.23.27", - "socket2", - "thiserror 2.0.12", - "tokio", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-proto" -version = "0.11.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" -dependencies = [ - "bytes", - "getrandom 0.3.2", - "rand 0.9.1", - "ring", - "rustc-hash 2.1.1", - "rustls 0.23.27", - "rustls-pki-types", - "slab", - "thiserror 2.0.12", - "tinyvec", - "tracing", - "web-time", -] - -[[package]] -name = "quinn-udp" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5" -dependencies = [ - "cfg_aliases", - "libc", - "once_cell", - "socket2", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" - -[[package]] -name = "rand" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -dependencies = [ - "getrandom 0.1.16", - "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc", - "rand_pcg", -] - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha 0.9.0", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_chacha" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" -dependencies = [ - "ppv-lite86", - "rand_core 0.5.1", -] - -[[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 0.6.4", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.15", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.2", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_pcg" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" -dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "raw-window-handle" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" - -[[package]] -name = "raw-window-handle" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" - -[[package]] -name = "rdkafka" -version = "0.37.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b52c81ac3cac39c9639b95c20452076e74b8d9a71bc6fc4d83407af2ea6fff" -dependencies = [ - "futures-channel", - "futures-util", - "libc", - "log", - "rdkafka-sys", - "serde", - "serde_derive", - "serde_json", - "slab", - "tokio", -] - -[[package]] -name = "rdkafka-sys" -version = "4.8.0+2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced38182dc436b3d9df0c77976f37a67134df26b050df1f0006688e46fc4c8be" -dependencies = [ - "libc", - "libz-sys", - "num_enum", - "pkg-config", -] - -[[package]] -name = "recursive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0786a43debb760f491b1bc0269fe5e84155353c67482b9e60d0cfb596054b43e" -dependencies = [ - "recursive-proc-macro-impl", - "stacker", -] - -[[package]] -name = "recursive-proc-macro-impl" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76009fbe0614077fc1a2ce255e3a1881a2e3a3527097d5dc6d8212c585e7e38b" -dependencies = [ - "quote", - "syn 2.0.100", -] - -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.5.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" -dependencies = [ - "bitflags 2.9.0", -] - -[[package]] -name = "redox_users" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" -dependencies = [ - "getrandom 0.2.15", - "libredox", - "thiserror 2.0.12", -] - -[[package]] -name = "reed-solomon-erasure" -version = "6.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7263373d500d4d4f505d43a2a662d475a894aa94503a1ee28e9188b5f3960d4f" -dependencies = [ - "cc", - "libc", - "libm", - "lru", - "parking_lot 0.11.2", - "smallvec", - "spin", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.9", - "regex-syntax 0.8.5", -] - -[[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.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax 0.8.5", -] - -[[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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "reqwest" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bf597b113be201cb2269b4c39b39a804d01b99ee95a4278f0ed04e45cff1c71" -dependencies = [ - "base64 0.22.1", - "bytes", - "encoding_rs", - "futures-channel", - "futures-core", - "futures-util", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-rustls", - "hyper-util", - "ipnet", - "js-sys", - "log", - "mime", - "mime_guess", - "once_cell", - "percent-encoding", - "pin-project-lite", - "quinn", - "rustls 0.23.27", - "rustls-pki-types", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper", - "tokio", - "tokio-rustls 0.26.2", - "tokio-util", - "tower 0.5.2", - "tower-http", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "webpki-roots 1.0.0", -] - -[[package]] -name = "rfd" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a73a7337fc24366edfca76ec521f51877b114e42dab584008209cca6719251" -dependencies = [ - "ashpd 0.8.1", - "block", - "dispatch", - "js-sys", - "log", - "objc", - "objc-foundation", - "objc_id", - "pollster 0.3.0", - "raw-window-handle 0.6.2", - "urlencoding", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows-sys 0.48.0", -] - -[[package]] -name = "rfd" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80c844748fdc82aae252ee4594a89b6e7ebef1063de7951545564cbc4e57075d" -dependencies = [ - "ashpd 0.11.0", - "block2 0.6.1", - "dispatch2 0.2.0", - "js-sys", - "log", - "objc2 0.6.1", - "objc2-app-kit 0.3.1", - "objc2-core-foundation", - "objc2-foundation 0.3.1", - "pollster 0.4.0", - "raw-window-handle 0.6.2", - "urlencoding", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows-sys 0.59.0", -] - -[[package]] -name = "ring" -version = "0.17.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" -dependencies = [ - "cc", - "cfg-if", - "getrandom 0.2.15", - "libc", - "untrusted", - "windows-sys 0.52.0", -] - -[[package]] -name = "rmp" -version = "0.8.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" -dependencies = [ - "byteorder", - "num-traits", - "paste", -] - -[[package]] -name = "rmp-serde" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" -dependencies = [ - "byteorder", - "rmp", - "serde", -] - -[[package]] -name = "ron" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" -dependencies = [ - "base64 0.21.7", - "bitflags 2.9.0", - "serde", - "serde_derive", -] - -[[package]] -name = "rsa" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" -dependencies = [ - "const-oid 0.9.6", - "digest 0.10.7", - "num-bigint-dig", - "num-integer", - "num-traits", - "pkcs1", - "pkcs8", - "rand_core 0.6.4", - "signature", - "spki", - "subtle", - "zeroize", -] - -[[package]] -name = "rumqttc" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1568e15fab2d546f940ed3a21f48bbbd1c494c90c99c4481339364a497f94a9" -dependencies = [ - "bytes", - "flume", - "futures-util", - "log", - "rustls-native-certs", - "rustls-pemfile", - "rustls-webpki 0.102.8", - "thiserror 1.0.69", - "tokio", - "tokio-rustls 0.25.0", -] - -[[package]] -name = "rust-embed" -version = "8.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e425e204264b144d4c929d126d0de524b40a961686414bab5040f7465c71be" -dependencies = [ - "rust-embed-impl", - "rust-embed-utils", - "walkdir", -] - -[[package]] -name = "rust-embed-impl" -version = "8.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bf418c9a2e3f6663ca38b8a7134cc2c2167c9d69688860e8961e3faa731702e" -dependencies = [ - "proc-macro2", - "quote", - "rust-embed-utils", - "shellexpand", - "syn 2.0.100", - "walkdir", -] - -[[package]] -name = "rust-embed-utils" -version = "8.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d55b95147fe01265d06b3955db798bdaed52e60e2211c41137701b3aba8e21" -dependencies = [ - "sha2 0.10.9", - "walkdir", -] - -[[package]] -name = "rust-ini" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f" -dependencies = [ - "cfg-if", - "ordered-multimap", - "trim-in-place", -] - -[[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.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" -dependencies = [ - "semver", -] - -[[package]] -name = "rustfs" -version = "0.0.1" -dependencies = [ - "api", - "appauth", - "async-trait", - "atoi", - "atomic_enum", - "axum", - "axum-extra", - "axum-server", - "bytes", - "chrono", - "clap", - "common", - "const-str", - "crypto", - "datafusion", - "ecstore", - "flatbuffers 25.2.10", - "futures", - "futures-util", - "http", - "http-body", - "hyper", - "hyper-util", - "iam", - "lazy_static", - "libsystemd", - "lock", - "madmin", - "matchit", - "mime", - "mime_guess", - "netif", - "opentelemetry", - "pin-project-lite", - "policy", - "prost-build", - "protos", - "query", - "rmp-serde", - "rust-embed", - "rustfs-config", - "rustfs-event-notifier", - "rustfs-obs", - "rustfs-utils", - "rustfs-zip", - "rustls 0.23.27", - "s3s", - "serde", - "serde_json", - "serde_urlencoded", - "shadow-rs", - "socket2", - "tikv-jemallocator", - "time", - "tokio", - "tokio-rustls 0.26.2", - "tokio-stream", - "tokio-tar", - "tokio-util", - "tonic 0.13.1", - "tonic-build", - "tower 0.5.2", - "tower-http", - "tracing", - "transform-stream", - "uuid", -] - -[[package]] -name = "rustfs-config" -version = "0.0.1" -dependencies = [ - "config", - "const-str", - "serde", - "serde_json", -] - -[[package]] -name = "rustfs-event-notifier" -version = "0.0.1" -dependencies = [ - "async-trait", - "axum", - "config", - "dotenvy", - "http", - "rdkafka", - "reqwest", - "rumqttc", - "serde", - "serde_json", - "serde_with", - "smallvec", - "strum", - "thiserror 2.0.12", - "tokio", - "tokio-util", - "tracing", - "tracing-subscriber", - "uuid", -] - -[[package]] -name = "rustfs-gui" -version = "0.0.1" -dependencies = [ - "chrono", - "dioxus", - "dirs", - "hex", - "keyring", - "lazy_static", - "rfd 0.15.3", - "rust-embed", - "serde", - "serde_json", - "sha2 0.10.9", - "tokio", - "tracing-appender", - "tracing-subscriber", -] - -[[package]] -name = "rustfs-obs" -version = "0.0.1" -dependencies = [ - "async-trait", - "chrono", - "flexi_logger", - "nu-ansi-term 0.50.1", - "nvml-wrapper", - "opentelemetry", - "opentelemetry-appender-tracing", - "opentelemetry-otlp", - "opentelemetry-semantic-conventions", - "opentelemetry-stdout", - "opentelemetry_sdk", - "rdkafka", - "reqwest", - "rustfs-config", - "rustfs-utils", - "serde", - "serde_json", - "smallvec", - "sysinfo", - "thiserror 2.0.12", - "tokio", - "tracing", - "tracing-core", - "tracing-error", - "tracing-opentelemetry", - "tracing-subscriber", -] - -[[package]] -name = "rustfs-utils" -version = "0.0.1" -dependencies = [ - "local-ip-address", - "rustfs-config", - "rustls 0.23.27", - "rustls-pemfile", - "rustls-pki-types", - "tempfile", - "tracing", -] - -[[package]] -name = "rustfs-zip" -version = "0.0.1" -dependencies = [ - "async-compression", - "async_zip", - "tokio", - "tokio-stream", - "tokio-tar", - "xz2", - "zip", -] - -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.9.0", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustix" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" -dependencies = [ - "bitflags 2.9.0", - "errno", - "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.59.0", -] - -[[package]] -name = "rustls" -version = "0.22.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring", - "rustls-pki-types", - "rustls-webpki 0.102.8", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls" -version = "0.23.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "730944ca083c1c233a75c09f199e973ca499344a2b7ba9e755c457e86fb4a321" -dependencies = [ - "aws-lc-rs", - "log", - "once_cell", - "ring", - "rustls-pki-types", - "rustls-webpki 0.103.2", - "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 2.11.1", -] - -[[package]] -name = "rustls-pemfile" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "rustls-pki-types" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c" -dependencies = [ - "web-time", -] - -[[package]] -name = "rustls-webpki" -version = "0.102.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" -dependencies = [ - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustls-webpki" -version = "0.103.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7149975849f1abb3832b246010ef62ccc80d3a76169517ada7188252b9cfb437" -dependencies = [ - "aws-lc-rs", - "ring", - "rustls-pki-types", - "untrusted", -] - -[[package]] -name = "rustversion" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2" - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "s3s" -version = "0.12.0-dev" -source = "git+https://github.com/Nugine/s3s.git?rev=4733cdfb27b2713e832967232cbff413bb768c10#4733cdfb27b2713e832967232cbff413bb768c10" -dependencies = [ - "arrayvec", - "async-trait", - "atoi", - "base64-simd", - "bytes", - "bytestring", - "chrono", - "const-str", - "crc32c", - "crc32fast", - "crc64fast-nvme", - "futures", - "hex-simd", - "hmac 0.13.0-pre.5", - "http", - "http-body", - "http-body-util", - "httparse", - "hyper", - "itoa 1.0.15", - "md-5", - "memchr", - "mime", - "nom 7.1.3", - "nugine-rust-utils", - "numeric_cast", - "pin-project-lite", - "quick-xml", - "serde", - "serde_urlencoded", - "sha1 0.11.0-pre.5", - "sha2 0.11.0-pre.5", - "smallvec", - "std-next", - "sync_wrapper", - "thiserror 2.0.12", - "time", - "tokio", - "tower 0.5.2", - "tracing", - "transform-stream", - "urlencoding", - "zeroize", -] - -[[package]] -name = "s3s-policy" -version = "0.12.0-dev" -source = "git+https://github.com/Nugine/s3s.git?rev=4733cdfb27b2713e832967232cbff413bb768c10#4733cdfb27b2713e832967232cbff413bb768c10" -dependencies = [ - "indexmap 2.9.0", - "serde", - "serde_json", - "thiserror 2.0.12", -] - -[[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.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" -dependencies = [ - "windows-sys 0.59.0", -] - -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - -[[package]] -name = "security-framework" -version = "2.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" -dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.9.4", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316" -dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.10.0", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" -dependencies = [ - "core-foundation-sys", - "libc", -] - -[[package]] -name = "selectors" -version = "0.22.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df320f1889ac4ba6bc0cdc9c9af7af4bd64bb927bccdf32d81140dc1f9be12fe" -dependencies = [ - "bitflags 1.3.2", - "cssparser", - "derive_more", - "fxhash", - "log", - "matches", - "phf 0.8.0", - "phf_codegen 0.8.0", - "precomputed-hash", - "servo_arc", - "smallvec", - "thin-slice", -] - -[[package]] -name = "semver" -version = "1.0.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" -dependencies = [ - "serde", -] - -[[package]] -name = "send_wrapper" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" -dependencies = [ - "futures-core", -] - -[[package]] -name = "seq-macro" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc711410fbe7399f390ca1c3b60ad0f53f80e95c5eb935e52268a0e2cd49acc" - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde-wasm-bindgen" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "serde_fmt" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4" -dependencies = [ - "serde", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "itoa 1.0.15", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "serde_path_to_error" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" -dependencies = [ - "itoa 1.0.15", - "serde", -] - -[[package]] -name = "serde_qs" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0431a35568651e363364210c91983c1da5eb29404d9f0928b67d4ebcfa7d330c" -dependencies = [ - "percent-encoding", - "serde", - "thiserror 1.0.69", -] - -[[package]] -name = "serde_repr" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "serde_spanned" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" -dependencies = [ - "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 1.0.15", - "ryu", - "serde", -] - -[[package]] -name = "serde_with" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b6f7f2fcb69f747921f79f3926bd1e203fce4fef62c268dd3abfb6d86029aa" -dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.9.0", - "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d00caa5193a3c8362ac2b73be6b9e768aa5a4b2f721d8f4b339600c3cb51f8e" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "server_fn" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fae7a3038a32e5a34ba32c6c45eb4852f8affaf8b794ebfcd4b1099e2d62ebe" -dependencies = [ - "bytes", - "const_format", - "dashmap 5.5.3", - "futures", - "gloo-net", - "http", - "js-sys", - "once_cell", - "reqwest", - "send_wrapper", - "serde", - "serde_json", - "serde_qs", - "server_fn_macro_default", - "thiserror 1.0.69", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "wasm-streams", - "web-sys", - "xxhash-rust", -] - -[[package]] -name = "server_fn_macro" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaaf648c6967aef78177c0610478abb5a3455811f401f3c62d10ae9bd3901a1" -dependencies = [ - "const_format", - "convert_case 0.6.0", - "proc-macro2", - "quote", - "syn 2.0.100", - "xxhash-rust", -] - -[[package]] -name = "server_fn_macro_default" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2aa8119b558a17992e0ac1fd07f080099564f24532858811ce04f742542440" -dependencies = [ - "server_fn_macro", - "syn 2.0.100", -] - -[[package]] -name = "servo_arc" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98238b800e0d1576d8b6e3de32827c2d74bee68bb97748dcf5071fb53965432" -dependencies = [ - "nodrop", - "stable_deref_trait", -] - -[[package]] -name = "sha1" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha1" -version = "0.11.0-pre.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55f44e40722caefdd99383c25d3ae52a1094a1951215ae76f68837ece4e7f566" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.11.0-pre.10", -] - -[[package]] -name = "sha2" -version = "0.10.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.10.7", -] - -[[package]] -name = "sha2" -version = "0.11.0-pre.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b4241d1a56954dce82cecda5c8e9c794eef6f53abe5e5216bac0a0ea71ffa7" -dependencies = [ - "cfg-if", - "cpufeatures", - "digest 0.11.0-pre.10", -] - -[[package]] -name = "shadow-rs" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d5625ed609cf66d7e505e7d487aca815626dc4ebb6c0dd07637ca61a44651a6" -dependencies = [ - "cargo_metadata", - "const_format", - "is_debug", - "serde_json", - "time", - "tzdb", -] - -[[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 = "shellexpand" -version = "3.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" -dependencies = [ - "dirs", -] - -[[package]] -name = "shlex" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" - -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - -[[package]] -name = "signal-hook-registry" -version = "1.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" -dependencies = [ - "libc", -] - -[[package]] -name = "signature" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" -dependencies = [ - "digest 0.10.7", - "rand_core 0.6.4", -] - -[[package]] -name = "simd-adler32" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" - -[[package]] -name = "simdutf8" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" - -[[package]] -name = "simple_asn1" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" -dependencies = [ - "num-bigint", - "num-traits", - "thiserror 2.0.12", - "time", -] - -[[package]] -name = "siphasher" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" - -[[package]] -name = "siphasher" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" - -[[package]] -name = "slab" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" -dependencies = [ - "autocfg", -] - -[[package]] -name = "sledgehammer_bindgen" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49e83e178d176459c92bc129cfd0958afac3ced925471b889b3a75546cfc4133" -dependencies = [ - "sledgehammer_bindgen_macro", - "wasm-bindgen", -] - -[[package]] -name = "sledgehammer_bindgen_macro" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33a1b4f13e2bbf2f5b29d09dfebc9de69229ffee245aed80e3b70f9b5fd28c06" -dependencies = [ - "quote", - "syn 2.0.100", -] - -[[package]] -name = "sledgehammer_utils" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "debdd4b83524961983cea3c55383b3910fd2f24fd13a188f5b091d2d504a61ae" -dependencies = [ - "rustc-hash 1.1.0", -] - -[[package]] -name = "slotmap" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" -dependencies = [ - "serde", - "version_check", -] - -[[package]] -name = "smallvec" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" -dependencies = [ - "serde", -] - -[[package]] -name = "snafu" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "223891c85e2a29c3fe8fb900c1fae5e69c2e42415e3177752e8718475efa5019" -dependencies = [ - "backtrace", - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c3c6b7927ffe7ecaa769ee0e3994da3b8cafc8f444578982c83ecb161af917" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "snap" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" - -[[package]] -name = "socket2" -version = "0.5.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" -dependencies = [ - "libc", - "windows-sys 0.52.0", -] - -[[package]] -name = "soup3" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" -dependencies = [ - "futures-channel", - "gio", - "glib", - "libc", - "soup3-sys", -] - -[[package]] -name = "soup3-sys" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" -dependencies = [ - "gio-sys", - "glib-sys", - "gobject-sys", - "libc", - "system-deps", -] - -[[package]] -name = "spin" -version = "0.9.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" -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 = "sqlparser" -version = "0.54.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66e3b7374ad4a6af849b08b3e7a6eda0edbd82f0fd59b57e22671bf16979899" -dependencies = [ - "log", - "recursive", - "sqlparser_derive", -] - -[[package]] -name = "sqlparser_derive" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da5fc6819faabb412da764b99d3b713bb55083c11e7e0c00144d386cd6a1939c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "stacker" -version = "0.1.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601f9201feb9b09c00266478bf459952b9ef9a6b94edb2f21eba14ab681a60a9" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys 0.59.0", -] - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - -[[package]] -name = "std-next" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1258af3e6890fc6369f89e9d5c052c3406707aef3f8e836697155fb6e07153bf" -dependencies = [ - "simdutf8", - "thiserror 2.0.12", -] - -[[package]] -name = "string_cache" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" -dependencies = [ - "new_debug_unreachable", - "parking_lot 0.12.3", - "phf_shared 0.11.3", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" -dependencies = [ - "phf_generator 0.11.3", - "phf_shared 0.11.3", - "proc-macro2", - "quote", -] - -[[package]] -name = "strsim" -version = "0.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" - -[[package]] -name = "strum" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64def088c51c9510a8579e3c5d67c65349dcf755e5479ad3d010aa6454e2c32" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c77a8c5abcaf0f9ce05d62342b7d298c346515365c36b673df4ebe3ced01fde8" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.100", -] - -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "sval" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9739f56c5d0c44a5ed45473ec868af02eb896af8c05f616673a31e1d1bb09" - -[[package]] -name = "sval_buffer" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f39b07436a8c271b34dad5070c634d1d3d76d6776e938ee97b4a66a5e8003d0b" -dependencies = [ - "sval", - "sval_ref", -] - -[[package]] -name = "sval_dynamic" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffcb072d857431bf885580dacecf05ed987bac931230736739a79051dbf3499b" -dependencies = [ - "sval", -] - -[[package]] -name = "sval_fmt" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f214f427ad94a553e5ca5514c95c6be84667cbc5568cce957f03f3477d03d5c" -dependencies = [ - "itoa 1.0.15", - "ryu", - "sval", -] - -[[package]] -name = "sval_json" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ed34b32e638dec9a99c8ac92d0aa1220d40041026b625474c2b6a4d6f4feb" -dependencies = [ - "itoa 1.0.15", - "ryu", - "sval", -] - -[[package]] -name = "sval_nested" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14bae8fcb2f24fee2c42c1f19037707f7c9a29a0cda936d2188d48a961c4bb2a" -dependencies = [ - "sval", - "sval_buffer", - "sval_ref", -] - -[[package]] -name = "sval_ref" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a4eaea3821d3046dcba81d4b8489421da42961889902342691fb7eab491d79e" -dependencies = [ - "sval", -] - -[[package]] -name = "sval_serde" -version = "2.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "172dd4aa8cb3b45c8ac8f3b4111d644cd26938b0643ede8f93070812b87fb339" -dependencies = [ - "serde", - "sval", - "sval_nested", -] - -[[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.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "sync_wrapper" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" -dependencies = [ - "futures-core", -] - -[[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.100", -] - -[[package]] -name = "sysinfo" -version = "0.35.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79251336d17c72d9762b8b54be4befe38d2db56fbbc0241396d70f173c39d47a" -dependencies = [ - "libc", - "memchr", - "ntapi", - "objc2-core-foundation", - "objc2-io-kit", - "windows 0.61.1", -] - -[[package]] -name = "system-configuration" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" -dependencies = [ - "bitflags 2.9.0", - "core-foundation 0.9.4", - "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 = "system-deps" -version = "6.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" -dependencies = [ - "cfg-expr", - "heck 0.5.0", - "pkg-config", - "toml", - "version-compare", -] - -[[package]] -name = "tao" -version = "0.30.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6682a07cf5bab0b8a2bd20d0a542917ab928b5edb75ebd4eda6b05cbaab872da" -dependencies = [ - "bitflags 2.9.0", - "cocoa 0.26.0", - "core-foundation 0.10.0", - "core-graphics 0.24.0", - "crossbeam-channel", - "dispatch", - "dlopen2", - "dpi", - "gdkwayland-sys", - "gdkx11-sys", - "gtk", - "instant", - "jni", - "lazy_static", - "libc", - "log", - "ndk", - "ndk-context", - "ndk-sys", - "objc", - "once_cell", - "parking_lot 0.12.3", - "raw-window-handle 0.5.2", - "raw-window-handle 0.6.2", - "scopeguard", - "tao-macros", - "unicode-segmentation", - "url", - "windows 0.58.0", - "windows-core 0.58.0", - "windows-version", - "x11-dl", -] - -[[package]] -name = "tao-macros" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "target-lexicon" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" - -[[package]] -name = "tempfile" -version = "3.19.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" -dependencies = [ - "fastrand", - "getrandom 0.3.2", - "once_cell", - "rustix 1.0.5", - "windows-sys 0.59.0", -] - -[[package]] -name = "tendril" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" -dependencies = [ - "futf", - "mac", - "utf-8", -] - -[[package]] -name = "test-case" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2550dd13afcd286853192af8601920d959b14c401fcece38071d53bf0768a8" -dependencies = [ - "test-case-macros", -] - -[[package]] -name = "test-case-core" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adcb7fd841cd518e279be3d5a3eb0636409487998a4aff22f3de87b81e88384f" -dependencies = [ - "cfg-if", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "test-case-macros" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c89e72a01ed4c579669add59014b9a524d609c0c88c6a585ce37485879f6ffb" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "test-case-core", -] - -[[package]] -name = "thin-slice" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaa81235c7058867fa8c0e7314f33dcce9c215f535d1913822a2b3f5e289f3c" - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl 1.0.69", -] - -[[package]] -name = "thiserror" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708" -dependencies = [ - "thiserror-impl 2.0.12", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "thread_local" -version = "1.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "thrift" -version = "0.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e54bc85fc7faa8bc175c4bab5b92ba8d9a3ce893d0e9f42cc455c8ab16a9e09" -dependencies = [ - "byteorder", - "integer-encoding", - "ordered-float", -] - -[[package]] -name = "tikv-jemalloc-sys" -version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "tikv-jemallocator" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cec5ff18518d81584f477e9bfdf957f5bb0979b0bac3af4ca30b5b3ae2d2865" -dependencies = [ - "libc", - "tikv-jemalloc-sys", -] - -[[package]] -name = "time" -version = "0.3.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" -dependencies = [ - "deranged", - "itoa 1.0.15", - "libc", - "num-conv", - "num_threads", - "powerfmt", - "serde", - "time-core", - "time-macros", -] - -[[package]] -name = "time-core" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" - -[[package]] -name = "time-macros" -version = "0.2.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" -dependencies = [ - "num-conv", - "time-core", -] - -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - -[[package]] -name = "tinyvec" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" -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", - "parking_lot 0.12.3", - "pin-project-lite", - "signal-hook-registry", - "socket2", - "tokio-macros", - "tracing", - "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.100", -] - -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - -[[package]] -name = "tokio-rustls" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" -dependencies = [ - "rustls 0.23.27", - "tokio", -] - -[[package]] -name = "tokio-stream" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" -dependencies = [ - "futures-core", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "tokio-tar" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5714c010ca3e5c27114c1cdeb9d14641ace49874aa5626d7149e47aedace75" -dependencies = [ - "filetime", - "futures-core", - "libc", - "redox_syscall 0.3.5", - "tokio", - "tokio-stream", - "xattr", -] - -[[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-io", - "futures-sink", - "pin-project-lite", - "tokio", -] - -[[package]] -name = "toml" -version = "0.8.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148" -dependencies = [ - "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.22.24", -] - -[[package]] -name = "toml_datetime" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" -dependencies = [ - "serde", -] - -[[package]] -name = "toml_edit" -version = "0.19.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap 2.9.0", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap 2.9.0", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.22.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" -dependencies = [ - "indexmap 2.9.0", - "serde", - "serde_spanned", - "toml_datetime", - "winnow 0.7.6", -] - -[[package]] -name = "tonic" -version = "0.12.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" -dependencies = [ - "async-trait", - "base64 0.22.1", - "bytes", - "flate2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-timeout", - "hyper-util", - "percent-encoding", - "pin-project", - "prost", - "tokio", - "tokio-stream", - "tower 0.4.13", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tonic" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9" -dependencies = [ - "async-trait", - "axum", - "base64 0.22.1", - "bytes", - "flate2", - "h2", - "http", - "http-body", - "http-body-util", - "hyper", - "hyper-timeout", - "hyper-util", - "percent-encoding", - "pin-project", - "prost", - "socket2", - "tokio", - "tokio-stream", - "tower 0.5.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tonic-build" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac6f67be712d12f0b41328db3137e0d0757645d8904b4cb7d51cd9c2279e847" -dependencies = [ - "prettyplease", - "proc-macro2", - "prost-build", - "prost-types", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tower" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" -dependencies = [ - "futures-core", - "futures-util", - "indexmap 1.9.3", - "pin-project", - "pin-project-lite", - "rand 0.8.5", - "slab", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" -dependencies = [ - "futures-core", - "futures-util", - "indexmap 2.9.0", - "pin-project-lite", - "slab", - "sync_wrapper", - "tokio", - "tokio-util", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-http" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e" -dependencies = [ - "async-compression", - "bitflags 2.9.0", - "bytes", - "futures-core", - "futures-util", - "http", - "http-body", - "iri-string", - "pin-project-lite", - "tokio", - "tokio-util", - "tower 0.5.2", - "tower-layer", - "tower-service", - "tracing", -] - -[[package]] -name = "tower-layer" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" - -[[package]] -name = "tower-service" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" - -[[package]] -name = "tracing" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" -dependencies = [ - "log", - "pin-project-lite", - "tracing-attributes", - "tracing-core", -] - -[[package]] -name = "tracing-appender" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" -dependencies = [ - "crossbeam-channel", - "thiserror 1.0.69", - "time", - "tracing-subscriber", -] - -[[package]] -name = "tracing-attributes" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "tracing-core" -version = "0.1.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" -dependencies = [ - "once_cell", - "valuable", -] - -[[package]] -name = "tracing-error" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" -dependencies = [ - "tracing", - "tracing-subscriber", -] - -[[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-opentelemetry" -version = "0.30.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd8e764bd6f5813fd8bebc3117875190c5b0415be8f7f8059bffb6ecd979c444" -dependencies = [ - "js-sys", - "once_cell", - "opentelemetry", - "opentelemetry_sdk", - "smallvec", - "tracing", - "tracing-core", - "tracing-log", - "tracing-subscriber", - "web-time", -] - -[[package]] -name = "tracing-serde" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" -dependencies = [ - "serde", - "tracing-core", -] - -[[package]] -name = "tracing-subscriber" -version = "0.3.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" -dependencies = [ - "matchers", - "nu-ansi-term 0.46.0", - "once_cell", - "regex", - "serde", - "serde_json", - "sharded-slab", - "smallvec", - "thread_local", - "time", - "tracing", - "tracing-core", - "tracing-log", - "tracing-serde", -] - -[[package]] -name = "tracing-wasm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" -dependencies = [ - "tracing", - "tracing-subscriber", - "wasm-bindgen", -] - -[[package]] -name = "transform-stream" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a814d25437963577f6221d33a2aaa60bfb44acc3330cdc7c334644e9832022" -dependencies = [ - "futures-core", -] - -[[package]] -name = "tray-icon" -version = "0.19.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eadd75f5002e2513eaa19b2365f533090cc3e93abd38788452d9ea85cff7b48a" -dependencies = [ - "crossbeam-channel", - "dirs", - "libappindicator", - "muda 0.15.3", - "objc2 0.6.1", - "objc2-app-kit 0.3.1", - "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation 0.3.1", - "once_cell", - "png", - "thiserror 2.0.12", - "windows-sys 0.59.0", -] - -[[package]] -name = "trim-in-place" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc" - -[[package]] -name = "try-lock" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" - -[[package]] -name = "tungstenite" -version = "0.23.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http", - "httparse", - "log", - "rand 0.8.5", - "sha1 0.10.6", - "thiserror 1.0.69", - "utf-8", -] - -[[package]] -name = "twox-hash" -version = "1.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" -dependencies = [ - "cfg-if", - "static_assertions", -] - -[[package]] -name = "typeid" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" - -[[package]] -name = "typenum" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" - -[[package]] -name = "tz-rs" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1450bf2b99397e72070e7935c89facaa80092ac812502200375f1f7d33c71a1" - -[[package]] -name = "tzdb" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be2ea5956f295449f47c0b825c5e109022ff1a6a53bb4f77682a87c2341fbf5" -dependencies = [ - "iana-time-zone", - "tz-rs", - "tzdb_data", -] - -[[package]] -name = "tzdb_data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c4c81d75033770e40fbd3643ce7472a1a9fd301f90b7139038228daf8af03ec" -dependencies = [ - "tz-rs", -] - -[[package]] -name = "ucd-trie" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" - -[[package]] -name = "uds_windows" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" -dependencies = [ - "memoffset", - "tempfile", - "winapi", -] - -[[package]] -name = "unicase" -version = "2.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" - -[[package]] -name = "unicode-xid" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" - -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common 0.1.6", - "subtle", -] - -[[package]] -name = "untrusted" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" - -[[package]] -name = "url" -version = "2.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" -dependencies = [ - "form_urlencoded", - "idna", - "percent-encoding", - "serde", -] - -[[package]] -name = "urlencoding" -version = "2.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" - -[[package]] -name = "utf-8" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" - -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - -[[package]] -name = "uuid" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "458f7a779bf54acc9f347480ac654f68407d3aab21269a6e3c9f922acd9e2da9" -dependencies = [ - "getrandom 0.3.2", - "js-sys", - "rand 0.9.1", - "serde", - "uuid-macro-internal", - "wasm-bindgen", -] - -[[package]] -name = "uuid-macro-internal" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72dcd78c4f979627a754f5522cea6e6a25e55139056535fe6e69c506cd64a862" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "valuable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" - -[[package]] -name = "value-bag" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943ce29a8a743eb10d6082545d861b24f9d1b160b7d741e0f2cdf726bec909c5" -dependencies = [ - "value-bag-serde1", - "value-bag-sval2", -] - -[[package]] -name = "value-bag-serde1" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35540706617d373b118d550d41f5dfe0b78a0c195dc13c6815e92e2638432306" -dependencies = [ - "erased-serde", - "serde", - "serde_fmt", -] - -[[package]] -name = "value-bag-sval2" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fe7e140a2658cc16f7ee7a86e413e803fc8f9b5127adc8755c19f9fefa63a52" -dependencies = [ - "sval", - "sval_buffer", - "sval_dynamic", - "sval_fmt", - "sval_json", - "sval_ref", - "sval_serde", -] - -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - -[[package]] -name = "version-compare" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" - -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - -[[package]] -name = "vsimd" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" - -[[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 = "warnings" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64f68998838dab65727c9b30465595c6f7c953313559371ca8bf31759b3680ad" -dependencies = [ - "pin-project", - "tracing", - "warnings-macro", -] - -[[package]] -name = "warnings-macro" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59195a1db0e95b920366d949ba5e0d3fc0e70b67c09be15ce5abb790106b0571" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "wasm-bindgen" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" -dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.100", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-futures" -version = "0.4.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" -dependencies = [ - "cfg-if", - "js-sys", - "once_cell", - "wasm-bindgen", - "web-sys", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" -dependencies = [ - "quote", - "wasm-bindgen-macro-support", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "wasm-bindgen-backend", - "wasm-bindgen-shared", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "wasm-streams" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" -dependencies = [ - "futures-util", - "js-sys", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "web-sys" -version = "0.3.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "web-time" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - -[[package]] -name = "webbrowser" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b" -dependencies = [ - "core-foundation 0.9.4", - "home", - "jni", - "log", - "ndk-context", - "objc", - "raw-window-handle 0.5.2", - "url", - "web-sys", -] - -[[package]] -name = "webkit2gtk" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" -dependencies = [ - "bitflags 1.3.2", - "cairo-rs", - "gdk", - "gdk-sys", - "gio", - "gio-sys", - "glib", - "glib-sys", - "gobject-sys", - "gtk", - "gtk-sys", - "javascriptcore-rs", - "libc", - "once_cell", - "soup3", - "webkit2gtk-sys", -] - -[[package]] -name = "webkit2gtk-sys" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" -dependencies = [ - "bitflags 1.3.2", - "cairo-sys-rs", - "gdk-sys", - "gio-sys", - "glib-sys", - "gobject-sys", - "gtk-sys", - "javascriptcore-rs-sys", - "libc", - "pkg-config", - "soup3-sys", - "system-deps", -] - -[[package]] -name = "webpki-roots" -version = "0.26.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "webpki-roots" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2853738d1cc4f2da3a225c18ec6c3721abb31961096e9dbf5ab35fa88b19cfdb" -dependencies = [ - "rustls-pki-types", -] - -[[package]] -name = "webview2-com" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61ff3d9d0ee4efcb461b14eb3acfda2702d10dc329f339303fc3e57215ae2c" -dependencies = [ - "webview2-com-macros", - "webview2-com-sys", - "windows 0.58.0", - "windows-core 0.58.0", - "windows-implement 0.58.0", - "windows-interface 0.58.0", -] - -[[package]] -name = "webview2-com-macros" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d228f15bba3b9d56dde8bddbee66fa24545bd17b48d5128ccf4a8742b18e431" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "webview2-com-sys" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3a3e2eeb58f82361c93f9777014668eb3d07e7d174ee4c819575a9208011886" -dependencies = [ - "thiserror 1.0.69", - "windows 0.58.0", - "windows-core 0.58.0", -] - -[[package]] -name = "which" -version = "4.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" -dependencies = [ - "either", - "home", - "once_cell", - "rustix 0.38.44", -] - -[[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.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" -dependencies = [ - "windows-sys 0.59.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.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" -dependencies = [ - "windows-core 0.58.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows" -version = "0.61.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" -dependencies = [ - "windows-collections", - "windows-core 0.61.0", - "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.0", -] - -[[package]] -name = "windows-core" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" -dependencies = [ - "windows-implement 0.58.0", - "windows-interface 0.58.0", - "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-core" -version = "0.61.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" -dependencies = [ - "windows-implement 0.60.0", - "windows-interface 0.59.1", - "windows-link", - "windows-result 0.3.2", - "windows-strings 0.4.0", -] - -[[package]] -name = "windows-future" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a1d6bbefcb7b60acd19828e1bc965da6fcf18a7e39490c5f8be71e54a19ba32" -dependencies = [ - "windows-core 0.61.0", - "windows-link", -] - -[[package]] -name = "windows-implement" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[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.100", -] - -[[package]] -name = "windows-interface" -version = "0.58.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[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.100", -] - -[[package]] -name = "windows-link" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" - -[[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.0", - "windows-link", -] - -[[package]] -name = "windows-registry" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" -dependencies = [ - "windows-result 0.3.2", - "windows-strings 0.3.1", - "windows-targets 0.53.0", -] - -[[package]] -name = "windows-result" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-result" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" -dependencies = [ - "windows-result 0.2.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-strings" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-strings" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[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.6", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "windows_i686_msvc 0.52.6", - "windows_x86_64_gnu 0.52.6", - "windows_x86_64_gnullvm 0.52.6", - "windows_x86_64_msvc 0.52.6", -] - -[[package]] -name = "windows-targets" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows-version" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04a5c6627e310a23ad2358483286c7df260c964eb2d003d8efd6d0f4e79265c" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[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.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" -dependencies = [ - "memchr", -] - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags 2.9.0", -] - -[[package]] -name = "workers" -version = "0.0.1" -dependencies = [ - "common", - "tokio", - "tracing", -] - -[[package]] -name = "wrapcenum-derive" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76ff259533532054cfbaefb115c613203c73707017459206380f03b3b3f266e" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - -[[package]] -name = "wry" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac0099a336829fbf54c26b5f620c68980ebbe37196772aeaf6118df4931b5cb0" -dependencies = [ - "base64 0.22.1", - "block", - "cocoa 0.26.0", - "core-graphics 0.24.0", - "crossbeam-channel", - "dpi", - "dunce", - "gdkx11", - "gtk", - "html5ever", - "http", - "javascriptcore-rs", - "jni", - "kuchikiki", - "libc", - "ndk", - "objc", - "objc_id", - "once_cell", - "percent-encoding", - "raw-window-handle 0.6.2", - "sha2 0.10.9", - "soup3", - "tao-macros", - "thiserror 1.0.69", - "webkit2gtk", - "webkit2gtk-sys", - "webview2-com", - "windows 0.58.0", - "windows-core 0.58.0", - "windows-version", - "x11-dl", -] - -[[package]] -name = "x11" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" -dependencies = [ - "libc", - "pkg-config", -] - -[[package]] -name = "x11-dl" -version = "2.21.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" -dependencies = [ - "libc", - "once_cell", - "pkg-config", -] - -[[package]] -name = "xattr" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d65cbf2f12c15564212d48f4e3dfb87923d25d611f2aed18f4cb23f0413d89e" -dependencies = [ - "libc", - "rustix 1.0.5", -] - -[[package]] -name = "xdg-home" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "xxhash-rust" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" - -[[package]] -name = "xz2" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2" -dependencies = [ - "lzma-sys", -] - -[[package]] -name = "yaml-rust2" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "818913695e83ece1f8d2a1c52d54484b7b46d0f9c06beeb2649b9da50d9b512d" -dependencies = [ - "arraydeque", - "encoding_rs", - "hashlink", -] - -[[package]] -name = "yoke" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "synstructure", -] - -[[package]] -name = "zbus" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb97012beadd29e654708a0fdb4c84bc046f537aecfde2c3ee0a9e4b4d48c725" -dependencies = [ - "async-broadcast", - "async-process", - "async-recursion", - "async-trait", - "enumflags2", - "event-listener", - "futures-core", - "futures-sink", - "futures-util", - "hex", - "nix 0.29.0", - "ordered-stream", - "rand 0.8.5", - "serde", - "serde_repr", - "sha1 0.10.6", - "static_assertions", - "tokio", - "tracing", - "uds_windows", - "windows-sys 0.52.0", - "xdg-home", - "zbus_macros 4.4.0", - "zbus_names 3.0.0", - "zvariant 4.2.0", -] - -[[package]] -name = "zbus" -version = "5.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59c333f648ea1b647bc95dc1d34807c8e25ed7a6feff3394034dc4776054b236" -dependencies = [ - "async-broadcast", - "async-recursion", - "async-trait", - "enumflags2", - "event-listener", - "futures-core", - "futures-lite", - "hex", - "nix 0.29.0", - "ordered-stream", - "serde", - "serde_repr", - "static_assertions", - "tokio", - "tracing", - "uds_windows", - "windows-sys 0.59.0", - "winnow 0.7.6", - "xdg-home", - "zbus_macros 5.5.0", - "zbus_names 4.2.0", - "zvariant 5.4.0", -] - -[[package]] -name = "zbus_macros" -version = "4.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "267db9407081e90bbfa46d841d3cbc60f59c0351838c4bc65199ecd79ab1983e" -dependencies = [ - "proc-macro-crate 3.3.0", - "proc-macro2", - "quote", - "syn 2.0.100", - "zvariant_utils 2.1.0", -] - -[[package]] -name = "zbus_macros" -version = "5.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f325ad10eb0d0a3eb060203494c3b7ec3162a01a59db75d2deee100339709fc0" -dependencies = [ - "proc-macro-crate 3.3.0", - "proc-macro2", - "quote", - "syn 2.0.100", - "zbus_names 4.2.0", - "zvariant 5.4.0", - "zvariant_utils 3.2.0", -] - -[[package]] -name = "zbus_names" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" -dependencies = [ - "serde", - "static_assertions", - "zvariant 4.2.0", -] - -[[package]] -name = "zbus_names" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be68e64bf6ce8db94f63e72f0c7eb9a60d733f7e0499e628dfab0f84d6bcb97" -dependencies = [ - "serde", - "static_assertions", - "winnow 0.7.6", - "zvariant 5.4.0", -] - -[[package]] -name = "zerocopy" -version = "0.7.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" -dependencies = [ - "zerocopy-derive 0.7.35", -] - -[[package]] -name = "zerocopy" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" -dependencies = [ - "zerocopy-derive 0.8.24", -] - -[[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.100", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zerofrom" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", - "synstructure", -] - -[[package]] -name = "zeroize" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zerovec" -version = "0.10.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zip" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabe6324e908f85a1c52063ce7aa26b68dcb7eb6dbc83a2d148403c9bc3eba50" -dependencies = [ - "aes", - "arbitrary", - "bzip2", - "constant_time_eq", - "crc32fast", - "crossbeam-utils", - "deflate64", - "displaydoc", - "flate2", - "getrandom 0.3.2", - "hmac 0.12.1", - "indexmap 2.9.0", - "lzma-rs", - "memchr", - "pbkdf2", - "sha1 0.10.6", - "thiserror 2.0.12", - "time", - "xz2", - "zeroize", - "zopfli", - "zstd", -] - -[[package]] -name = "zopfli" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfc5ee405f504cd4984ecc6f14d02d55cfda60fa4b689434ef4102aae150cd7" -dependencies = [ - "bumpalo", - "crc32fast", - "log", - "simd-adler32", -] - -[[package]] -name = "zstd" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" -dependencies = [ - "zstd-safe", -] - -[[package]] -name = "zstd-safe" -version = "7.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" -dependencies = [ - "zstd-sys", -] - -[[package]] -name = "zstd-sys" -version = "2.0.15+zstd.1.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237" -dependencies = [ - "cc", - "pkg-config", -] - -[[package]] -name = "zvariant" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2084290ab9a1c471c38fc524945837734fbf124487e105daec2bb57fd48c81fe" -dependencies = [ - "endi", - "enumflags2", - "serde", - "static_assertions", - "url", - "zvariant_derive 4.2.0", -] - -[[package]] -name = "zvariant" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2df9ee044893fcffbdc25de30546edef3e32341466811ca18421e3cd6c5a3ac" -dependencies = [ - "endi", - "enumflags2", - "serde", - "static_assertions", - "url", - "winnow 0.7.6", - "zvariant_derive 5.4.0", - "zvariant_utils 3.2.0", -] - -[[package]] -name = "zvariant_derive" -version = "4.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73e2ba546bda683a90652bac4a279bc146adad1386f25379cf73200d2002c449" -dependencies = [ - "proc-macro-crate 3.3.0", - "proc-macro2", - "quote", - "syn 2.0.100", - "zvariant_utils 2.1.0", -] - -[[package]] -name = "zvariant_derive" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74170caa85b8b84cc4935f2d56a57c7a15ea6185ccdd7eadb57e6edd90f94b2f" -dependencies = [ - "proc-macro-crate 3.3.0", - "proc-macro2", - "quote", - "syn 2.0.100", - "zvariant_utils 3.2.0", -] - -[[package]] -name = "zvariant_utils" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51bcff7cc3dbb5055396bcf774748c3dab426b4b8659046963523cee4808340" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.100", -] - -[[package]] -name = "zvariant_utils" -version = "3.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16edfee43e5d7b553b77872d99bc36afdda75c223ca7ad5e3fbecd82ca5fc34" -dependencies = [ - "proc-macro2", - "quote", - "serde", - "static_assertions", - "syn 2.0.100", - "winnow 0.7.6", -] diff --git a/bucket_replicate_test.md b/bucket_replicate_test.md new file mode 100644 index 00000000..c2ce554d --- /dev/null +++ b/bucket_replicate_test.md @@ -0,0 +1,45 @@ +启动两个rustfs +rustfs --address 0.0.0.0:9000 /rustfs-data9000 +rustfs --address 0.0.0.0:9001 /rustfs-data9001 + + +### 使用 minio mc 设置 alias 分别为 rustfs 和 rustfs2 + + +### 创建 bucket +mc mb rustfs/srcbucket + +### 创建 desc bucket + +mc mb rustfs2/destbucket + + + +### 开启版本控制 + +mc version enable rustfs/srcbucket +mc version enable rustfs2/destbucket + +#### 使用修改过的 mc 才能 add bucket replication + +./mc replication add rustfs/srcbucket --remote-bucket rustfs2/destbucket + + + +###### 复制一个小文件; +mc cp ./1.txt rustfs/srcbucket + +###### 查看是否成功 +mc ls --versions rustfs/srcbucket/1.txt +mc ls --versions rustfs/destbucket/1.txt + + +##### 复制一个大文件 +1 创建一个大文件 +dd if=/dev/zero of=./dd.out bs=4096000 count=1000 + +mc cp ./dd.out rustfs/srcbucket/ + +##### 查看是否成功 +mc ls --versions rustfs/srcbucket/dd.out +mc ls --versions rustfs2/destbucket/dd.out diff --git a/build_rustfs.sh b/build_rustfs.sh new file mode 100755 index 00000000..6a7d7149 --- /dev/null +++ b/build_rustfs.sh @@ -0,0 +1,21 @@ +#!/bin/bash +clear + +# 获取当前平台架构 +ARCH=$(uname -m) + +# 根据架构设置 target 目录 +if [ "$ARCH" == "x86_64" ]; then + TARGET_DIR="target/x86_64" +elif [ "$ARCH" == "aarch64" ]; then + TARGET_DIR="target/arm64" +else + TARGET_DIR="target/unknown" +fi + +# 设置 CARGO_TARGET_DIR 并构建项目 +CARGO_TARGET_DIR=$TARGET_DIR RUSTFLAGS="-C link-arg=-fuse-ld=mold" cargo build --package rustfs + +echo -e "\a" +echo -e "\a" +echo -e "\a" diff --git a/common/common/src/bucket_stats.rs b/common/common/src/bucket_stats.rs new file mode 100644 index 00000000..4e0be53e --- /dev/null +++ b/common/common/src/bucket_stats.rs @@ -0,0 +1,73 @@ +use std::{collections::HashMap, i64, u64}; + +use crate::last_minute::{self}; +pub struct ReplicationLatency { + // 单个和多部分 PUT 请求的延迟 + upload_histogram: last_minute::LastMinuteHistogram, +} + +impl ReplicationLatency { + // 合并两个 ReplicationLatency + pub fn merge(&mut self, other: &mut ReplicationLatency) -> &ReplicationLatency { + self.upload_histogram.merge(&other.upload_histogram); + return self; + } + + // 获取上传延迟(按对象大小区间分类) + pub fn get_upload_latency(&mut self) -> HashMap { + let mut ret = HashMap::new(); + let avg = self.upload_histogram.get_avg_data(); + for (i, v) in avg.iter().enumerate() { + let avg_duration = v.avg(); + ret.insert(self.size_tag_to_string(i), avg_duration.as_millis() as u64); + } + ret + } + pub fn update(&mut self, size: i64, during: std::time::Duration) { + self.upload_histogram.add(size, during); + } + + // 模拟从 size tag 到字符串的转换 + fn size_tag_to_string(&self, tag: usize) -> String { + match tag { + 0 => String::from("Size < 1 KiB"), + 1 => String::from("Size < 1 MiB"), + 2 => String::from("Size < 10 MiB"), + 3 => String::from("Size < 100 MiB"), + 4 => String::from("Size < 1 GiB"), + _ => String::from("Size > 1 GiB"), + } + } +} + +// #[derive(Debug, Clone, Default)] +// pub struct ReplicationLastMinute { +// pub last_minute: LastMinuteLatency, +// } + +// impl ReplicationLastMinute { +// pub fn merge(&mut self, other: ReplicationLastMinute) -> ReplicationLastMinute { +// let mut nl = ReplicationLastMinute::default(); +// nl.last_minute = self.last_minute.merge(&mut other.last_minute); +// nl +// } + +// pub fn add_size(&mut self, n: i64) { +// let t = SystemTime::now() +// .duration_since(UNIX_EPOCH) +// .expect("Time went backwards") +// .as_secs(); +// self.last_minute.add_all(t - 1, &AccElem { total: t - 1, size: n as u64, n: 1 }); +// } + +// pub fn get_total(&self) -> AccElem { +// self.last_minute.get_total() +// } +// } + +// impl fmt::Display for ReplicationLastMinute { +// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +// let t = self.last_minute.get_total(); +// write!(f, "ReplicationLastMinute sz= {}, n= {}, dur= {}", t.size, t.n, t.total) +// } +// } diff --git a/common/common/src/last_minute.rs b/common/common/src/last_minute.rs index 2c9a9bc8..2b0c6f83 100644 --- a/common/common/src/last_minute.rs +++ b/common/common/src/last_minute.rs @@ -1,6 +1,81 @@ -use std::time::{Duration, SystemTime, UNIX_EPOCH}; +use std::{time::{Duration, SystemTime, UNIX_EPOCH}}; -#[derive(Clone, Debug, Default)] +#[allow(dead_code)] +#[derive(Debug, Default)] +struct TimedAction { + count: u64, + acc_time: u64, + min_time: Option, + max_time: Option, + bytes: u64, +} + +#[allow(dead_code)] +impl TimedAction { + // Avg returns the average time spent on the action. + pub fn avg(&self) -> Option { + if self.count == 0 { + return None; + } + Some(std::time::Duration::from_nanos(self.acc_time / self.count)) + } + + // AvgBytes returns the average bytes processed. + pub fn avg_bytes(&self) -> u64 { + if self.count == 0 { + return 0; + } + self.bytes / self.count + } + + // Merge other into t. + pub fn merge(&mut self, other: TimedAction) { + self.count += other.count; + self.acc_time += other.acc_time; + self.bytes += other.bytes; + + if self.count == 0 { + self.min_time = other.min_time; + } + if let Some(other_min) = other.min_time { + self.min_time = self.min_time.map_or(Some(other_min), |min| Some(min.min(other_min))); + } + + self.max_time = self + .max_time + .map_or(other.max_time, |max| Some(max.max(other.max_time.unwrap_or(0)))); + } +} + +#[allow(dead_code)] +#[derive(Debug)] +enum SizeCategory { + SizeLessThan1KiB = 0, + SizeLessThan1MiB, + SizeLessThan10MiB, + SizeLessThan100MiB, + SizeLessThan1GiB, + SizeGreaterThan1GiB, + // Add new entries here + SizeLastElemMarker, +} + +#[allow(dead_code)] +impl SizeCategory { + fn to_string(&self) -> String { + match *self { + SizeCategory::SizeLessThan1KiB => "SizeLessThan1KiB".to_string(), + SizeCategory::SizeLessThan1MiB => "SizeLessThan1MiB".to_string(), + SizeCategory::SizeLessThan10MiB => "SizeLessThan10MiB".to_string(), + SizeCategory::SizeLessThan100MiB => "SizeLessThan100MiB".to_string(), + SizeCategory::SizeLessThan1GiB => "SizeLessThan1GiB".to_string(), + SizeCategory::SizeGreaterThan1GiB => "SizeGreaterThan1GiB".to_string(), + SizeCategory::SizeLastElemMarker => "SizeLastElemMarker".to_string(), + } + } +} + +#[derive(Clone, Debug, Default, Copy)] pub struct AccElem { pub total: u64, pub size: u64, @@ -28,7 +103,7 @@ impl AccElem { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct LastMinuteLatency { pub totals: Vec, pub last_sec: u64, @@ -44,10 +119,11 @@ impl Default for LastMinuteLatency { } impl LastMinuteLatency { - pub fn merge(&mut self, o: &mut LastMinuteLatency) -> LastMinuteLatency { + pub fn merge(&mut self, o: &LastMinuteLatency) -> LastMinuteLatency { let mut merged = LastMinuteLatency::default(); + let mut x = o.clone(); if self.last_sec > o.last_sec { - o.forward_to(self.last_sec); + x.forward_to(self.last_sec); merged.last_sec = self.last_sec; } else { self.forward_to(o.last_sec); @@ -111,7 +187,6 @@ impl LastMinuteLatency { } } } - #[cfg(test)] mod tests { use super::*; @@ -755,3 +830,48 @@ mod tests { assert_eq!(elem.avg(), Duration::from_secs(0)); } } + + + +const SIZE_LAST_ELEM_MARKER: usize = 10; // 这里假设你的 marker 是 10,请根据实际情况修改 + + +#[allow(dead_code)] +#[derive(Debug, Default)] +pub struct LastMinuteHistogram { + histogram: Vec, + size: u32, +} + + +impl LastMinuteHistogram { + pub fn merge(&mut self, other: &LastMinuteHistogram) { + for i in 0..self.histogram.len() { + self.histogram[i].merge(&other.histogram[i]); + } + } + + pub fn add(&mut self, size: i64, t: std::time::Duration) { + let index = size_to_tag(size); + self.histogram[index].add(&t); + } + + pub fn get_avg_data(&mut self) -> [AccElem; SIZE_LAST_ELEM_MARKER] { + let mut res = [AccElem::default(); SIZE_LAST_ELEM_MARKER]; + for (i, elem) in self.histogram.iter_mut().enumerate() { + res[i] = elem.get_total(); + } + res + } +} + +fn size_to_tag(size: i64) -> usize { + match size { + _ if size < 1024 => 0, // sizeLessThan1KiB + _ if size < 1024 * 1024 => 1, // sizeLessThan1MiB + _ if size < 10 * 1024 * 1024 => 2, // sizeLessThan10MiB + _ if size < 100 * 1024 * 1024 => 3, // sizeLessThan100MiB + _ if size < 1024 * 1024 * 1024 => 4, // sizeLessThan1GiB + _ => 5, // sizeGreaterThan1GiB + } +} \ No newline at end of file diff --git a/common/common/src/lib.rs b/common/common/src/lib.rs index 90250c5e..e6a3849f 100644 --- a/common/common/src/lib.rs +++ b/common/common/src/lib.rs @@ -1,6 +1,7 @@ pub mod error; pub mod globals; pub mod last_minute; +pub mod bucket_stats; // is ',' pub static DEFAULT_DELIMITER: u8 = 44; diff --git a/crypto/src/encdec/decrypt.rs b/crypto/src/encdec/decrypt.rs index e3660e6d..f339f219 100644 --- a/crypto/src/encdec/decrypt.rs +++ b/crypto/src/encdec/decrypt.rs @@ -28,6 +28,97 @@ pub fn decrypt_data(password: &[u8], data: &[u8]) -> Result, crate::Erro } } +// use argon2::{Argon2, PasswordHasher}; +// use argon2::password_hash::{SaltString}; +// use aes_gcm::{Aes256Gcm, Key, Nonce}; // For AES-GCM +// use chacha20poly1305::{ChaCha20Poly1305, Key as ChaChaKey, Nonce as ChaChaNonce}; // For ChaCha20 +// use pbkdf2::pbkdf2; +// use sha2::Sha256; +// use std::io::{self, Read}; +// use thiserror::Error; + +// #[derive(Debug, Error)] +// pub enum DecryptError { +// #[error("unexpected header")] +// UnexpectedHeader, +// #[error("invalid encryption algorithm ID")] +// InvalidAlgorithmId, +// #[error("IO error")] +// Io(#[from] io::Error), +// #[error("decryption error")] +// DecryptionError, +// } + +// pub fn decrypt_data2(password: &str, mut data: R) -> Result, DecryptError> { +// // Parse the stream header +// let mut hdr = [0u8; 32 + 1 + 8]; +// if data.read_exact(&mut hdr).is_err() { +// return Err(DecryptError::UnexpectedHeader); +// } + +// let salt = &hdr[0..32]; +// let id = hdr[32]; +// let nonce = &hdr[33..41]; + +// let key = match id { +// // Argon2id + AES-GCM +// 0x01 => { +// let salt = SaltString::encode_b64(salt).map_err(|_| DecryptError::DecryptionError)?; +// let argon2 = Argon2::default(); +// let hashed_key = argon2.hash_password(password.as_bytes(), &salt) +// .map_err(|_| DecryptError::DecryptionError)?; +// hashed_key.hash.unwrap().as_bytes().to_vec() +// } +// // Argon2id + ChaCha20Poly1305 +// 0x02 => { +// let salt = SaltString::encode_b64(salt).map_err(|_| DecryptError::DecryptionError)?; +// let argon2 = Argon2::default(); +// let hashed_key = argon2.hash_password(password.as_bytes(), &salt) +// .map_err(|_| DecryptError::DecryptionError)?; +// hashed_key.hash.unwrap().as_bytes().to_vec() +// } +// // PBKDF2 + AES-GCM +// // 0x03 => { +// // let mut key = [0u8; 32]; +// // pbkdf2::(password.as_bytes(), salt, 10000, &mut key); +// // key.to_vec() +// // } +// _ => return Err(DecryptError::InvalidAlgorithmId), +// }; + +// // Decrypt data using the corresponding cipher +// let mut encrypted_data = Vec::new(); +// data.read_to_end(&mut encrypted_data)?; + +// let plaintext = match id { +// 0x01 => { +// let cipher = Aes256Gcm::new(Key::from_slice(&key)); +// let nonce = Nonce::from_slice(nonce); +// cipher +// .decrypt(nonce, encrypted_data.as_ref()) +// .map_err(|_| DecryptError::DecryptionError)? +// } +// 0x02 => { +// let cipher = ChaCha20Poly1305::new(ChaChaKey::from_slice(&key)); +// let nonce = ChaChaNonce::from_slice(nonce); +// cipher +// .decrypt(nonce, encrypted_data.as_ref()) +// .map_err(|_| DecryptError::DecryptionError)? +// } +// 0x03 => { + +// let cipher = Aes256Gcm::new(Key::from_slice(&key)); +// let nonce = Nonce::from_slice(nonce); +// cipher +// .decrypt(nonce, encrypted_data.as_ref()) +// .map_err(|_| DecryptError::DecryptionError)? +// } +// _ => return Err(DecryptError::InvalidAlgorithmId), +// }; + +// Ok(plaintext) +// } + #[cfg(any(test, feature = "crypto"))] #[inline] fn decryp(stream: T, nonce: &[u8], data: &[u8]) -> Result, crate::Error> { diff --git a/ecstore/Cargo.toml b/ecstore/Cargo.toml index 0f9431fc..455b5d96 100644 --- a/ecstore/Cargo.toml +++ b/ecstore/Cargo.toml @@ -58,7 +58,7 @@ tokio-stream = { workspace = true } tonic.workspace = true tower.workspace = true byteorder = "1.5.0" -xxhash-rust = { version = "0.8.15", features = ["xxh64"] } +xxhash-rust = { version = "0.8.15", features = ["xxh64","xxh3"] } num = "0.4.3" num_cpus = { workspace = true } s3s-policy.workspace = true @@ -67,7 +67,14 @@ pin-project-lite.workspace = true md-5.workspace = true madmin.workspace = true workers.workspace = true -reqwest = { workspace = true } +reqwest = "0.12.12" +aws-sdk-s3 = "1.29.0" +#log.workspace = true +once_cell = "1.20.3" +aws-smithy-types = "1.2.13" +rustfs-rsc = "2025.220.3" +hyper.workspace = true +#reqwest = { workspace = true } urlencoding = "2.1.3" smallvec = { workspace = true } shadow-rs.workspace = true diff --git a/ecstore/src/bucket/metadata.rs b/ecstore/src/bucket/metadata.rs index 8ab53b19..f7d628fd 100644 --- a/ecstore/src/bucket/metadata.rs +++ b/ecstore/src/bucket/metadata.rs @@ -16,6 +16,7 @@ use std::sync::Arc; use time::OffsetDateTime; use tracing::error; +use crate::bucket::target::BucketTarget; use crate::config::com::{read_config, save_config}; use crate::{config, new_object_layer_fn}; use common::error::{Error, Result}; @@ -278,8 +279,11 @@ impl BucketMetadata { self.replication_config_updated_at = updated; } BUCKET_TARGETS_FILE => { - self.tagging_config_xml = data; - self.tagging_config_updated_at = updated; + // let x = data.clone(); + // let str = std::str::from_utf8(&x).expect("Invalid UTF-8"); + // println!("update config:{}", str); + self.bucket_targets_config_json = data.clone(); + self.bucket_targets_config_updated_at = updated; } _ => return Err(Error::msg(format!("config file not found : {}", config_file))), } @@ -340,8 +344,10 @@ impl BucketMetadata { if !self.replication_config_xml.is_empty() { self.replication_config = Some(deserialize::(&self.replication_config_xml)?); } + //let temp = self.bucket_targets_config_json.clone(); if !self.bucket_targets_config_json.is_empty() { - self.bucket_target_config = Some(BucketTargets::unmarshal(&self.bucket_targets_config_json)?); + let arr:Vec = serde_json::from_slice(&self.bucket_targets_config_json)?; + self.bucket_target_config = Some(BucketTargets { targets: arr }); } else { self.bucket_target_config = Some(BucketTargets::default()) } diff --git a/ecstore/src/bucket/metadata_sys.rs b/ecstore/src/bucket/metadata_sys.rs index 73a1ff57..9024ea2f 100644 --- a/ecstore/src/bucket/metadata_sys.rs +++ b/ecstore/src/bucket/metadata_sys.rs @@ -6,6 +6,7 @@ use std::{collections::HashMap, sync::Arc}; use crate::bucket::error::BucketMetadataError; use crate::bucket::metadata::{load_bucket_metadata_parse, BUCKET_LIFECYCLE_CONFIG}; use crate::bucket::utils::is_meta_bucketname; +use crate::cmd::bucket_targets; use crate::config::error::ConfigError; use crate::disk::error::DiskError; use crate::global::{is_dist_erasure, is_erasure, new_object_layer_fn, GLOBAL_Endpoints}; @@ -228,7 +229,9 @@ impl BucketMetadataSys { match res { Ok(res) => { if let Some(bucket) = buckets.get(idx) { - mp.insert(bucket.clone(), Arc::new(res)); + let x = Arc::new(res); + mp.insert(bucket.clone(), x.clone()); + bucket_targets::init_bucket_targets(bucket, x.clone()).await; } } Err(e) => { @@ -340,6 +343,7 @@ impl BucketMetadataSys { } pub async fn get_config_from_disk(&self, bucket: &str) -> Result { + println!("load data from disk"); if is_meta_bucketname(bucket) { return Err(Error::msg("errInvalidArgument")); } @@ -549,7 +553,12 @@ impl BucketMetadataSys { pub async fn get_replication_config(&self, bucket: &str) -> Result<(ReplicationConfiguration, OffsetDateTime)> { let (bm, reload) = match self.get_config(bucket).await { - Ok(res) => res, + Ok(res) => { + if res.0.replication_config.is_none() { + return Err(Error::new(BucketMetadataError::BucketReplicationConfigNotFound)); + } + res + }, Err(err) => { warn!("get_replication_config err {:?}", &err); return if config::error::is_err_config_not_found(&err) { @@ -564,7 +573,7 @@ impl BucketMetadataSys { if reload { // TODO: globalBucketTargetSys } - + //println!("549 {:?}", config.clone()); Ok((config.clone(), bm.replication_config_updated_at)) } else { Err(Error::new(BucketMetadataError::BucketReplicationConfigNotFound)) @@ -584,9 +593,13 @@ impl BucketMetadataSys { } }; + + println!("573"); + if let Some(config) = &bm.bucket_target_config { if reload { // TODO: globalBucketTargetSys + //config. } Ok(config.clone()) diff --git a/ecstore/src/bucket/mod.rs b/ecstore/src/bucket/mod.rs index 33e5b87e..35cd030a 100644 --- a/ecstore/src/bucket/mod.rs +++ b/ecstore/src/bucket/mod.rs @@ -5,7 +5,8 @@ pub mod object_lock; pub mod policy_sys; mod quota; pub mod tagging; -mod target; +pub mod target; pub mod utils; pub mod versioning; +pub mod replication; pub mod versioning_sys; diff --git a/ecstore/src/bucket/replication/datatypes.rs b/ecstore/src/bucket/replication/datatypes.rs new file mode 100644 index 00000000..f2d78055 --- /dev/null +++ b/ecstore/src/bucket/replication/datatypes.rs @@ -0,0 +1,27 @@ +// Replication status type for x-amz-replication-status header +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum StatusType { + Pending, + Completed, + CompletedLegacy, + Failed, + Replica, +} + +impl StatusType { + // Converts the enum variant to its string representation + pub fn as_str(&self) -> &'static str { + match self { + StatusType::Pending => "PENDING", + StatusType::Completed => "COMPLETED", + StatusType::CompletedLegacy => "COMPLETE", + StatusType::Failed => "FAILED", + StatusType::Replica => "REPLICA", + } + } + + // Checks if the status is empty (not set) + pub fn is_empty(&self) -> bool { + matches!(self, StatusType::Pending) // Adjust this as needed + } +} \ No newline at end of file diff --git a/ecstore/src/bucket/replication/mod.rs b/ecstore/src/bucket/replication/mod.rs new file mode 100644 index 00000000..58fd615b --- /dev/null +++ b/ecstore/src/bucket/replication/mod.rs @@ -0,0 +1 @@ +pub mod datatypes; \ No newline at end of file diff --git a/ecstore/src/bucket/tagging/mod.rs b/ecstore/src/bucket/tagging/mod.rs index f50b85a7..538f8e64 100644 --- a/ecstore/src/bucket/tagging/mod.rs +++ b/ecstore/src/bucket/tagging/mod.rs @@ -25,6 +25,7 @@ pub fn encode_tags(tags: Vec) -> String { for tag in tags.iter() { if let (Some(k), Some(v)) = (tag.key.as_ref(), tag.value.as_ref()) { + //encoded.append_pair(k.as_ref().unwrap().as_str(), v.as_ref().unwrap().as_str()); encoded.append_pair(k.as_str(), v.as_str()); } } diff --git a/ecstore/src/bucket/target/mod.rs b/ecstore/src/bucket/target/mod.rs index d3305517..64e6205f 100644 --- a/ecstore/src/bucket/target/mod.rs +++ b/ecstore/src/bucket/target/mod.rs @@ -1,15 +1,16 @@ use common::error::Result; use rmp_serde::Serializer as rmpSerializer; use serde::{Deserialize, Serialize}; -use std::time::Duration; use time::OffsetDateTime; #[derive(Debug, Deserialize, Serialize, Default, Clone)] pub struct Credentials { - access_key: String, - secret_key: String, - session_token: Option, - expiration: Option, + #[serde(rename = "accessKey")] + pub access_key: String, + #[serde(rename = "secretKey")] + pub secret_key: String, + pub session_token: Option, + pub expiration: Option>, } #[derive(Debug, Deserialize, Serialize, Default, Clone)] @@ -20,52 +21,53 @@ pub enum ServiceType { #[derive(Debug, Deserialize, Serialize, Default, Clone)] pub struct LatencyStat { - curr: Duration, // 当前延迟 - avg: Duration, // 平均延迟 - max: Duration, // 最大延迟 + curr: u64, // 当前延迟 + avg: u64, // 平均延迟 + max: u64, // 最大延迟 } // 定义 BucketTarget 结构体 #[derive(Debug, Deserialize, Serialize, Default, Clone)] pub struct BucketTarget { - source_bucket: String, + #[serde(rename = "sourcebucket")] + pub source_bucket: String, - endpoint: String, + pub endpoint: String, - credentials: Option, - - target_bucket: String, + pub credentials: Option, + #[serde(rename = "targetbucket")] + pub target_bucket: String, secure: bool, - - path: Option, + pub path: Option, api: Option, - arn: Option, + pub arn: Option, + #[serde(rename = "type")] + pub type_: Option, - type_: ServiceType, - - region: Option, + pub region: Option, bandwidth_limit: Option, + #[serde(rename = "replicationSync")] replication_sync: bool, storage_class: Option, - - health_check_duration: Option, - + #[serde(rename = "healthCheckDuration")] + health_check_duration: u64, + #[serde(rename = "disableProxy")] disable_proxy: bool, - reset_before_date: Option, - + #[serde(rename = "resetBeforeDate")] + reset_before_date: String, reset_id: Option, - - total_downtime: Duration, + #[serde(rename = "totalDowntime")] + total_downtime: u64, last_online: Option, - + #[serde(rename = "isOnline")] online: bool, latency: LatencyStat, @@ -73,6 +75,15 @@ pub struct BucketTarget { deployment_id: Option, edge: bool, + #[serde(rename = "edgeSyncBeforeExpiry")] + edge_sync_before_expiry: bool, +} + +impl BucketTarget { + pub fn is_empty(self) -> bool { + //self.target_bucket.is_empty() && self.endpoint.is_empty() && self.arn.is_empty() + self.target_bucket.is_empty() && self.endpoint.is_empty() && self.arn.is_none() + } } #[derive(Debug, Deserialize, Serialize, Default, Clone)] @@ -93,4 +104,18 @@ impl BucketTargets { let t: BucketTargets = rmp_serde::from_slice(buf)?; Ok(t) } + + pub fn is_empty(&self) -> bool { + if self.targets.is_empty() { + return true; + } + + for target in &self.targets { + if !target.clone().is_empty() { + return false; + } + } + + true + } } diff --git a/ecstore/src/cmd/bucket_replication.rs b/ecstore/src/cmd/bucket_replication.rs new file mode 100644 index 00000000..09b5173a --- /dev/null +++ b/ecstore/src/cmd/bucket_replication.rs @@ -0,0 +1,2744 @@ +#![allow(unused_variables)] +#![allow(dead_code)] +use aws_sdk_s3::config::BehaviorVersion; +use aws_sdk_s3::config::Credentials; +use aws_sdk_s3::config::Region; +use aws_sdk_s3::Client as S3Client; +use aws_sdk_s3::Config; +use bytes::Bytes; +use uuid::Uuid; +// use error::Error; +use crate::bucket::metadata_sys::get_replication_config; +use crate::bucket::versioning_sys::BucketVersioningSys; +use crate::new_object_layer_fn; +use crate::peer::RemotePeerS3Client; +use crate::store; +use crate::store_api; +use crate::store_api::ObjectIO; +use crate::store_api::ObjectInfo; +use crate::store_api::ObjectOptions; +use crate::store_api::ObjectToDelete; +use crate::StorageAPI; +use chrono::DateTime; +use chrono::Duration; +use chrono::Utc; +use common::error::Error; +use futures::stream::FuturesUnordered; +use futures::StreamExt; +use http::HeaderMap; +use http::Method; +use lazy_static::lazy_static; +use regex::Regex; +use rustfs_rsc::provider::StaticProvider; +use rustfs_rsc::Minio; +use s3s::dto::DeleteMarkerReplicationStatus; +use s3s::dto::DeleteReplicationStatus; +use s3s::dto::ExistingObjectReplicationStatus; +use s3s::dto::ReplicaModificationsStatus; +use s3s::dto::ReplicationRuleStatus; +use serde::{Deserialize, Serialize}; +use std::any::Any; +use std::collections::HashMap; +use std::collections::HashSet; +use std::fmt; +use std::iter::Iterator; +use std::sync::atomic::AtomicI32; +use std::sync::atomic::Ordering; +use std::sync::Arc; +use std::vec; +use time::OffsetDateTime; +use tokio::sync::Mutex; +use tokio::task; +use tracing::{debug, error, warn, info}; +use xxhash_rust::xxh3::xxh3_64; +// use std::time::SystemTime; +use once_cell::sync::Lazy; +use tokio::sync::mpsc::{Receiver, Sender}; +use tokio::sync::RwLock; +// use bucket_targets::{self, GLOBAL_Bucket_Target_Sys}; + +#[derive(Serialize, Deserialize, Debug)] +struct MRFReplicateEntry { + #[serde(rename = "bucket")] + bucket: String, + + #[serde(rename = "object")] + object: String, + + #[serde(skip_serializing, skip_deserializing)] + version_id: String, + + #[serde(rename = "retryCount")] + retry_count: i32, + + #[serde(skip_serializing, skip_deserializing)] + sz: i64, +} + +trait ReplicationWorkerOperation: Any + Send + Sync { + fn to_mrf_entry(&self) -> MRFReplicateEntry; + fn as_any(&self) -> &dyn Any; +} + +// WorkerMaxLimit max number of workers per node for "fast" mode +pub const WORKER_MAX_LIMIT: usize = 50; + +// WorkerMinLimit min number of workers per node for "slow" mode +pub const WORKER_MIN_LIMIT: usize = 5; + +// WorkerAutoDefault is default number of workers for "auto" mode +pub const WORKER_AUTO_DEFAULT: usize = 10; + +// MRFWorkerMaxLimit max number of mrf workers per node for "fast" mode +pub const MRF_WORKER_MAX_LIMIT: usize = 8; + +// MRFWorkerMinLimit min number of mrf workers per node for "slow" mode +pub const MRF_WORKER_MIN_LIMIT: usize = 2; + +// MRFWorkerAutoDefault is default number of mrf workers for "auto" mode +pub const MRF_WORKER_AUTO_DEFAULT: usize = 4; + +// LargeWorkerCount is default number of workers assigned to large uploads ( >= 128MiB) +pub const LARGE_WORKER_COUNT: usize = 2; + +pub const MIN_LARGE_OBJSIZE: u64 = 128 * 1024 * 1024; + +pub struct ReplicationPool { + // Atomic operations + active_workers: Arc, + active_lrg_workers: Arc, + active_mrf_workers: Arc, + + // Shared objects + obj_layer: Arc, + //ctx: Arc>, // Placeholder for context; replace as needed + priority: String, + max_workers: usize, + max_lworkers: usize, + //stats: Option>, + + // Synchronization primitives + //mu: RwLock<()>, + //mrf_mu: Mutex<()>, + //resyncer: Option>, + + // Workers + workers_sender: Vec>>, + workers_recever: Vec>>, + lrg_workers_sender: Vec>>, + lrg_workers_receiver: Vec>>, + + // MRF + //mrf_worker_kill_ch: Option>, + mrf_replica_ch_sender: Sender>, + mrf_replica_ch_receiver: Receiver>, + //mrf_save_ch: Sender, + //mrf_stop_ch: Sender<()>, + mrf_worker_size: usize, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] +#[repr(u8)] // 明确表示底层值为 u8 +pub enum ReplicationType { + UnsetReplicationType = 0, + ObjectReplicationType = 1, + DeleteReplicationType = 2, + MetadataReplicationType = 3, + HealReplicationType = 4, + ExistingObjectReplicationType = 5, + ResyncReplicationType = 6, + AllReplicationType = 7, +} + +impl Default for ReplicationType { + fn default() -> Self { + ReplicationType::UnsetReplicationType + } +} + +impl ReplicationType { + /// 从 u8 转换为枚举 + pub fn from_u8(value: u8) -> Option { + match value { + 0 => Some(Self::UnsetReplicationType), + 1 => Some(Self::ObjectReplicationType), + 2 => Some(Self::DeleteReplicationType), + 3 => Some(Self::MetadataReplicationType), + 4 => Some(Self::HealReplicationType), + 5 => Some(Self::ExistingObjectReplicationType), + 6 => Some(Self::ResyncReplicationType), + 7 => Some(Self::AllReplicationType), + _ => None, + } + } + + /// 获取枚举对应的 u8 值 + pub fn as_u8(self) -> u8 { + self as u8 + } + + pub fn is_data_replication(self) -> bool { + matches!( + self, + ReplicationType::ObjectReplicationType + | ReplicationType::HealReplicationType + | ReplicationType::ExistingObjectReplicationType + ) + } +} + +const SYSTEM_XML_OBJECT: &str = ".system-d26a9498-cb7c-4a87-a44a-8ae204f5ba6c/system.xml"; +const CAPACITY_XML_OBJECT: &str = ".system-d26a9498-cb7c-4a87-a44a-8ae204f5ba6c/capacity.xml"; +const VEEAM_AGENT_SUBSTR: &str = "APN/1.0 Veeam/1.0"; + +fn is_veeam_sos_api_object(object: &str) -> bool { + match object { + SYSTEM_XML_OBJECT | CAPACITY_XML_OBJECT => true, + _ => false, + } +} + +pub async fn queue_replication_heal( + bucket: &str, + oi: &ObjectInfo, + rcfg: &s3s::dto::ReplicationConfiguration, + _retry_count: u32, +) -> Option { + if oi.mod_time.is_none() || is_veeam_sos_api_object(&oi.name) { + return None; + } + + if rcfg.rules.is_empty() { + return None; + } + + let mut moi = oi.clone(); + + let mut roi = get_heal_replicate_object_info(&mut moi, rcfg).await; + //roi.retry_count = retry_count; + + if !roi.dsc.replicate_any() { + error!("Replication heal for object {} in bucket {} is not configured", oi.name, bucket); + return None; + } + + if oi.replication_status == ReplicationStatusType::Completed + && !roi.existing_obj_resync.must_resync() + { + return None; + } + + // Handle Delete Marker or VersionPurgeStatus cases + if roi.delete_marker || !roi.version_purge_status.is_empty() { + let (version_id, dm_version_id) = if roi.version_purge_status.is_empty() { + (String::new(), roi.version_id.clone()) + } else { + (roi.version_id.clone(), String::new()) + }; + + let dv = DeletedObjectReplicationInfo { + deleted_object: DeletedObject { + object_name: Some(roi.name.clone()), + delete_marker_version_id: Some(dm_version_id), + version_id: Some(roi.version_id.clone()), + replication_state: roi.replication_state.clone(), + delete_marker_mtime: roi.mod_time, + delete_marker: Some(roi.delete_marker), + }, + bucket: roi.bucket.clone(), + op_type: ReplicationType::HealReplicationType, + //event_type: ReplicationType::HealDeleteType, + event_type: "".to_string(), + reset_id: "".to_string(), + target_arn: "".to_string(), + }; + + if matches!(roi.replication_status, ReplicationStatusType::Pending | ReplicationStatusType::Failed) + || matches!(roi.version_purge_status, VersionPurgeStatusType::Failed | VersionPurgeStatusType::Pending) + { + let mut pool = GLOBAL_REPLICATION_POOL.write().await; + pool.as_mut().unwrap().queue_replica_task(roi).await; + //GLOBAL_REPLICATION_POOL().queue_replica_delete_task(dv); + return None; + } + + if roi.existing_obj_resync.must_resync() + && (roi.replication_status == ReplicationStatusType::Completed || roi.replication_status.is_empty()) + { + //queue_replicate_deletes_wrapper(dv, &roi.existing_obj_resync); + let mut pool = GLOBAL_REPLICATION_POOL.write().await; + pool.as_mut().unwrap().queue_replica_task(roi).await; + return None; + } + + return None; + } + + if roi.existing_obj_resync.must_resync() { + roi.op_type = ReplicationType::ExistingObjectReplicationType as i32; + } + + let mut pool = GLOBAL_REPLICATION_POOL.write().await; + + match roi.replication_status { + ReplicationStatusType::Pending | ReplicationStatusType::Failed => { + //roi.event_type = ReplicateEventType::Heal; + //roi.event_type = ReplicateEventType::Heal; + pool.as_mut().unwrap().queue_replica_task(roi.clone()).await; + return Some(roi); + } + _ => {} + } + + if roi.existing_obj_resync.must_resync() { + //roi.event_type = ReplicateEventType::Existing; + pool.as_mut().unwrap().queue_replica_task(roi.clone()).await; + } + + Some(roi) +} + +fn new_replicate_target_decision(arn: String, replicate: bool, sync: bool) -> ReplicateTargetDecision { + ReplicateTargetDecision { + id: String::new(), // Using a default value for the 'id' field is acceptable + replicate, + synchronous: sync, + arn, + } +} + +pub async fn check_replicate_delete( + bucket: &str, + dobj: &ObjectToDelete, + oi: &ObjectInfo, + del_opts: &ObjectOptions, + gerr: Option<&Error>, +) -> ReplicateDecision { + error!("check_replicate_delete"); + let mut dsc = ReplicateDecision::default(); + + let rcfg = match get_replication_config(bucket).await { + Ok((cfg, mod_time)) => cfg, + Err(e) => { + //repl_log_once_if(ctx, None, bucket); // 你需要实现这个日志函数 + error!("get replication config err:"); + return dsc; + } + }; + + if del_opts.replication_request { + return dsc; + } + + if !del_opts.versioned { + return dsc; + } + + let mut opts = ReplicationObjectOpts { + name: dobj.object_name.clone(), + ssec: false, + user_tags: Some(oi.user_tags.clone()), + delete_marker: oi.delete_marker, + //version_id: dobj.version_id.clone().map(|v| v.to_string()), + version_id: oi + .version_id + .map(|uuid| uuid.to_string()) + .unwrap_or_default(), + op_type: ReplicationType::DeleteReplicationType, + target_arn: None, + replica: true, + existing_object: true, + }; + + let tgt_arns = rcfg.filter_target_arns(&opts); + dsc.targets_map = HashMap::with_capacity(tgt_arns.len()); + + if tgt_arns.is_empty() { + return dsc; + } + + let sync = false; + let mut replicate; + + for tgt_arn in tgt_arns { + //let mut opts = opts.clone(); + opts.target_arn = Some(tgt_arn.clone()); + replicate = rcfg.replicate(&opts); + + if gerr.is_some() { + let valid_repl_status = matches!( + oi.target_replication_status(tgt_arn.clone()), + ReplicationStatusType::Pending | ReplicationStatusType::Completed | ReplicationStatusType::Failed + ); + + if oi.delete_marker && (valid_repl_status || replicate) { + dsc.set(new_replicate_target_decision(tgt_arn.clone(), replicate, sync)); + continue; + } + + if !oi.version_purge_status.is_empty() { + replicate = matches!(oi.version_purge_status, VersionPurgeStatusType::Pending | VersionPurgeStatusType::Failed); + dsc.set(new_replicate_target_decision(tgt_arn.clone(), replicate, sync)); + continue; + } + } + + let tgt = bucket_targets::get_bucket_target_client(bucket, &tgt_arn).await; + + let tgt_dsc = match tgt { + Ok(tgt) => new_replicate_target_decision(tgt_arn.clone(), replicate, tgt.replicate_sync), + Err(_) => new_replicate_target_decision(tgt_arn.clone(), false, false), + }; + + // let tgt_dsc = if let Some(tgt) = tgt { + // new_replicate_target_decision(tgt_arn.clone(), replicate, tgt.replicate_sync) + // } else { + // new_replicate_target_decision(tgt_arn.clone(), false, false) + // }; + + dsc.set(tgt_dsc); + } + + dsc +} +// use crate::replication::*; +// use crate::crypto; +// use crate::global::*; + +fn target_reset_header(arn: &str) -> String { + format!("{}-{}", format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, REPLICATION_RESET), arn) +} + +pub async fn get_heal_replicate_object_info( + oi: &mut ObjectInfo, + rcfg: &s3s::dto::ReplicationConfiguration, +) -> ReplicateObjectInfo { + let mut user_defined = oi.user_defined.clone(); + + if !rcfg.rules.is_empty() { + if !oi.replication_status.is_empty() { + oi.replication_status_internal = format!("{}={};", rcfg.role, oi.replication_status.as_str()); + } + + if !oi.version_purge_status.is_empty() { + oi.version_purge_status_internal = format!("{}={};", rcfg.role, oi.version_purge_status.to_string()); + } + + // let to_replace: Vec<(String, String)> = user_defined + // .iter() + // .filter(|(k, _)| k.eq_ignore_ascii_case(&(RESERVED_METADATA_PREFIX_LOWER.to_owned() + REPLICATION_RESET))) + // .map(|(k, v)| (k.clone(), v.clone())) + // .collect::>() + // .collect(); + let to_replace: Vec<(String, String)> = match &user_defined { + Some(map) => map + .iter() + .filter(|(k, _)| k.eq_ignore_ascii_case(&(RESERVED_METADATA_PREFIX_LOWER.to_owned() + REPLICATION_RESET))) + .map(|(k, v)| (k.clone(), v.clone())) + .collect(), + None => Vec::new(), + }; + + // 第二步:apply 修改 + for (k, v) in to_replace { + if let Some(mp) = user_defined.as_mut() { + mp.remove(&k); + mp.insert(target_reset_header(&rcfg.role), v); + } + } + } + //} + + //let dsc = if oi.delete_marker || !oi.version_purge_status.is_empty() { + let dsc = if oi.delete_marker { + check_replicate_delete( + &oi.bucket, + &ObjectToDelete { + object_name: oi.name.clone(), + version_id: oi.version_id.clone(), + }, + &oi, + &ObjectOptions { + // versioned: global_bucket_versioning_sys::prefix_enabled(&oi.bucket, &oi.name), + // version_suspended: global_bucket_versioning_sys::prefix_suspended(&oi.bucket, &oi.name), + versioned: true, + version_suspended: false, + ..Default::default() + }, + None, + ).await + } else { + // let opts: ObjectOptions = put_opts(&bucket, &key, version_id, &req.headers, Some(mt)) + // .await + // .map_err(to_s3_error)?; + let mt = oi.user_defined.clone(); + let mt2 = oi.user_defined.clone(); + let opts = ObjectOptions { + user_defined: user_defined.clone(), + versioned: true, + version_id: oi.version_id.map(|uuid| uuid.to_string()), + mod_time: oi.mod_time, + ..Default::default() + }; + let repoptions = + get_must_replicate_options(mt2.as_ref().unwrap_or(&HashMap::new()), "", ReplicationStatusType::Unknown, ReplicationType::ObjectReplicationType, &opts); + + let decision = must_replicate(&oi.bucket, &oi.name, &repoptions).await; + error!("decision:"); + decision + }; + + let tgt_statuses = replication_statuses_map(&oi.replication_status_internal); + let purge_statuses = version_purge_statuses_map(&oi.version_purge_status_internal); + //let existing_obj_resync = rcfg.resync(&GLOBAL_CONTEXT, oi, &dsc, &tgt_statuses); + + // let tm = user_defined + // .get(&(RESERVED_METADATA_PREFIX_LOWER.to_owned() + REPLICATION_TIMESTAMP)) + // .and_then(|v| DateTime::parse_from_rfc3339(v).ok()) + // .map(|dt| dt.with_timezone(&Utc)); + + let tm = user_defined.as_ref().and_then(|map| { + map.get(&(RESERVED_METADATA_PREFIX_LOWER.to_owned() + REPLICATION_TIMESTAMP)) + .and_then(|v| DateTime::parse_from_rfc3339(v).ok()) + .map(|dt| dt.with_timezone(&Utc)) + }); + + let mut rstate = oi.replication_state(); + rstate.replicate_decision_str = dsc.to_string(); + + let asz = oi.get_actual_size().unwrap_or(0); + + let key = format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, REPLICATION_TIMESTAMP); + let tm: Option> = user_defined.as_ref().unwrap().get(&key) + .and_then(|v| DateTime::parse_from_rfc3339(v).ok()) + .map(|dt| dt.with_timezone(&Utc)); + + let mut result = ReplicateObjectInfo { + name: oi.name.clone(), + size: oi.size as i64, + actual_size: asz as i64, + bucket: oi.bucket.clone(), + //version_id: oi.version_id.clone(), + version_id: oi + .version_id + .map(|uuid| uuid.to_string()) // 将 Uuid 转换为 String + .unwrap_or_default(), + etag: oi.etag.clone().unwrap(), + mod_time: convert_offsetdatetime_to_chrono(oi.mod_time).unwrap(), + replication_status: oi.replication_status.clone(), + replication_status_internal: oi.replication_status_internal.clone(), + delete_marker: oi.delete_marker, + version_purge_status_internal: oi.version_purge_status_internal.clone(), + version_purge_status: oi.version_purge_status.clone(), + replication_state: rstate, + op_type: 1, + dsc, + existing_obj_resync: Default::default(), + target_statuses: tgt_statuses, + target_purge_statuses: purge_statuses, + replication_timestamp: tm.unwrap_or_else(|| chrono::Utc::now()), + //ssec: crypto::is_encrypted(&oi.user_defined), + ssec: false, + user_tags: oi.user_tags.clone(), + checksum: oi.checksum.clone(), + event_type: "".to_string(), + retry_count: 0, + reset_id: "".to_string(), + target_arn: "".to_string(), + }; + + if result.ssec { + result.checksum = oi.checksum.clone(); + } + + warn!("Replication heal for object {} in bucket {} is configured {:?}", oi.name, oi.bucket, oi.version_id); + + result +} + +#[derive(Debug, Clone)] +pub struct MustReplicateOptions { + pub meta: HashMap, + pub status: ReplicationStatusType, + pub op_type: ReplicationType, + pub replication_request: bool, // Incoming request is a replication request +} + +impl MustReplicateOptions { + /// Get the replication status from metadata, if available. + pub fn replication_status(&self) -> ReplicationStatusType { + if let Some(rs) = self.meta.get("x-amz-bucket-replication-status") { + return match rs.as_str() { + "Pending" => ReplicationStatusType::Pending, + "Completed" => ReplicationStatusType::Completed, + "CompletedLegacy" => ReplicationStatusType::CompletedLegacy, + "Failed" => ReplicationStatusType::Failed, + "Replica" => ReplicationStatusType::Replica, + _ => ReplicationStatusType::Unknown, + }; + } + self.status.clone() + } + + /// Check if the operation type is existing object replication. + pub fn is_existing_object_replication(&self) -> bool { + self.op_type == ReplicationType::ExistingObjectReplicationType + } + + /// Check if the operation type is metadata replication. + pub fn is_metadata_replication(&self) -> bool { + self.op_type == ReplicationType::MetadataReplicationType + } +} + +use tokio::sync::mpsc; + +use crate::cmd::bucket_targets; + +// use super::bucket_targets::Client; +use super::bucket_targets::TargetClient; +//use crate::storage; + +// 模拟依赖的类型 +pub struct Context; // 用于代替 Go 的 `context.Context` +#[derive(Default)] +pub struct ReplicationStats; + +#[derive(Default)] +pub struct ReplicationPoolOpts { + pub priority: String, + pub max_workers: usize, + pub max_l_workers: usize, +} + +//pub static GLOBAL_REPLICATION_POOL: OnceLock> = OnceLock::new(); + +pub static GLOBAL_REPLICATION_POOL: Lazy>> = Lazy::new(|| { + RwLock::new(None) // 允许延迟初始化 +}); + +impl ReplicationPool { + pub async fn init_bucket_replication_pool( + obj_layer: Arc, + opts: ReplicationPoolOpts, + stats: Arc, + ) { + let mut workers = 0; + let mut failed_workers = 0; + let mut priority = "auto".to_string(); + let mut max_workers = WORKER_MAX_LIMIT; + warn!("init_bucket_replication_pool {} {} {} {}", workers, failed_workers, priority, max_workers); + + let (sender, receiver) = mpsc::channel::>(10); + + // Self { + // mrf_replica_ch_sender: sender, + // } + + if !opts.priority.is_empty() { + priority = opts.priority.clone(); + } + if opts.max_workers > 0 { + max_workers = opts.max_workers; + } + + match priority.as_str() { + "fast" => { + workers = WORKER_MAX_LIMIT; + failed_workers = MRF_WORKER_MAX_LIMIT; + } + "slow" => { + workers = WORKER_MIN_LIMIT; + failed_workers = MRF_WORKER_MIN_LIMIT; + } + _ => { + workers = WORKER_AUTO_DEFAULT; + failed_workers = MRF_WORKER_AUTO_DEFAULT; + } + } + + if max_workers > 0 && workers > max_workers { + workers = max_workers; + } + if max_workers > 0 && failed_workers > max_workers { + failed_workers = max_workers; + } + + let max_l_workers = if opts.max_l_workers > 0 { + opts.max_l_workers + } else { + LARGE_WORKER_COUNT + }; + + // 初始化通道 + let (mrf_replica_tx, _) = mpsc::channel::(100_000); + let (mrf_worker_kill_tx, _) = mpsc::channel::(failed_workers); + let (mrf_save_tx, _) = mpsc::channel::(100_000); + let (mrf_stop_tx, _) = mpsc::channel::(1); + + let mut pool = Self { + workers_sender: Vec::with_capacity(workers), + workers_recever: Vec::with_capacity(workers), + lrg_workers_sender: Vec::with_capacity(max_l_workers), + lrg_workers_receiver: Vec::with_capacity(max_l_workers), + active_workers: Arc::new(AtomicI32::new(0)), + active_lrg_workers: Arc::new(AtomicI32::new(0)), + active_mrf_workers: Arc::new(AtomicI32::new(0)), + max_lworkers: max_l_workers, + //mrf_worker_kill_ch: None, + mrf_replica_ch_sender: sender, + mrf_replica_ch_receiver: receiver, + mrf_worker_size: workers, + priority, + max_workers, + obj_layer: obj_layer, + }; + + warn!("work size is: {}", workers); + pool.resize_lrg_workers(max_l_workers, Some(0)).await; + pool.resize_workers(workers, Some(0)).await; + pool.resize_failed_workers(failed_workers).await; + let obj_layer_clone = pool.obj_layer.clone(); + + // 启动后台任务 + let resyncer = Arc::new(RwLock::new(ReplicationResyncer::new())); + let x = Arc::new(RwLock::new(&pool)); + // tokio::spawn(async move { + // resyncer.lock().await.persist_to_disk(ctx_clone, obj_layer_clone).await; + // }); + + tokio::spawn(async move { + //pool4.process_mrf().await + }); + let pool5 = Arc::clone(&x); + tokio::spawn(async move { + //pool5.persist_mrf().await + }); + + let mut global_pool = GLOBAL_REPLICATION_POOL.write().await; + global_pool.replace(pool); + } + + pub async fn resize_lrg_workers(&mut self, n: usize, check_old: Option) { + //let mut lrg_workers = self.lrg_workers.lock().unwrap(); + if (check_old.is_some() && self.lrg_workers_sender.len() != check_old.unwrap()) + || n == self.lrg_workers_sender.len() + || n < 1 + { + // Either already satisfied or worker count changed while waiting for the lock. + return; + } + println!("2 resize_lrg_workers"); + + let active_workers = Arc::clone(&self.active_lrg_workers); + let obj_layer = Arc::clone(&self.obj_layer); + let mut lrg_workers_sender = std::mem::take(&mut self.lrg_workers_sender); + + while lrg_workers_sender.len() < n { + let (sender, mut receiver) = mpsc::channel::>(100); + lrg_workers_sender.push(sender); + + let active_workers_clone = Arc::clone(&active_workers); + let obj_layer_clone = Arc::clone(&obj_layer); + + tokio::spawn(async move { + while let Some(operation) = receiver.recv().await { + println!("resize workers 1"); + active_workers_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + + if let Some(info) = operation.as_any().downcast_ref::() { + replicate_object(info.clone(), obj_layer_clone.clone()).await; + } else if let Some(info) = operation.as_any().downcast_ref::() { + replicate_delete(&info.clone(), obj_layer_clone.clone()).await; + } else { + eprintln!("Unknown replication type"); + } + + active_workers_clone.fetch_sub(1, std::sync::atomic::Ordering::SeqCst); + } + }); + } + + // Add new workers if needed + // Remove excess workers if needed + while lrg_workers_sender.len() > n { + lrg_workers_sender.pop(); // Dropping the sender will close the channel + } + + self.lrg_workers_sender = lrg_workers_sender; + } + + pub async fn resize_workers(&mut self, n: usize, check_old: Option) { + debug!("resize worker"); + //let mut lrg_workers = self.lrg_workers.lock().unwrap(); + if (check_old.is_some() && self.workers_sender.len() != check_old.unwrap()) || n == self.workers_sender.len() || n < 1 { + // Either already satisfied or worker count changed while waiting for the lock. + return; + } + debug!("resize worker"); + // Add new workers if needed + let active_workers_clone = Arc::clone(&self.active_workers); + let mut vsender = std::mem::take(&mut self.workers_sender); + //let mut works_sender = std::mem::take(&mut self.workers_sender); + let layer = Arc::clone(&self.obj_layer); + while vsender.len() < n { + debug!("resize workers"); + let (sender, mut receiver) = mpsc::channel::>(100); + vsender.push(sender); + + let active_workers_clone = Arc::clone(&active_workers_clone); + // Spawn a new workero + let layer_clone = Arc::clone(&layer); + tokio::spawn(async move { + while let Some(operation) = receiver.recv().await { + // Simulate work being processed + active_workers_clone.fetch_add(1, std::sync::atomic::Ordering::SeqCst); + + if let Some(info) = operation.as_any().downcast_ref::() { + //self.stats.inc_q(&info.bucket, info.size, info.delete_marker, &info.op_type); + let _layer = Arc::clone(&layer_clone); + replicate_object(info.clone(), _layer).await; + //self.stats.dec_q(&info.bucket, info.size, info.delete_marker, &info.op_type); + } else if let Some(info) = operation.as_any().downcast_ref::() { + let _layer = Arc::clone(&layer_clone); + replicate_delete(&info.clone(), _layer).await; + } else { + eprintln!("Unknown replication type"); + } + + active_workers_clone.fetch_sub(1, std::sync::atomic::Ordering::SeqCst); + } + }); + } + // Remove excess workers if needed + while vsender.len() > n { + vsender.pop(); // Dropping the sender will close the channel + } + self.workers_sender = vsender; + warn!("self sender size is {:?}", self.workers_sender.len()); + warn!("self sender size is {:?}", self.workers_sender.len()); + } + + async fn resize_failed_workers(&self, _count: usize) { + // 实现失败 worker 的初始化逻辑 + } + + // async fn process_mrf(&self) { + // // 实现 MRF 处理逻辑 + // } + + // async fn persist_mrf(&self) { + // // 实现 MRF 持久化逻辑 + // } + + fn get_worker_ch(&self, bucket: &str, object: &str, _sz: i64) -> Option<&Sender>> { + let h = xxh3_64(format!("{}{}", bucket, object).as_bytes()); // 计算哈希值 + //need lock; + let workers = &self.workers_sender; // 读锁 + + if workers.is_empty() { + warn!("workers is empty"); + return None; + } + + let index = (h as usize) % workers.len(); // 选择 worker + Some(&workers[index]) // 返回对应的 Sender + } + + async fn queue_replica_task(&mut self, ri: ReplicateObjectInfo) { + if ri.size >= MIN_LARGE_OBJSIZE as i64 { + let h = xxh3_64(format!("{}{}", ri.bucket, ri.name).as_bytes()); + let workers = &self.lrg_workers_sender; + let worker_count = workers.len(); + + if worker_count > 0 { + let worker_index = (h as usize) % worker_count; + let sender = &workers[worker_index]; + + match sender.try_send(Box::new(ri.clone())) { + Ok(_) => return, + Err(_) => { + // 任务队列满了,执行 MRF 处理 + //println!("Queue full, saving to MRF: {}", ri.to_mrf_entry()); + println!("Queue full, saving to MRF"); + } + } + } + + // 检查是否需要增加 worker + let existing = worker_count; + let max_workers = self.max_lworkers.min(LARGE_WORKER_COUNT); + + if self.active_lrg_workers.load(Ordering::SeqCst) < max_workers as i32 { + let new_worker_count = (existing + 1).min(max_workers); + self.resize_lrg_workers(new_worker_count, Some(existing)).await; + } + return; + } + let mut ch: Option<&Sender>> = None; + let mut heal_ch: Option<&Sender>> = None; + warn!("enqueue object:{}", ch.is_none()); + + if ri.op_type == ReplicationType::HealReplicationType as i32 + || ri.op_type == ReplicationType::ExistingObjectReplicationType as i32 + { + ch = Some(&self.mrf_replica_ch_sender); + heal_ch = self.get_worker_ch(&ri.name, &ri.bucket, ri.size); + } else { + info!("get worker channel for replication"); + ch = self.get_worker_ch(&ri.name, &ri.bucket, ri.size); + } + + if ch.is_none() && heal_ch.is_none() { + error!("replicste chan empty"); + return; + } + + let mut sent = false; + tokio::select! { + //_ = self.ctx_done.closed() => {}, + Some(h) = async { heal_ch } => { + //if let Some(h) = h { + if h.send(Box::new(ri.clone())).await.is_ok() { + warn!("enqueue object"); + sent = true; + } + //} + } + Some(c) = async { ch } => { + //if let Some(c) = c { + if c.send(Box::new(ri.clone())).await.is_ok() { + info!("enqueue object"); + sent = true; + } + //} + } + } + + if !sent { + //todo! + //self.queue_mrf_save(ri).await; + let max_workers = self.max_workers; + + match self.priority.as_str() { + "fast" => { + println!("Warning: Unable to keep up with incoming traffic"); + } + "slow" => { + println!("Warning: Incoming traffic is too high. Increase replication priority."); + } + _ => { + let worker_count = self.active_workers.load(Ordering::SeqCst); + let max_workers = max_workers.min(WORKER_MAX_LIMIT); + if worker_count < max_workers as i32 { + //self.resize_workers((worker_count + 1 as usize).try_into().unwrap(), worker_count).await; + self.resize_workers(worker_count as usize + 1 as usize, Some(worker_count as usize)) + .await; + } + + //let max_mrf_workers = max_workers.min(MRFWorkerMaxLimit); + let max_mrf_workers = max_workers.min(MRF_WORKER_MAX_LIMIT); + if self.mrf_worker_size < max_mrf_workers { + self.resize_failed_workers(self.mrf_worker_size + 1).await; + } + } + } + } + } +} + +pub struct ReplicationResyncer; + +impl ReplicationResyncer { + pub fn new() -> Self { + Self + } + + pub async fn persist_to_disk(&self, _ctx: Arc, _obj_layer: Arc) { + // 实现持久化到磁盘的逻辑 + } +} + +pub async fn init_bucket_replication_pool() { + if let Some(store) = new_object_layer_fn() { + let opts = ReplicationPoolOpts::default(); + let stats = ReplicationStats::default(); + let stat = Arc::new(stats); + warn!("init bucket replication pool"); + ReplicationPool::init_bucket_replication_pool(store, opts, stat).await; + } else { + } +} + +pub struct ReplicationClient { + pub s3cli: S3Client, + pub remote_peer_client: RemotePeerS3Client, + pub arn: String, +} + +pub trait RemotePeerS3ClientExt { + fn putobject(remote_bucket: String, remote_object: String, size: i64); + fn multipart(); +} + +impl RemotePeerS3ClientExt for RemotePeerS3Client { + fn putobject(remote_bucket: String, remote_object: String, size: i64) {} + + fn multipart() {} +} + +#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum ReplicationStatusType { + #[default] + Pending, + Completed, + CompletedLegacy, + Failed, + Replica, + Unknown, +} + +impl ReplicationStatusType { + // Converts the enum variant to its string representation + pub fn as_str(&self) -> &'static str { + match self { + ReplicationStatusType::Pending => "PENDING", + ReplicationStatusType::Completed => "COMPLETED", + ReplicationStatusType::CompletedLegacy => "COMPLETE", + ReplicationStatusType::Failed => "FAILED", + ReplicationStatusType::Replica => "REPLICA", + ReplicationStatusType::Unknown => "", + } + } + + // Checks if the status is empty (not set) + pub fn is_empty(&self) -> bool { + matches!(self, ReplicationStatusType::Pending) // Adjust logic if needed + } + + // 从字符串构造 ReplicationStatusType 枚举 + pub fn from(value: &str) -> Self { + match value.to_uppercase().as_str() { + "PENDING" => ReplicationStatusType::Pending, + "COMPLETED" => ReplicationStatusType::Completed, + "COMPLETE" => ReplicationStatusType::CompletedLegacy, + "FAILED" => ReplicationStatusType::Failed, + "REPLICA" => ReplicationStatusType::Replica, + other => ReplicationStatusType::Unknown, + } + } +} + +#[derive(Default, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum VersionPurgeStatusType { + Pending, + Complete, + Failed, + Empty, + #[default] + Unknown, +} + +impl VersionPurgeStatusType { + // 检查是否是 Empty + pub fn is_empty(&self) -> bool { + matches!(self, VersionPurgeStatusType::Empty) + } + + // 检查是否是 Pending(Pending 或 Failed 都算作 Pending 状态) + pub fn is_pending(&self) -> bool { + matches!(self, VersionPurgeStatusType::Pending | VersionPurgeStatusType::Failed) + } +} + +// 从字符串实现转换(类似于 Go 的字符串比较) +impl From<&str> for VersionPurgeStatusType { + fn from(value: &str) -> Self { + match value.to_uppercase().as_str() { + "PENDING" => VersionPurgeStatusType::Pending, + "COMPLETE" => VersionPurgeStatusType::Complete, + "FAILED" => VersionPurgeStatusType::Failed, + _ => VersionPurgeStatusType::Empty, + } + } +} + +// 将枚举转换为字符串 +impl ToString for VersionPurgeStatusType { + fn to_string(&self) -> String { + match self { + VersionPurgeStatusType::Pending => "PENDING".to_string(), + VersionPurgeStatusType::Complete => "COMPLETE".to_string(), + VersionPurgeStatusType::Failed => "FAILED".to_string(), + VersionPurgeStatusType::Empty => "".to_string(), + VersionPurgeStatusType::Unknown => "".to_string(), + } + } +} + +pub fn get_composite_version_purge_status(status_map: &HashMap) -> VersionPurgeStatusType { + if status_map.is_empty() { + return VersionPurgeStatusType::Unknown; + } + + let mut completed_count = 0; + + for status in status_map.values() { + match status { + VersionPurgeStatusType::Failed => return VersionPurgeStatusType::Failed, + VersionPurgeStatusType::Complete => completed_count += 1, + _ => {} + } + } + + if completed_count == status_map.len() { + VersionPurgeStatusType::Complete + } else { + VersionPurgeStatusType::Pending + } +} + +// 定义 ReplicationAction 枚举 +#[derive(Debug, Default, PartialEq, Eq, Clone, Serialize, Deserialize)] +pub enum ReplicationAction { + ReplicateMetadata, + #[default] + ReplicateNone, + ReplicateAll, +} + +impl ReplicationAction { + // 工厂方法,根据字符串生成对应的枚举 + pub fn from_str(action: &str) -> Self { + match action.to_lowercase().as_str() { + "metadata" => ReplicationAction::ReplicateMetadata, + "none" => ReplicationAction::ReplicateNone, + "all" => ReplicationAction::ReplicateAll, + _ => ReplicationAction::ReplicateNone, + } + } +} + +// 定义 ObjectInfo 结构体 +// #[derive(Debug)] +// pub struct ObjectInfo { +// pub e_tag: String, +// pub version_id: String, +// pub actual_size: i64, +// pub mod_time: DateTime, +// pub delete_marker: bool, +// pub content_type: String, +// pub content_encoding: String, +// pub user_tags: HashMap, +// pub user_defined: HashMap, +// } + +// impl ObjectInfo { +// // 获取实际大小 +// pub fn get_actual_size(&self) -> i64 { +// self.actual_size +// } +// } + +// 定义 MinioObjectInfo 结构体 +#[derive(Debug)] +pub struct MinioObjectInfo { + pub e_tag: String, + pub version_id: String, + pub size: i64, + pub last_modified: DateTime, + pub is_delete_marker: bool, + pub content_type: String, + pub metadata: HashMap>, + pub user_tag_count: usize, + pub user_tags: HashMap, +} + +// 忽略大小写比较字符串列表 +// fn equals(k1: &str, keys: &[&str]) -> bool { +// keys.iter().any(|&k2| k1.eq_ignore_ascii_case(k2)) +// } + +// 比较两个对象的 ReplicationAction +pub fn get_replication_action(oi1: &ObjectInfo, oi2: &ObjectInfo, op_type: &str) -> ReplicationAction { + let _null_version_id = "null"; + + // 如果是现有对象复制,判断是否需要跳过同步 + if op_type == "existing" && oi1.mod_time > oi2.mod_time && oi1.version_id == None { + return ReplicationAction::ReplicateNone; + } + + let sz = oi1.get_actual_size(); + + // 完整复制的条件 + if oi1.etag != oi2.etag + || oi1.version_id != oi2.version_id + || sz.unwrap() != oi2.size + || oi1.delete_marker != oi2.delete_marker + || oi1.mod_time != oi2.mod_time + { + return ReplicationAction::ReplicateAll; + } + + // 元数据复制的条件 + if oi1.content_type != oi2.content_type { + return ReplicationAction::ReplicateMetadata; + } + + // if oi1.content_encoding.is_some() { + // if let Some(enc) = oi2 + // .metadata + // .get("content-encoding") + // .or_else(|| oi2.metadata.get("content-encoding".to_lowercase().as_str())) + // { + // if enc.join(",") != oi1.content_encoding { + // return ReplicationAction::ReplicateMetadata; + // } + // } else { + // return ReplicationAction::ReplicateMetadata; + // } + // } + + // if !oi2.user_tags.is_empty() && oi1.user_tags != oi2.user_tags { + // return ReplicationAction::ReplicateMetadata; + // } + + // 需要比较的头部前缀列表 + // let compare_keys = vec![ + // "expires", + // "cache-control", + // "content-language", + // "content-disposition", + // "x-amz-object-lock-mode", + // "x-amz-object-lock-retain-until-date", + // "x-amz-object-lock-legal-hold", + // "x-amz-website-redirect-location", + // "x-amz-meta-", + // ]; + + // 提取并比较必要的元数据 + // let compare_meta1: HashMap = oi1 + // .user_defined + // .iter() + // .filter(|(k, _)| compare_keys.iter().any(|prefix| k.to_lowercase().starts_with(prefix))) + // .map(|(k, v)| (k.to_lowercase(), v.clone())) + // .collect(); + + // let compare_meta2: HashMap = oi2 + // .metadata + // .iter() + // .filter(|(k, _)| compare_keys.iter().any(|prefix| k.to_lowercase().starts_with(prefix))) + // .map(|(k, v)| (k.to_lowercase(), v.join(","))) + // .collect(); + + // if compare_meta1 != compare_meta2 { + // return ReplicationAction::ReplicateMetadata; + // } + + ReplicationAction::ReplicateNone +} + +/// 目标的复制决策结构 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ReplicateTargetDecision { + pub replicate: bool, // 是否进行复制 + pub synchronous: bool, // 是否是同步复制 + pub arn: String, // 复制目标的 ARN + pub id: String, // ID +} + +impl ReplicateTargetDecision { + /// 将结构体转换为字符串 + pub fn to_string(&self) -> String { + format!("{};{};{};{}", self.replicate, self.synchronous, self.arn, self.id) + } + + /// 创建一个新的 ReplicateTargetDecision 实例 + pub fn new(arn: &str, replicate: bool, synchronous: bool) -> Self { + Self { + replicate, + synchronous, + arn: arn.to_string(), + id: String::new(), + } + } +} + +/// 复制决策结构体,包含多个目标的决策 +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct ReplicateDecision { + targets_map: HashMap, +} + +impl ReplicateDecision { + /// 创建一个新的空的 ReplicateDecision + pub fn new() -> Self { + Self { + targets_map: HashMap::new(), + } + } + + /// 检查是否有任何目标需要复制 + pub fn replicate_any(&self) -> bool { + self.targets_map.values().any(|t| t.replicate) + } + + /// 检查是否有任何目标需要同步复制 + pub fn synchronous(&self) -> bool { + self.targets_map.values().any(|t| t.synchronous) + } + + /// 将目标的决策添加到 map 中 + pub fn set(&mut self, decision: ReplicateTargetDecision) { + self.targets_map.insert(decision.arn.clone(), decision); + } + + /// 返回所有目标的 Pending 状态字符串 + pub fn pending_status(&self) -> String { + let mut result = String::new(); + for target in self.targets_map.values() { + if target.replicate { + result.push_str(&format!("{}=PENDING;", target.arn)); + } + } + result + } +} + +impl fmt::Display for ReplicateDecision { + /// 将 ReplicateDecision 转换为字符串格式 + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut entries = Vec::new(); + for (key, value) in &self.targets_map { + entries.push(format!("{}={}", key, value.to_string())); + } + write!(f, "{}", entries.join(",")) + } +} + +/// ResyncTargetDecision 表示重同步决策 +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ResyncTargetDecision { + pub replicate: bool, + pub reset_id: String, + pub reset_before_date: DateTime, +} + +/// ResyncDecision 表示所有目标的重同步决策 +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct ResyncDecision { + targets: HashMap, +} + +impl ResyncDecision { + /// 创建一个新的 ResyncDecision + pub fn new() -> Self { + Self { targets: HashMap::new() } + } + + /// 检查是否没有任何目标需要重同步 + pub fn is_empty(&self) -> bool { + self.targets.is_empty() + } + + /// 检查是否有至少一个目标需要重同步 + pub fn must_resync(&self) -> bool { + self.targets.values().any(|v| v.replicate) + } + + /// 检查指定目标是否需要重同步 + pub fn must_resync_target(&self, tgt_arn: &str) -> bool { + if let Some(target) = self.targets.get(tgt_arn) { + target.replicate + } else { + false + } + } +} + +/// 解析字符串为 ReplicateDecision 结构 +pub fn parse_replicate_decision(input: &str) -> Result { + let mut decision = ReplicateDecision::new(); + if input.is_empty() { + return Ok(decision); + } + + for pair in input.split(',') { + if pair.is_empty() { + continue; + } + let parts: Vec<&str> = pair.split('=').collect(); + if parts.len() != 2 { + return Err("Invalid replicate decision format"); + } + + let key = parts[0]; + let value = parts[1].trim_matches('"'); + let values: Vec<&str> = value.split(';').collect(); + + if values.len() != 4 { + return Err("Invalid replicate target decision format"); + } + + let replicate = values[0] == "true"; + let synchronous = values[1] == "true"; + let arn = values[2].to_string(); + let id = values[3].to_string(); + + decision.set(ReplicateTargetDecision { + replicate, + synchronous, + arn, + id, + }); + } + Ok(decision) +} + +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct ReplicatedTargetInfo { + pub arn: String, + pub size: i64, + pub duration: Duration, + pub replication_action: ReplicationAction, // 完整或仅元数据 + pub op_type: i32, // 传输类型 + pub replication_status: ReplicationStatusType, // 当前复制状态 + pub prev_replication_status: ReplicationStatusType, // 上一个复制状态 + pub version_purge_status: VersionPurgeStatusType, // 版本清理状态 + pub resync_timestamp: String, // 重同步时间戳 + pub replication_resynced: bool, // 是否重同步 + pub endpoint: String, // 目标端点 + pub secure: bool, // 是否安全连接 + pub err: Option, // 错误信息 +} + +// 实现 ReplicatedTargetInfo 方法 +impl ReplicatedTargetInfo { + /// 检查 arn 是否为空 + pub fn is_empty(&self) -> bool { + self.arn.is_empty() + } +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct DeletedObjectReplicationInfo { + #[serde(flatten)] // 使用 `flatten` 将 `DeletedObject` 的字段展开到当前结构体 + pub deleted_object: DeletedObject, + + pub bucket: String, + pub event_type: String, + pub op_type: ReplicationType, // 假设 `replication.Type` 是 `ReplicationType` 枚举 + pub reset_id: String, + pub target_arn: String, +} + +pub fn get_composite_replication_status(m: &HashMap) -> ReplicationStatusType { + if m.is_empty() { + return ReplicationStatusType::Unknown; + } + + let mut completed_count = 0; + + for status in m.values() { + match status { + ReplicationStatusType::Failed => return ReplicationStatusType::Failed, + ReplicationStatusType::Completed => completed_count += 1, + _ => {} + } + } + + if completed_count == m.len() { + return ReplicationStatusType::Completed; + } + + ReplicationStatusType::Pending +} + +#[derive(Debug, Default, Clone, Serialize, Deserialize)] +pub struct ReplicationState { + pub replica_timestamp: DateTime, + pub replica_status: ReplicationStatusType, + pub delete_marker: bool, + pub replication_timestamp: DateTime, + pub replication_status_internal: String, + pub version_purge_status_internal: String, + pub replicate_decision_str: String, + pub targets: HashMap, + pub purge_targets: HashMap, + pub reset_statuses_map: HashMap, +} + +// impl Default for ReplicationState { +// fn default() -> Self { +// ReplicationState { +// replica_timestamp: Utc::now(), +// replica_status: ReplicationStatusType::default(), +// delete_marker: false, +// replication_timestamp: Utc::now(), +// replication_status_internal: String::new(), +// version_purge_status_internal: String::new(), +// replicate_decision_str: String::new(), +// targets: HashMap::new(), +// purge_targets: HashMap::new(), +// reset_statuses_map: HashMap::new(), +// } +// } +// } + +pub struct ReplicationObjectOpts { + pub name: String, + pub user_tags: Option, + pub version_id: String, + pub delete_marker: bool, + pub ssec: bool, + pub op_type: ReplicationType, + pub replica: bool, + pub existing_object: bool, + pub target_arn: Option, +} + +pub trait ConfigProcess { + fn filter_actionable_rules(&self, obj: &ReplicationObjectOpts) -> Vec; + + fn replicate(&self, obj: &ReplicationObjectOpts) -> bool; + fn filter_target_arns(&self, obj: &ReplicationObjectOpts) -> Vec; +} + +impl ConfigProcess for s3s::dto::ReplicationConfiguration { + fn filter_target_arns(&self, obj: &ReplicationObjectOpts) -> Vec { + let mut arns = Vec::new(); + let mut tgts_map = HashSet::new(); + + let rules = self.filter_actionable_rules(obj); + debug!("rule len is {}", rules.len()); + for rule in rules { + debug!("rule"); + + if rule.status == ReplicationRuleStatus::from_static(ReplicationRuleStatus::DISABLED) { + debug!("rule"); + continue; + } + + if self.role != "" { + debug!("rule"); + arns.push(self.role.clone()); // use legacy RoleArn if present + return arns; + } + + debug!("rule"); + if !tgts_map.contains(&rule.destination.bucket) { + tgts_map.insert(rule.destination.bucket.clone()); + } + } + + for arn in tgts_map { + arns.push(arn); + } + arns + } + + fn replicate(&self, obj: &ReplicationObjectOpts) -> bool { + for rule in self.filter_actionable_rules(obj) { + if rule.status == ReplicationRuleStatus::from_static(ReplicationRuleStatus::DISABLED) { + warn!("need replicate failed"); + continue; + } + if obj.existing_object + && rule.existing_object_replication.is_some() + && rule.existing_object_replication.unwrap().status + == ExistingObjectReplicationStatus::from_static(ExistingObjectReplicationStatus::DISABLED) + { + warn!("need replicate failed"); + return false; + } + + if obj.op_type == ReplicationType::DeleteReplicationType { + return if !obj.version_id.is_empty() { + // MinIO 扩展:检查版本化删除 + if rule.delete_replication.is_none() { + warn!("need replicate failed"); + return false; + } + rule.delete_replication.unwrap().status + == DeleteReplicationStatus::from_static(DeleteReplicationStatus::DISABLED) + } else { + if rule.delete_marker_replication.is_none() { + warn!("need replicate failed"); + return false; + } + if rule.delete_marker_replication.as_ref().unwrap().status.clone().is_none() { + warn!("need replicate failed"); + return false; + } + rule.delete_marker_replication.as_ref().unwrap().status.clone().unwrap() + == DeleteMarkerReplicationStatus::from_static(DeleteMarkerReplicationStatus::DISABLED) + }; + } + // 处理常规对象/元数据复制 + if !obj.replica { + warn!("not need replicate {} {} ", obj.name, obj.version_id); + return true; + } + return obj.replica + && rule.source_selection_criteria.is_some() + && rule.source_selection_criteria.unwrap().replica_modifications.unwrap().status + == ReplicaModificationsStatus::from_static(ReplicaModificationsStatus::ENABLED); + } + warn!("need replicate failed"); + false + } + + fn filter_actionable_rules(&self, obj: &ReplicationObjectOpts) -> Vec { + if obj.name.is_empty() + && !matches!(obj.op_type, ReplicationType::ResyncReplicationType | ReplicationType::AllReplicationType) + { + warn!("filter"); + return vec![]; + } + + let mut rules: Vec = Vec::new(); + debug!("rule size is {}", &self.rules.len()); + + for rule in &self.rules { + if rule.status.as_str() == s3s::dto::ReplicationRuleStatus::DISABLED { + debug!("rule size is"); + continue; + } + + if obj.target_arn.is_some() + && rule.destination.bucket != obj.target_arn.clone().unwrap() + && self.role != obj.target_arn.clone().unwrap() + { + debug!("rule size is"); + continue; + } + debug!("match {:?}", obj.op_type.clone()); + if matches!(obj.op_type, ReplicationType::ResyncReplicationType | ReplicationType::AllReplicationType) { + //println!("filter"); + rules.push(rule.clone()); + continue; + } + + if obj.existing_object { + if rule.existing_object_replication.is_none() { + continue; + } + + if rule.existing_object_replication.clone().unwrap().status.as_str() == ExistingObjectReplicationStatus::DISABLED + { + continue; + } + } + + if rule.prefix.is_some() && !obj.name.starts_with(rule.prefix.as_ref().unwrap()) { + continue; + } + + //if rule.filter.test_tags(&obj.user_tags) { + rules.push(rule.clone()); + //} + } + + rules.sort_by(|a, b| { + if a.priority == b.priority { + a.destination.bucket.to_string().cmp(&b.destination.bucket.to_string()) + } else { + b.priority.cmp(&a.priority) + } + }); + + rules + } +} + +fn replication_statuses_map(s: &str) -> HashMap { + let mut targets = HashMap::new(); + let repl_status_regex = Regex::new(r"(\w+):([\w-]+)").unwrap(); + + for cap in repl_status_regex.captures_iter(s) { + if let (Some(target), Some(status)) = (cap.get(1), cap.get(2)) { + let tp = ReplicationStatusType::from(status.as_str()); + targets.insert(target.as_str().to_string(), tp); + } + } + + targets +} + +fn version_purge_statuses_map(s: &str) -> HashMap { + let mut targets = HashMap::new(); + let repl_status_regex = Regex::new(r"(\w+):([\w-]+)").unwrap(); + + for cap in repl_status_regex.captures_iter(s) { + if let (Some(target), Some(status)) = (cap.get(1), cap.get(2)) { + let ptp = VersionPurgeStatusType::from(status.as_str()); + targets.insert(target.as_str().to_string(), ptp); + } + } + + targets +} + +pub trait TraitForObjectInfo { + fn replication_state(&self) -> ReplicationState; +} + +const RESERVED_METADATA_PREFIX: &str = "X-Minio-Internal-"; +const RESERVED_METADATA_PREFIX_LOWER: &str = "x-minio-internal-"; +lazy_static! { + static ref THROTTLE_DEADLINE: std::time::Duration = std::time::Duration::from_secs(3600); +} + +// Replication-related string constants +pub const REPLICATION_RESET: &str = "replication-reset"; +pub const REPLICATION_STATUS: &str = "replication-status"; +pub const REPLICATION_TIMESTAMP: &str = "replication-timestamp"; +pub const REPLICA_STATUS: &str = "replica-status"; +pub const REPLICA_TIMESTAMP: &str = "replica-timestamp"; +pub const TAGGING_TIMESTAMP: &str = "tagging-timestamp"; +pub const OBJECT_LOCK_RETENTION_TIMESTAMP: &str = "objectlock-retention-timestamp"; +pub const OBJECT_LOCK_LEGAL_HOLD_TIMESTAMP: &str = "objectlock-legalhold-timestamp"; +pub const REPLICATION_SSEC_CHECKSUM_HEADER: &str = "X-Minio-Replication-Ssec-Crc"; + +impl TraitForObjectInfo for ObjectInfo { + fn replication_state(&self) -> ReplicationState { + let mut rs = ReplicationState { + replication_status_internal: self.replication_status_internal.clone(), + //version_purge_status_internal: self.version_purge_status_internal.clone(), + version_purge_status_internal: "".to_string(), + replicate_decision_str: self.replication_status_internal.clone(), + targets: HashMap::new(), + purge_targets: HashMap::new(), + reset_statuses_map: HashMap::new(), + replica_timestamp: chrono::Utc::now(), + replica_status: ReplicationStatusType::Pending, + delete_marker: false, + replication_timestamp: chrono::Utc::now(), + }; + + // Set targets and purge_targets using respective functions + rs.targets = replication_statuses_map(&self.replication_status_internal); + //rs.purge_targets = version_purge_statuses_map(&self.version_purge_status_internal); + rs.purge_targets = version_purge_statuses_map(""); + + // Process reset statuses map + if self.user_defined.is_some() { + for (k, v) in self.user_defined.as_ref().unwrap() { + if k.starts_with(&(RESERVED_METADATA_PREFIX_LOWER.to_owned() + REPLICATION_RESET)) { + let arn = k.trim_start_matches(&(RESERVED_METADATA_PREFIX_LOWER.to_owned() + REPLICATION_RESET)); + rs.reset_statuses_map.insert(arn.to_string(), v.clone()); + } + } + } + rs + } +} + +fn convert_offsetdatetime_to_chrono(offset_dt: Option) -> Option> { + //offset_dt.map(|odt| { + let tm = offset_dt.unwrap().unix_timestamp(); + //let naive = NaiveDateTime::from_timestamp_opt(tm, 0).expect("Invalid timestamp"); + DateTime::::from_timestamp(tm, 0) + //DateTime::from_naive_utc_and_offset(naive, Utc) // Convert to Utc first + //}) +} + +pub async fn schedule_replication(oi: ObjectInfo, o: Arc, dsc: ReplicateDecision, op_type: i32) { + let tgt_statuses = replication_statuses_map(&oi.replication_status_internal); + // //let purge_statuses = version_purge_statuses_map(&oi.); + let replication_timestamp = chrono::Utc::now(); // Placeholder for timestamp parsing + let replication_state = oi.replication_state(); + + let actual_size = oi.actual_size.unwrap_or(0); + //let ssec = oi.user_defined.contains_key("ssec"); + let ssec = false; + + let ri = ReplicateObjectInfo { + name: oi.name, + size: oi.size as i64, + bucket: oi.bucket, + version_id: oi + .version_id + .map(|uuid| uuid.to_string()) // 将 Uuid 转换为 String + .unwrap_or_default(), + etag: oi.etag.unwrap_or_default(), + mod_time: convert_offsetdatetime_to_chrono(oi.mod_time).unwrap(), + replication_status: oi.replication_status, + replication_status_internal: oi.replication_status_internal, + delete_marker: oi.delete_marker, + version_purge_status_internal: oi.version_purge_status_internal, + version_purge_status: oi.version_purge_status, + replication_state, + op_type, + dsc: dsc.clone(), + target_statuses: tgt_statuses, + target_purge_statuses: Default::default(), + replication_timestamp, + ssec, + user_tags: oi.user_tags, + checksum: if ssec { oi.checksum.clone() } else { Vec::new() }, + event_type: "".to_string(), + retry_count: 0, + reset_id: "".to_string(), + existing_obj_resync: Default::default(), + target_arn: "".to_string(), + actual_size: 0, + }; + + if dsc.synchronous() { + warn!("object sync replication"); + replicate_object(ri, o).await; + } else { + warn!("object need async replication"); + //GLOBAL_REPLICATION_POOL.lock().unwrap().queue_replica_task(ri); + let mut pool = GLOBAL_REPLICATION_POOL.write().await; + pool.as_mut().unwrap().queue_replica_task(ri).await; + } +} + +pub async fn must_replicate(bucket: &str, object: &str, mopts: &MustReplicateOptions) -> ReplicateDecision { + let mut decision = ReplicateDecision::default(); + + // object layer 未初始化时直接返回 + if new_object_layer_fn().is_none() { + return decision; + } + + // 检查是否允许复制(版本化前缀 + if !BucketVersioningSys::prefix_enabled(bucket, object).await { + return decision; + } + + let repl_status = mopts.replication_status(); + if repl_status == ReplicationStatusType::Replica && !mopts.is_metadata_replication() { + return decision; + } + + if mopts.replication_request { + return decision; + } + + let cfg = match get_replication_config(bucket).await { + Ok((config, timestamp)) => config, + //Ok(None) => return decision, + Err(err) => { + //repl_log_once_if(err, bucket); + return decision; + } + }; + + let mut opts = ReplicationObjectOpts { + name: object.to_string(), + //ssec: crypto::is_ssec_encrypted(&mopts.meta), + ssec: false, + replica: repl_status == ReplicationStatusType::Replica, + existing_object: mopts.is_existing_object_replication(), + user_tags: None, + target_arn: None, + version_id: "0".to_string(), + delete_marker: false, + op_type: mopts.op_type, + }; + + if let Some(tag_str) = mopts.meta.get("x-amz-object-tagging") { + opts.user_tags = Some(tag_str.clone()); + } + + // let rules = cfg.filter_actionable_rules(&opts); + let tgt_arns = cfg.filter_target_arns(&opts); + info!("arn lens:{}", tgt_arns.len()); + for tgt_arn in tgt_arns { + let tgt = bucket_targets::get_bucket_target_client(bucket, &tgt_arn.clone()).await; + //let tgt = GLOBAL_Bucket_Target_Sys.get().unwrap().get_remote_target_client(tgt) + + // 不判断在线状态,因为目标可能暂时不可用 + opts.target_arn = Some(tgt_arn.clone()); + let replicate = cfg.replicate(&opts); + info!("need replicate {}", &replicate); + + let synchronous = tgt.map_or(false, |t| t.replicate_sync); + //decision.set(ReplicateTargetDecision::new(replicate,synchronous)); + info!("targe decision arn is:{}", tgt_arn.clone()); + decision.set(ReplicateTargetDecision { + replicate: replicate, + synchronous: synchronous, + arn: tgt_arn.clone(), + id: 0.to_string(), + }); + } + info!("must replicate"); + decision +} + +impl ReplicationState { + // Equal 方法:判断两个状态是否相等 + pub fn equal(&self, other: &ReplicationState) -> bool { + self.replica_status == other.replica_status + && self.replication_status_internal == other.replication_status_internal + && self.version_purge_status_internal == other.version_purge_status_internal + } + + // CompositeReplicationStatus 方法:返回总体的复制状态 + pub fn composite_replication_status(&self) -> ReplicationStatusType { + if !self.replication_status_internal.is_empty() { + let status = ReplicationStatusType::from(self.replication_status_internal.as_str()); + match status { + ReplicationStatusType::Pending + | ReplicationStatusType::Completed + | ReplicationStatusType::Failed + | ReplicationStatusType::Replica => status, + _ => { + let repl_status = get_composite_replication_status(&self.targets); + if self.replica_timestamp == Utc::now() || self.replica_timestamp.timestamp() == 0 { + return repl_status; + } + if repl_status == ReplicationStatusType::Completed && self.replica_timestamp > self.replication_timestamp { + return self.replica_status.clone(); + } + repl_status + } + } + } else if !self.replica_status.is_empty() { + self.replica_status.clone() + } else { + return ReplicationStatusType::Unknown; + } + } + + // CompositeVersionPurgeStatus 方法:返回总体的版本清除状态 + pub fn composite_version_purge_status(&self) -> VersionPurgeStatusType { + let status = VersionPurgeStatusType::from(self.version_purge_status_internal.as_str()); + match status { + VersionPurgeStatusType::Pending | VersionPurgeStatusType::Complete | VersionPurgeStatusType::Failed => status, + _ => get_composite_version_purge_status(&self.purge_targets), + } + } + + // target_state 方法:返回目标状态 + pub fn target_state(&self, arn: &str) -> ReplicatedTargetInfo { + ReplicatedTargetInfo { + arn: arn.to_string(), + prev_replication_status: self.targets.get(arn).cloned().unwrap_or(ReplicationStatusType::Unknown), + version_purge_status: self + .purge_targets + .get(arn) + .cloned() + .unwrap_or(VersionPurgeStatusType::Unknown), + resync_timestamp: self.reset_statuses_map.get(arn).cloned().unwrap_or_default(), + size: 0, + replication_status: self.replica_status.clone(), + duration: Duration::zero(), + replication_action: ReplicationAction::ReplicateAll, + op_type: 0, + replication_resynced: false, + endpoint: "".to_string(), + secure: false, + err: None, + } + } +} + +lazy_static! { + static ref REPL_STATUS_REGEX: Regex = Regex::new(r"([^=].*?)=([^,].*?);").unwrap(); +} +pub trait ObjectInfoExt { + fn target_replication_status(&self, arn: String) -> ReplicationStatusType; + fn is_multipart(&self) -> bool; +} + +impl ObjectInfoExt for store_api::ObjectInfo { + fn target_replication_status(&self, arn: String) -> ReplicationStatusType { + let rep_stat_matches = REPL_STATUS_REGEX.captures_iter(&self.replication_status_internal); + for matched in rep_stat_matches { + if let Some(arn_match) = matched.get(1) { + if arn_match.as_str() == arn { + if let Some(status_match) = matched.get(2) { + return ReplicationStatusType::from(status_match.as_str()); + } + } + } + } + /* `ReplicationStatusType` value */ + ReplicationStatusType::Unknown + } + fn is_multipart(&self) -> bool { + match &self.etag { + Some(etgval) => etgval.len() != 32 && etgval.len() > 0, + None => false, + } + } +} + +// Replication type enum (placeholder, as it's not clearly used in the Go code) +//#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ReplicateObjectInfo { + pub name: String, + pub bucket: String, + pub version_id: String, + pub etag: String, + pub size: i64, + pub actual_size: i64, + pub mod_time: DateTime, + pub user_tags: String, + pub ssec: bool, + pub replication_status: ReplicationStatusType, + pub replication_status_internal: String, + pub version_purge_status_internal: String, + pub version_purge_status: VersionPurgeStatusType, + pub replication_state: ReplicationState, + pub delete_marker: bool, + + pub op_type: i32, + pub event_type: String, + pub retry_count: u32, + pub reset_id: String, + pub dsc: ReplicateDecision, + pub existing_obj_resync: ResyncDecision, + pub target_arn: String, + pub target_statuses: HashMap, + pub target_purge_statuses: HashMap, + pub replication_timestamp: DateTime, + pub checksum: Vec, +} +impl ReplicateObjectInfo { + pub fn to_object_info(&self) -> ObjectInfo { + ObjectInfo { + bucket: self.bucket.clone(), + name: self.name.clone(), + mod_time: Some( + OffsetDateTime::from_unix_timestamp(self.mod_time.timestamp()).unwrap_or_else(|_| OffsetDateTime::now_utc()), + ), + size: self.size as usize, + actual_size: Some(self.actual_size as usize), + is_dir: false, + user_defined: None, // 可以按需从别处导入 + parity_blocks: 0, + data_blocks: 0, + version_id: Uuid::try_parse(&self.version_id).ok(), + delete_marker: self.delete_marker, + user_tags: self.user_tags.clone(), + parts: Vec::new(), + is_latest: true, + content_type: None, + content_encoding: None, + num_versions: 0, + successor_mod_time: None, + put_object_reader: None, + etag: Some(self.etag.clone()), + inlined: false, + metadata_only: false, + version_only: false, + replication_status_internal: self.replication_status_internal.clone(), + replication_status: self.replication_status.clone(), + version_purge_status_internal: self.version_purge_status_internal.clone(), + version_purge_status: self.version_purge_status.clone(), + checksum: self.checksum.clone(), + } + } +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct DeletedObject { + #[serde(rename = "DeleteMarker")] + pub delete_marker: Option, // Go 中的 `bool` 转换为 Rust 中的 `Option` 以支持 `omitempty` + + #[serde(rename = "DeleteMarkerVersionId")] + pub delete_marker_version_id: Option, // `omitempty` 转为 `Option` + + #[serde(rename = "Key")] + pub object_name: Option, // 同样适用 `Option` 包含 `omitempty` + + #[serde(rename = "VersionId")] + pub version_id: Option, // 同上 + + // 以下字段未出现在 XML 序列化中,因此不需要 serde 标注 + #[serde(skip)] + pub delete_marker_mtime: DateTime, // 自定义类型,需定义或引入 + #[serde(skip)] + pub replication_state: ReplicationState, // 自定义类型,需定义或引入 +} + +// 假设 `DeleteMarkerMTime` 和 `ReplicationState` 的定义如下: +#[derive(Debug, Default, Clone)] +pub struct DeleteMarkerMTime { + time: chrono::NaiveDate, + // 填写具体字段类型 +} + +impl ReplicationWorkerOperation for ReplicateObjectInfo { + fn to_mrf_entry(&self) -> MRFReplicateEntry { + MRFReplicateEntry { + bucket: self.bucket.clone(), + object: self.name.clone(), + version_id: self.version_id.clone(), // 直接使用计算后的 version_id + retry_count: 0, + sz: self.size.clone(), + } + } + fn as_any(&self) -> &dyn Any { + self + } +} + +impl ReplicationWorkerOperation for DeletedObjectReplicationInfo { + fn to_mrf_entry(&self) -> MRFReplicateEntry { + let version_id = if !self.deleted_object.delete_marker_version_id.is_none() { + self.deleted_object.delete_marker_version_id.clone() + } else { + self.deleted_object.delete_marker_version_id.clone() + }; + + MRFReplicateEntry { + bucket: self.bucket.clone(), + object: self.deleted_object.object_name.clone().unwrap().clone(), + version_id: "0".to_string(), // 直接使用计算后的 version_id + retry_count: 0, + sz: 0, + } + } + fn as_any(&self) -> &dyn Any { + self + } +} + +pub fn get_s3client_from_para(ak: &str, sk: &str, url: &str, _region: &str) -> Result> { + let credentials = Credentials::new(ak, sk, None, None, ""); + let region = Region::new("us-east-1".to_string()); + + let config = Config::builder() + .region(region) + .endpoint_url(url.to_string()) + .credentials_provider(credentials) + .behavior_version(BehaviorVersion::latest()) // Adjust as necessary + .build(); + Ok(S3Client::from_conf(config)) +} + +// use hyper::body::Body; +// use s3s::Body; + +async fn replicate_object_with_multipart( + rep_obj: &ReplicateObjectInfo, + local_obj_info: &ObjectInfo, + target_info: &ReplicatedTargetInfo, + tgt_cli: &TargetClient, +) -> Result<(), Error> { + let store = new_object_layer_fn().unwrap(); + let provider = StaticProvider::new(&tgt_cli.ak, &tgt_cli.sk, None); + let minio_cli = Minio::builder() + .endpoint(target_info.endpoint.clone()) + .provider(provider) + .secure(false) + .build() + .unwrap(); + + let ret = minio_cli + .create_multipart_upload_with_versionid(tgt_cli.bucket.clone(), local_obj_info.name.clone(), rep_obj.version_id.clone()) + .await; + match ret { + Ok(task) => { + let parts_len = local_obj_info.parts.len(); + let mut part_results = vec![None; parts_len]; + let version_id = local_obj_info.version_id.clone().expect("missing version_id"); + let task = Arc::new(task); // clone safe + let store = Arc::new(store); + let minio_cli = Arc::new(minio_cli); + + let mut upload_futures = FuturesUnordered::new(); + + for (index, _) in local_obj_info.parts.iter().enumerate() { + let store = Arc::clone(&store); + let minio_cli = Arc::clone(&minio_cli); + let task = Arc::clone(&task); + let bucket = local_obj_info.bucket.clone(); + let name = local_obj_info.name.clone(); + let version_id = version_id.clone(); + + upload_futures.push(tokio::spawn(async move { + let get_opts = ObjectOptions { + version_id: Some(version_id.to_string()), + versioned: true, + part_number: Some(index + 1), + version_suspended: false, + ..Default::default() + }; + + let h = HeaderMap::new(); + match store.get_object_reader(&bucket, &name, None, h, &get_opts).await { + Ok(mut reader) => match reader.read_all().await { + Ok(ret) => { + debug!("2025 readall suc:"); + let body = Bytes::from(ret); + match minio_cli.upload_part(&task, index + 1, body).await { + Ok(part) => { + debug!("2025 multipar upload suc:"); + Ok((index, part)) + } + Err(err) => { + error!("upload part {} failed: {}", index + 1, err); + Err(Error::from_string(format!("upload error: {}", err))) + } + } + } + Err(err) => { + error!("read error for part {}: {}", index + 1, err); + Err(err) + } + }, + Err(err) => { + error!("reader error for part {}: {}", index + 1, err); + Err(Error::from_string(format!("reader error: {}", err))) + } + } + })); + } + + while let Some(result) = upload_futures.next().await { + match result { + Ok(Ok((index, part))) => { + part_results[index] = Some(part); + } + Ok(Err(err)) => { + error!("upload part failed: {}", err); + return Err(err); + } + Err(join_err) => { + error!("tokio join error: {}", join_err); + return Err(Error::from_string(format!("join error: {}", join_err))); + } + } + } + + let parts: Vec<_> = part_results.into_iter().flatten().collect(); + + let ret = minio_cli.complete_multipart_upload(&task, parts, None).await; + match ret { + Ok(res) => { + warn!("finish upload suc:{:?} version_id={:?}", res, local_obj_info.version_id); + } + Err(err) => { + error!("finish upload failed:{}", err); + return Err(err.into()); + } + } + } + Err(err) => { + return Err(err.into()); + } + } + return Ok(()); +} + +impl ReplicateObjectInfo { + fn target_replication_status(&self, arn: &str) -> ReplicationStatusType { + // 定义正则表达式,匹配类似 `arn;status` 格式 + let repl_status_regex = Regex::new(r"(\w+);(\w+)").expect("Invalid regex"); + + // 遍历正则表达式的匹配项 + for caps in repl_status_regex.captures_iter(&self.replication_status_internal) { + if let (Some(matched_arn), Some(matched_status)) = (caps.get(1), caps.get(2)) { + // 如果 ARN 匹配,返回对应的状态 + if matched_arn.as_str() == arn { + return ReplicationStatusType::from(matched_status.as_str()); + } + } + } + + // 如果没有匹配到,返回默认的 `Unknown` 状态 + ReplicationStatusType::Unknown + } + + async fn replicate_object(&self, target: &TargetClient, _arn: String) -> ReplicatedTargetInfo { + let _start_time = chrono::Utc::now(); + + // 初始化 ReplicatedTargetInfo + warn!("replicate is {}", _arn.clone()); + let mut rinfo = ReplicatedTargetInfo { + size: self.actual_size, + arn: _arn.clone(), + prev_replication_status: self.target_replication_status(&_arn.clone()), + replication_status: ReplicationStatusType::Failed, + op_type: self.op_type.clone(), + replication_action: ReplicationAction::ReplicateAll, + endpoint: target.endpoint.clone(), + secure: target.endpoint.clone().contains("https://"), + resync_timestamp: chrono::Utc::now().to_string(), + replication_resynced: false, + duration: Duration::default(), + err: None, + version_purge_status: VersionPurgeStatusType::Pending, + }; + + if self.target_replication_status(&_arn) == ReplicationStatusType::Completed + && !self.existing_obj_resync.is_empty() + && !self.existing_obj_resync.must_resync_target(&_arn) + { + warn!("replication return"); + rinfo.replication_status = ReplicationStatusType::Completed; + rinfo.replication_resynced = true; + return rinfo; + } + + // 模拟远程目标离线的检查 + // if self.is_target_offline(&target.endpoint) { + // rinfo.err = Some(format!( + // "Target is offline for bucket: {} arn: {} retry: {}", + // self.bucket, + // _arn.clone(), + // self.retry_count + // )); + // return rinfo; + // } + + // versioned := globalBucketVersioningSys.PrefixEnabled(bucket, object) + // versionSuspended := globalBucketVersioningSys.PrefixSuspended(bucket, object) + + // 模拟对象获取和元数据检查 + let mut opt = store_api::ObjectOptions::default(); + opt.version_id = Some(self.version_id.clone()); + opt.versioned = true; + opt.version_suspended = false; + + let object_info = match self.get_object_info(opt).await { + Ok(info) => info, + Err(err) => { + error!("get object info err:{}", err); + rinfo.err = Some(err.to_string()); + return rinfo; + } + }; + + rinfo.prev_replication_status = object_info.target_replication_status(_arn); + + // 设置对象大小 + //rinfo.size = object_info.actual_size.unwrap_or(0); + rinfo.size = object_info.actual_size.map_or(0, |v| v as i64); + //rinfo.replication_action = object_info. + + rinfo.replication_status = ReplicationStatusType::Completed; + rinfo.size = object_info.get_actual_size().unwrap_or(0) as i64; + rinfo.replication_action = ReplicationAction::ReplicateAll; + + let store = new_object_layer_fn().unwrap(); + //todo!() put replicationopts; + if object_info.is_multipart() { + debug!("version is multi part"); + match replicate_object_with_multipart(&self, &object_info, &rinfo, target).await { + Ok(_) => { + rinfo.replication_status = ReplicationStatusType::Completed; + println!("Object replicated successfully."); + } + Err(e) => { + rinfo.replication_status = ReplicationStatusType::Failed; + error!("Failed to replicate object: {:?}", e); + // 你可以根据错误类型进一步分类处理 + } + } + //replicate_object_with_multipart(local_obj_info, target_info, tgt_cli) + } else { + let get_opts = ObjectOptions { + version_id: Some(object_info.version_id.clone().expect("REASON").to_string()), + versioned: true, + version_suspended: false, + ..Default::default() + }; + warn!("version id is:{:?}", get_opts.version_id.clone()); + let h = HeaderMap::new(); + let gr = store + .get_object_reader(&object_info.bucket, &object_info.name, None, h, &get_opts) + .await; + + match gr { + Ok(mut reader) => { + warn!("endpoint is: {}", rinfo.endpoint); + let provider = StaticProvider::new(&target.ak, &target.sk, None); + let res = reader.read_all().await; + match res { + Ok(ret) => { + let body = rustfs_rsc::Data::from(ret); + let minio_cli = Minio::builder() + .endpoint(rinfo.endpoint.clone()) + .provider(provider) + .secure(false) + .build() + .unwrap(); + + let ex = minio_cli.executor(Method::PUT); + let ret = ex + .bucket_name(target.bucket.clone()) + .object_name(self.name.clone()) + .body(body) + .query("versionId", get_opts.version_id.clone().unwrap()) + .send_ok() + .await; + match ret { + Ok(_res) => { + warn!("replicate suc: {} {} {}", self.bucket, self.name, self.version_id); + rinfo.replication_status = ReplicationStatusType::Completed; + } + Err(err) => { + error!("replicate {} err:{}", target.bucket.clone(), err); + rinfo.replication_status = ReplicationStatusType::Failed; + } + } + } + Err(err) => { + error!("read_all err {}", err); + rinfo.replication_status = ReplicationStatusType::Failed; + return rinfo; + } + } + } + Err(err) => { + rinfo.replication_status = ReplicationStatusType::Failed; + error!("get client error {}", err); + } + } + } + return rinfo; + } + + fn is_target_offline(&self, endpoint: &str) -> bool { + // 模拟检查目标是否离线 + warn!("Checking if target {} is offline", endpoint); + false + } + + async fn get_object_info(&self, opts: store_api::ObjectOptions) -> Result { + let objectlayer = new_object_layer_fn(); + //let opts = ecstore::store_api::ObjectOptions { max_parity: (), mod_time: (), part_number: (), delete_prefix: (), version_id: (), no_lock: (), versioned: (), version_suspended: (), skip_decommissioned: (), skip_rebalancing: (), data_movement: (), src_pool_idx: (), user_defined: (), preserve_etag: (), metadata_chg: (), replication_request: (), delete_marker: () } + let res = objectlayer.unwrap().get_object_info(&self.bucket, &self.name, &opts).await; + return res; + } + + fn perform_replication(&self, target: &RemotePeerS3Client, object_info: &ObjectInfo) -> Result<(), String> { + // 模拟复制操作 + // println!( + // "Replicating object {} to target {}", + // //object_info.name, target.arn + // ); + Ok(()) + } + + fn current_timestamp() -> String { + // 返回当前时间戳 + "2024-12-18T00:00:00Z".to_string() + } +} + +//pub fn getvalidrule(cfg: ReplicationConfiguration) -> Vec { +// let mut arns = Vec::new(); +// let mut tgts_map = std::collections::HashSet::new(); +// for rule in cfg.rules { +// if rule.status.as_str() == "Disabe" { +// continue; +// } + +// if tgts_map.insert(rule.clone()) {} +// } +// arns +//} + +pub async fn replicate_delete(_ri: &DeletedObjectReplicationInfo, object_api: Arc) {} + +pub fn clone_mss(v: &HashMap) -> HashMap { + let mut r = HashMap::with_capacity(v.len()); + for (k, v) in v { + r.insert(k.clone(), v.clone()); + } + r +} + +pub fn get_must_replicate_options( + user_defined: &HashMap, + user_tags: &str, + status: ReplicationStatusType, // 假设 `status` 是字符串类型 + op: ReplicationType, // 假设 `op` 是字符串类型 + opts: &ObjectOptions, +) -> MustReplicateOptions { + let mut meta = clone_mss(&user_defined); + + if !user_tags.is_empty() { + meta.insert("xhttp.AmzObjectTagging".to_string(), user_tags.to_string()); + } + + MustReplicateOptions { + meta, + status: status, + op_type: op, + replication_request: opts.replication_request, + } +} + +#[derive(Default)] +struct ReplicatedInfos { + //replication_time_stamp: DateTime, + targets: Vec, +} + +// #[derive(Clone, Copy, PartialEq)] +// enum ReplicationStatus { +// Completed, +// InProgress, +// Pending, +// } + +impl ReplicatedInfos { + pub fn action(&self) -> ReplicationAction { + for target in &self.targets { + if target.is_empty() { + continue; + } + if target.prev_replication_status != ReplicationStatusType::Completed { + return target.replication_action.clone(); + } + } + ReplicationAction::ReplicateNone + } + + // fn completed_size(&self) -> i64 { + // let mut sz = 0; + // for t in &self.targets { + // if t.empty() { + // continue; + // } + // if t.replication_status == ReplicationStatusType::Completed + // && t.prev_replication_status != ReplicationStatusType::Completed + // { + // sz += t.size; + // } + // } + // sz + // } + + pub fn replication_resynced(&self) -> bool { + // 只要存在一个非 empty 且 replication_resynced 为 true 的目标,就返回 true + self.targets.iter().any(|t| !t.is_empty() && t.replication_resynced) + } + + /// 对应 Go 的 ReplicationStatusInternal + pub fn replication_status_internal(&self) -> String { + let mut buf = String::new(); + for t in &self.targets { + if t.is_empty() { + continue; + } + // 类似 fmt.Fprintf(b, "%s=%s;", t.Arn, t.ReplicationStatus.String()) + buf.push_str(&format!("{}={};", t.arn, t.replication_status.as_str())); + } + buf + } + + pub fn replication_status(&self) -> ReplicationStatusType { + // 如果没有任何目标,返回 Unknown(对应 Go 里 StatusType("")) + if self.targets.is_empty() { + return ReplicationStatusType::Unknown; + } + + // 统计已完成的数量 + let mut completed = 0; + + for t in &self.targets { + match t.replication_status { + ReplicationStatusType::Failed => { + // 只要有一个失败,整体就是 Failed + return ReplicationStatusType::Failed; + } + ReplicationStatusType::Completed => { + completed += 1; + } + _ => {} + } + } + + // 全部完成,则 Completed,否则 Pending + if completed == self.targets.len() { + ReplicationStatusType::Completed + } else { + ReplicationStatusType::Pending + } + } +} + + +impl ReplicatedTargetInfo { + fn empty(&self) -> bool { + // Implement your logic to check if the target is empty + self.size == 0 + } +} + +pub async fn replicate_object(ri: ReplicateObjectInfo, object_api: Arc) { + let bucket = ri.bucket.clone(); + let obj = ri.name.clone(); + match get_replication_config(&bucket).await { + Ok((cfg, timestamp)) => { + info!( + "replicate object: {} {} and arn is: {}", + ri.name.clone(), + timestamp, + ri.target_arn.clone() + ); + //let arns = getvalidrule(config); + + //TODO:nslock + + let objectlayer = new_object_layer_fn(); + + let opts = ReplicationObjectOpts { + name: ri.name.clone(), + //ssec: crypto::is_ssec_encrypted(&mopts.meta), + ssec: false, + //replica: repl_status == ReplicationStatusType::Replica, + replica: ri.replication_status == ReplicationStatusType::Replica, + existing_object: ri.existing_obj_resync.must_resync(), + user_tags: None, + target_arn: Some(ri.target_arn.clone()), + version_id: ri.version_id.clone(), + delete_marker: false, + op_type: ReplicationType::from_u8(ri.op_type as u8).expect("REASON"), + }; + + let tgt_arns = cfg.filter_target_arns(&opts); + info!("target len:{}", tgt_arns.len()); + + let rinfos = Arc::new(Mutex::new(ReplicatedInfos::default())); + let cri = Arc::new(ri.clone()); + let mut tasks: Vec> = vec![]; + + for tgt_arn in tgt_arns { + let tgt = bucket_targets::get_bucket_target_client(&ri.bucket, &tgt_arn).await; + + if !tgt.is_ok() { + // repl_log_once_if(ctx, format!("failed to get target for bucket: {} arn: {}", bucket, tgt_arn), &tgt_arn).await; + // send_event(event_args { + // event_name: "ObjectReplicationNotTracked".to_string(), + // bucket_name: bucket.to_string(), + // object: ri.to_object_info(), + // user_agent: "Internal: [Replication]".to_string(), + // host: global_local_node_name.to_string(), + // }).await; + continue; + } + + let tgt = tgt.unwrap(); + let rinfos_clone = Arc::clone(&rinfos); + let lcri = Arc::clone(&cri); + let task = task::spawn(async move { + warn!("async task"); + let mut tgt_info: ReplicatedTargetInfo = Default::default(); + if lcri.op_type as u8 == ReplicationType::ObjectReplicationType.as_u8() { + warn!("object replication and arn is {}", tgt.arn.clone()); + // all incoming calls go through optimized path.`o` + + tgt_info = lcri.replicate_object(&tgt, tgt.arn.clone()).await; + } else { + warn!("async task"); + // tgt_info = ri.replicate_all(object_api, &tgt).await; + } + + let mut rinfos_locked = rinfos_clone.lock().await; + rinfos_locked.targets.push(tgt_info); + }); + + tasks.push(task); + } + //futures::future::join_all(tasks); + futures::future::join_all(tasks).await; + + let mut rs = rinfos.lock().await; + let replication_status = rs.replication_status(); + //rinfos + let new_repl_status_internal = rs.replication_status_internal(); + // ri.to_object_info() 假设... + warn!("{} and {}", new_repl_status_internal, ri.replication_status_internal); + let obj_info = ri.to_object_info(); + if ri.replication_status_internal != new_repl_status_internal || rs.replication_resynced() { + warn!("save meta"); + let mut eval_metadata = HashMap::new(); + + eval_metadata.insert( + format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-status"), + new_repl_status_internal.clone(), + ); + eval_metadata.insert( + format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-timestamp"), + Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Nanos, true), + ); + eval_metadata.insert("x-amz-bucket-replication-status".to_string(), replication_status.as_str().to_owned()); + + for rinfo in &rs.targets { + // if !rinfo.resync_timestamp.is_empty() { + // eval_metadata.insert( + // format!("x-minio-replication-reset-status-{}", rinfo.arn), + // rinfo.resync_timestamp.clone(), + // ); + // } + } + + if !ri.user_tags.is_empty() { + eval_metadata.insert("x-amz-tagging".to_string(), ri.user_tags.clone()); + } + + let popts = ObjectOptions { + //mod_time: Some(ri.mod_time), + mod_time: None, + version_id: Some(ri.version_id.clone()), + eval_metadata: Some(eval_metadata), + ..Default::default() + }; + + //let uobj_info = ; + match object_api.put_object_metadata(&ri.bucket, &ri.name, &popts).await { + Ok(info) => { + info!("Put metadata success: {:?}", info); + // 你可以访问 info 字段,例如 info.size, info.last_modified 等 + } + Err(e) => { + error!("Failed to put metadata: {}", e); + // 根据错误类型做不同处理 + // if let Some(CustomError::NotFound) = e.downcast_ref::() { ... } + } + } + + // if !uobj_info.name.is_empty() { + // obj_info = uobj_info; + // } + + let mut op_type = ReplicationType::MetadataReplicationType; + if rs.action() == ReplicationAction::ReplicateAll { + op_type = ReplicationType::ObjectReplicationType + } + + for rinfo in &mut rs.targets { + if rinfo.replication_status != rinfo.prev_replication_status { + //rinfo.op_type = Some(op_type.clone()); + //global_replication_stats::update(&bucket, rinfo); + } + } + debug!("op type: {:?}", op_type); + } + + // send_event(EventArgs { + // event_name: ri.event_name.clone(), + // bucket_name: bucket.into(), + // object: obj_info.clone(), + // user_agent: "Internal: [Replication]".into(), + // host: "local-node-name".into(), + // }); + + // 失败重试 + // if rs.replication_status() != ReplicationStatusType::Completed { + // //ri.op_type = "HealReplicationType".into(); + // ri.event_type = "ReplicateMRF".into(); + // //ri.replication_status_internal = rinfos.replication_status_internal(); + // ri.retry_count += 1; + // // global_replication_pool.get().queue_mrf_save(ri.to_mrf_entry()); + // } + } + Err(err) => { + println!("Failed to get replication config: {:?}", err); + } + } +} diff --git a/ecstore/src/cmd/bucket_replication_utils.rs b/ecstore/src/cmd/bucket_replication_utils.rs new file mode 100644 index 00000000..7c456427 --- /dev/null +++ b/ecstore/src/cmd/bucket_replication_utils.rs @@ -0,0 +1,55 @@ +use std::collections::HashMap; +use chrono::{DateTime, Utc}; + +// Representation of the replication status +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum StatusType { + Pending, + Completed, + CompletedLegacy, + Failed, + Replica, +} + +// Representation of version purge status type (customize as needed) +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum VersionPurgeStatusType { + Pending, + Completed, + Failed, +} + +// ReplicationState struct definition +#[derive(Debug, Clone)] +pub struct ReplicationState { + // Timestamp when the last replica update was received + pub replica_time_stamp: DateTime, + + // Replica status + pub replica_status: StatusType, + + // Represents DeleteMarker replication state + pub delete_marker: bool, + + // Timestamp when the last replication activity happened + pub replication_time_stamp: DateTime, + + // Stringified representation of all replication activity + pub replication_status_internal: String, + + // Stringified representation of all version purge statuses + // Example format: "arn1=PENDING;arn2=COMPLETED;" + pub version_purge_status_internal: String, + + // Stringified representation of replication decision for each target + pub replicate_decision_str: String, + + // Map of ARN -> replication status for ongoing replication activity + pub targets: HashMap, + + // Map of ARN -> VersionPurgeStatus for all the targets + pub purge_targets: HashMap, + + // Map of ARN -> stringified reset id and timestamp for all the targets + pub reset_statuses_map: HashMap, +} \ No newline at end of file diff --git a/ecstore/src/cmd/bucket_targets.rs b/ecstore/src/cmd/bucket_targets.rs new file mode 100644 index 00000000..8edf2e46 --- /dev/null +++ b/ecstore/src/cmd/bucket_targets.rs @@ -0,0 +1,864 @@ +#![allow(unused_variables)] +#![allow(dead_code)] +use crate::{ + bucket::{metadata_sys, target::BucketTarget}, + endpoints::Node, + peer::{PeerS3Client, RemotePeerS3Client}, + StorageAPI, +}; +use crate::{ + bucket::{self, target::BucketTargets}, + new_object_layer_fn, peer, store_api, +}; +use chrono::Utc; +use lazy_static::lazy_static; +use std::{ + collections::HashMap, + time::{Duration, SystemTime}, +}; +//use tokio::sync::RwLock; +use aws_sdk_s3::Client as S3Client; +use std::sync::{Arc}; +use tokio::sync::RwLock; +use thiserror::Error; + +pub struct TClient { + pub s3cli: S3Client, + pub remote_peer_client: peer::RemotePeerS3Client, + pub arn: String, +} +impl TClient { + pub fn new(s3cli: S3Client, remote_peer_client: RemotePeerS3Client, arn: String) -> Self { + TClient { + s3cli, + remote_peer_client, + arn, + } + } +} + +pub struct EpHealth { + pub endpoint: String, + pub scheme: String, + pub online: bool, + pub last_online: SystemTime, + pub last_hc_at: SystemTime, + pub offline_duration: Duration, + pub latency: LatencyStat, // Assuming LatencyStat is a custom struct +} + +impl EpHealth { + pub fn new( + endpoint: String, + scheme: String, + online: bool, + last_online: SystemTime, + last_hc_at: SystemTime, + offline_duration: Duration, + latency: LatencyStat, + ) -> Self { + EpHealth { + endpoint, + scheme, + online, + last_online, + last_hc_at, + offline_duration, + latency, + } + } +} + +pub struct LatencyStat { + // Define the fields of LatencyStat as per your requirements +} + +pub struct ArnTarget { + client: TargetClient, + last_refresh: chrono::DateTime, +} +impl ArnTarget { + pub fn new(bucket: String, endpoint: String, ak:String, sk:String) -> Self { + Self { + client: TargetClient { + bucket: bucket, + storage_class: "STANDRD".to_string(), + disable_proxy: false, + health_check_duration: Duration::from_secs(100), + endpoint: endpoint, + reset_id: "0".to_string(), + replicate_sync: false, + secure: false, + arn: "".to_string(), + client: reqwest::Client::new(), + ak:ak, + sk:sk, + }, + last_refresh: Utc::now(), + } + } +} + +// pub fn get_s3client_from_para( +// ak: &str, +// sk: &str, +// url: &str, +// _region: &str, +// ) -> Result> { +// let credentials = Credentials::new(ak, sk, None, None, ""); +// let region = Region::new("us-east-1".to_string()); + +// let config = Config::builder() +// .region(region) +// .endpoint_url(url.to_string()) +// .credentials_provider(credentials) +// .behavior_version(BehaviorVersion::latest()) // Adjust as necessary +// .build(); +// Ok(S3Client::from_conf(config)) +// } + +pub struct BucketTargetSys { + arn_remote_map: Arc>>, + targets_map: Arc>>>, + hc: HashMap, + //store:Option>, +} + +lazy_static! { + pub static ref GLOBAL_Bucket_Target_Sys: std::sync::OnceLock = BucketTargetSys::new().into(); +} + +//#[derive(Debug)] +// pub enum SetTargetError { +// NotFound, +// } + +pub async fn get_bucket_target_client(bucket: &str, arn: &str) -> Result { + if let Some(sys) = GLOBAL_Bucket_Target_Sys.get() { + sys.get_remote_target_client2(arn).await + } else { + Err(SetTargetError::TargetNotFound(bucket.to_string())) + } +} + +#[derive(Debug)] +pub struct BucketRemoteTargetNotFound { + pub bucket: String, +} + +pub async fn init_bucket_targets(bucket: &str, meta: Arc) { + println!("140 {}", bucket); + if let Some(sys) = GLOBAL_Bucket_Target_Sys.get() { + if let Some(tgts) = meta.bucket_target_config.clone() { + for tgt in tgts.targets { + warn!("ak and sk is:{:?}",tgt.credentials); + let _ = sys.set_target(bucket, &tgt, false, true).await; + //sys.targets_map. + } + } + } +} + +pub async fn remove_bucket_target(bucket: &str, arn_str:&str) { + if let Some(sys) = GLOBAL_Bucket_Target_Sys.get() { + let _ = sys.remove_target(bucket, arn_str).await; + } +} + + +impl BucketTargetSys { + pub fn new() -> Self { + BucketTargetSys { + arn_remote_map: Arc::new(RwLock::new(HashMap::new())), + targets_map: Arc::new(RwLock::new(HashMap::new())), + hc: HashMap::new(), + } + } + + pub async fn list_bucket_targets(&self, bucket: &str) -> Result { + let targets_map = self.targets_map.read().await; + if let Some(targets) = targets_map.get(bucket) { + Ok(BucketTargets { + targets: targets.clone(), + }) + } else { + Err(BucketRemoteTargetNotFound { + bucket: bucket.to_string(), + }) + } + } + + pub async fn list_targets(&self, bucket: Option<&str>, _arn_type: Option<&str>) -> Vec { + let _ = _arn_type; + //let health_stats = self.health_stats(); + + let mut targets = Vec::new(); + + if let Some(bucket_name) = bucket { + if let Ok(ts) = self.list_bucket_targets(bucket_name).await { + for t in ts.targets { + //if arn_type.map_or(true, |arn| t.target_type == arn) { + //if let Some(hs) = health_stats.get(&t.url().host) { + // t.total_downtime = hs.offline_duration; + // t.online = hs.online; + // t.last_online = hs.last_online; + // t.latency = LatencyStat { + // curr: hs.latency.curr, + // avg: hs.latency.avg, + // max: hs.latency.peak, + // }; + //} + targets.push(t.clone()); + //} + } + } + return targets; + } + + // Locking and iterating over all targets in the system + let targets_map = self.targets_map.read().await; + for tgts in targets_map.values() { + for t in tgts { + //if arn_type.map_or(true, |arn| t.target_type == arn) { + // if let Some(hs) = health_stats.get(&t.url().host) { + // t.total_downtime = hs.offline_duration; + // t.online = hs.online; + // t.last_online = hs.last_online; + // t.latency = LatencyStat { + // curr: hs.latency.curr, + // avg: hs.latency.avg, + // max: hs.latency.peak, + // }; + // } + targets.push(t.clone()); + //} + } + } + + targets + } + + pub async fn remove_target(&self, bucket:&str, arn_str:&str) -> Result<(), SetTargetError> { + //to do need lock; + let mut targets_map = self.targets_map.write().await; + let tgts = targets_map.get(bucket); + let mut arn_remotes_map = self.arn_remote_map.write().await; + if tgts.is_none() { + //Err(SetTargetError::TargetNotFound(bucket.to_string())); + return Ok(()); + } + + let tgts = tgts.unwrap(); // 安全解引用 + let mut targets = Vec::with_capacity(tgts.len()); + let mut found = false; + + // 遍历 targets,找出不匹配的 ARN + for tgt in tgts { + if tgt.arn != Some(arn_str.to_string()) { + targets.push(tgt.clone()); // 克隆符合条件的项 + } else { + found = true; // 找到匹配的 ARN + } + } + + // 如果没有找到匹配的 ARN,则返回错误 + if !found { + return Ok(()); + } + + // 更新 targets_map + targets_map.insert(bucket.to_string(), targets); + arn_remotes_map.remove(arn_str); + + + let targets = self.list_targets(Some(&bucket), None).await; + println!("targets is {}", targets.len()); + match serde_json::to_vec(&targets) { + Ok(json) => { + let _ = metadata_sys::update(bucket, "bucket-targets.json", json).await; + } + Err(e) => { + println!("序列化失败{}", e); + } + } + + Ok(()) + } + + pub async fn get_remote_arn(&self, bucket: &str, target: Option<&BucketTarget>, depl_id: &str) -> (Option, bool) { + if target.is_none() { + return (None, false); + } + + let target = target.unwrap(); + + let targets_map = self.targets_map.read().await; + + // 获取锁以访问 arn_remote_map + let mut _arn_remotes_map = self.arn_remote_map.read().await; + if let Some(tgts) = targets_map.get(bucket) { + for tgt in tgts { + if tgt.type_ == target.type_ + && tgt.target_bucket == target.target_bucket + && tgt.endpoint == target.endpoint + && tgt.credentials.as_ref().unwrap().access_key == target.credentials.as_ref().unwrap().access_key + { + return (tgt.arn.clone(), true); + } + } + } + + // if !target.type_.is_valid() { + // return (None, false); + // } + + println!("generate_arn"); + + (Some(generate_arn(target.clone(), depl_id.to_string())), false) + } + + pub async fn get_remote_target_client2(&self, arn: &str) -> Result { + let map = self.arn_remote_map.read().await; + info!("get remote target client and arn is: {}", arn); + if let Some(value) = map.get(arn) { + let mut x = value.client.clone(); + x.arn = arn.to_string(); + Ok(x) + } else { + error!("not find target"); + Err(SetTargetError::TargetNotFound(arn.to_string())) + } + } + + // pub async fn get_remote_target_client(&self, _tgt: &BucketTarget) -> Result { + // // Mocked implementation for obtaining a remote client + // let tcli = TargetClient { + // bucket: _tgt.target_bucket.clone(), + // storage_class: "STANDRD".to_string(), + // disable_proxy: false, + // health_check_duration: Duration::from_secs(100), + // endpoint: _tgt.endpoint.clone(), + // reset_id: "0".to_string(), + // replicate_sync: false, + // secure: false, + // arn: "".to_string(), + // client: reqwest::Client::new(), + // ak: _tgt. + + // }; + // Ok(tcli) + // } + // pub async fn get_remote_target_client_with_bucket(&self, _bucket: String) -> Result { + // // Mocked implementation for obtaining a remote client + // let tcli = TargetClient { + // bucket: _tgt.target_bucket.clone(), + // storage_class: "STANDRD".to_string(), + // disable_proxy: false, + // health_check_duration: Duration::from_secs(100), + // endpoint: _tgt.endpoint.clone(), + // reset_id: "0".to_string(), + // replicate_sync: false, + // secure: false, + // arn: "".to_string(), + // client: reqwest::Client::new(), + // }; + // Ok(tcli) + // } + + async fn local_is_bucket_versioned(&self, _bucket: &str) -> bool { + let Some(store) = new_object_layer_fn() else { + return false; + }; + //store.get_bucket_info(bucket, opts) + + // let binfo:BucketInfo = store + // .get_bucket_info(bucket, &ecstore::store_api::BucketOptions::default()).await; + match store.get_bucket_info(_bucket, &store_api::BucketOptions::default()).await { + Ok(info) => { + println!("Bucket Info: {:?}", info); + return info.versionning; + } + Err(err) => { + eprintln!("Error: {:?}", err); + return false; + } + } + } + + async fn is_bucket_versioned(&self, _bucket: &str) -> bool { + return true; + // let url_str = "http://127.0.0.1:9001"; + + // // 转换为 Url 类型 + // let parsed_url = url::Url::parse(url_str).unwrap(); + + // let node = Node { + // url: parsed_url, + // pools: vec![], + // is_local: false, + // grid_host: "".to_string(), + // }; + // let cli = ecstore::peer::RemotePeerS3Client::new(Some(node), None); + + // match cli.get_bucket_info(_bucket, &ecstore::store_api::BucketOptions::default()).await + // { + // Ok(info) => { + // println!("Bucket Info: {:?}", info); + // info.versionning + // } + // Err(err) => { + // eprintln!("Error: {:?}", err); + // return false; + // } + // } + } + + pub async fn set_target(&self, bucket: &str, tgt: &BucketTarget, update: bool, fromdisk: bool) -> Result<(), SetTargetError> { + // if !tgt.type_.is_valid() && !update { + // return Err(SetTargetError::InvalidTargetType(bucket.to_string())); + // } + + //let client = self.get_remote_target_client(tgt).await?; + if tgt.type_ == Some("replication".to_string()) { + if !fromdisk { + let versioning_config = self.local_is_bucket_versioned(bucket).await; + if !versioning_config { + // println!("111111111"); + return Err(SetTargetError::TargetNotVersioned(bucket.to_string())); + } + } + } + + let url_str = format!("http://{}", tgt.endpoint.clone()); + + println!("url str is {}", url_str); + // 转换为 Url 类型 + let parsed_url = url::Url::parse(&url_str).unwrap(); + + let node = Node { + url: parsed_url, + pools: vec![], + is_local: false, + grid_host: "".to_string(), + }; + + let cli = peer::RemotePeerS3Client::new(Some(node), None); + + match cli + .get_bucket_info(&tgt.target_bucket, &store_api::BucketOptions::default()) + .await + { + Ok(info) => { + println!("Bucket Info: {:?}", info); + if !info.versionning { + println!("2222222222 {}", info.versionning); + return Err(SetTargetError::TargetNotVersioned(tgt.target_bucket.to_string())); + } + } + Err(err) => { + println!("remote bucket 369 is:{}", tgt.target_bucket); + eprintln!("Error: {:?}", err); + return Err(SetTargetError::SourceNotVersioned(tgt.target_bucket.to_string())); + } + } + + //if tgt.target_type == BucketTargetType::ReplicationService { + // Check if target is a MinIO server and alive + // let hc_result = tokio::time::timeout(Duration::from_secs(3), client.health_check(&tgt.endpoint)).await; + // match hc_result { + // Ok(Ok(true)) => {} // Server is alive + // Ok(Ok(false)) | Ok(Err(_)) | Err(_) => { + // return Err(SetTargetError::HealthCheckFailed(tgt.target_bucket.clone())); + // } + // } + + //Lock and update target maps + let mut targets_map = self.targets_map.write().await; + let mut arn_remotes_map = self.arn_remote_map.write().await; + + let targets = targets_map.entry(bucket.to_string()).or_default(); + let mut found = false; + + for existing_target in targets.iter_mut() { + println!("418 exist:{}", existing_target.source_bucket.clone()); + if existing_target.type_ == tgt.type_ { + if existing_target.arn == tgt.arn { + if !update { + return Err(SetTargetError::TargetAlreadyExists(existing_target.target_bucket.clone())); + } + *existing_target = tgt.clone(); + found = true; + break; + } + + if existing_target.endpoint == tgt.endpoint { + println!("endpoint is same:{}", tgt.endpoint.clone()); + return Err(SetTargetError::TargetAlreadyExists(existing_target.target_bucket.clone())); + } + } + } + + if !found && !update { + println!("437 exist:{}", tgt.arn.clone().unwrap()); + targets.push(tgt.clone()); + } + let arntgt: ArnTarget = ArnTarget::new(tgt.target_bucket.clone(), tgt.endpoint.clone(),tgt.credentials.clone().unwrap().access_key.clone(), tgt.credentials.clone().unwrap().secret_key); + + arn_remotes_map.insert(tgt.arn.clone().unwrap().clone(), arntgt); + //self.update_bandwidth_limit(bucket, &tgt.arn, tgt.bandwidth_limit).await; + + Ok(()) + } +} + +#[derive(Clone)] +pub struct TargetClient { + pub client: reqwest::Client, // Using reqwest HTTP client + pub health_check_duration: Duration, + pub bucket: String, // Remote bucket target + pub replicate_sync: bool, + pub storage_class: String, // Storage class on remote + pub disable_proxy: bool, + pub arn: String, // ARN to uniquely identify remote target + pub reset_id: String, + pub endpoint: String, + pub secure: bool, + pub ak:String, + pub sk:String, +} + +impl TargetClient { + pub fn new( + client: reqwest::Client, + health_check_duration: Duration, + bucket: String, + replicate_sync: bool, + storage_class: String, + disable_proxy: bool, + arn: String, + reset_id: String, + endpoint: String, + secure: bool, + ak:String, + sk:String, + ) -> Self { + TargetClient { + client, + health_check_duration, + bucket, + replicate_sync, + storage_class, + disable_proxy, + arn, + reset_id, + endpoint, + secure, + ak, + sk, + } + } + pub async fn bucket_exists(&self, _bucket: &str) -> Result { + Ok(true) // Mocked implementation + } +} +use tracing::{error, warn, info}; +use uuid::Uuid; + +#[derive(Debug, Clone)] +pub struct VersioningConfig { + pub enabled: bool, +} + +impl VersioningConfig { + pub fn is_enabled(&self) -> bool { + self.enabled + } +} + +#[derive(Debug)] +pub struct Client; + +impl Client { + pub async fn bucket_exists(&self, _bucket: &str) -> Result { + Ok(true) // Mocked implementation + } + + pub async fn get_bucket_versioning(&self, _bucket: &str) -> Result { + Ok(VersioningConfig { enabled: true }) + } + + pub async fn health_check(&self, _endpoint: &str) -> Result { + Ok(true) // Mocked health check + } +} + +#[derive(Debug, PartialEq)] +pub struct ServiceType(String); + +impl ServiceType { + pub fn is_valid(&self) -> bool { + !self.0.is_empty() // 根据需求添加具体的验证逻辑 + } +} + +#[derive(Debug, PartialEq)] +pub struct ARN { + pub arn_type: String, + pub id: String, + pub region: String, + pub bucket: String, +} + +impl ARN { + /// 检查 ARN 是否为空 + pub fn is_empty(&self) -> bool { + //!self.arn_type.is_valid() + return false; + } + + /// 将 ARN 转为字符串格式 + pub fn to_string(&self) -> String { + format!("arn:minio:{}:{}:{}:{}", self.arn_type, self.region, self.id, self.bucket) + } + + /// 从字符串解析 ARN + pub fn parse(s: &str) -> Result { + // ARN 必须是格式 arn:minio:::: + if !s.starts_with("arn:minio:") { + return Err(format!("Invalid ARN {}", s).into()); + } + + let tokens: Vec<&str> = s.split(':').collect(); + if tokens.len() != 6 || tokens[4].is_empty() || tokens[5].is_empty() { + return Err(format!("Invalid ARN {}", s).into()); + } + + Ok(ARN { + arn_type: tokens[2].to_string(), + region: tokens[3].to_string(), + id: tokens[4].to_string(), + bucket: tokens[5].to_string(), + }) + } +} + +// 实现 `Display` trait,使得可以直接使用 `format!` 或 `{}` 输出 ARN +impl std::fmt::Display for ARN { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.to_string()) + } +} + +fn must_get_uuid() -> String { + Uuid::new_v4().to_string() + // match Uuid::new_v4() { + // Ok(uuid) => uuid.to_string(), + // Err(err) => { + // error!("Critical error: {}", err); + // panic!("Failed to generate UUID: {}", err); // Ensures similar behavior as Go's logger.CriticalIf + // } + // } +} +fn generate_arn(target: BucketTarget, depl_id: String) -> String { + let mut uuid: String = depl_id; + if uuid == "" { + uuid = must_get_uuid(); + } + + let arn: ARN = ARN { + arn_type: target.type_.unwrap(), + id: (uuid), + region: "us-east-1".to_string(), + bucket: (target.target_bucket), + }; + return arn.to_string(); +} + +// use std::collections::HashMap; +// use std::sync::{Arc, Mutex, RwLock}; +// use std::time::Duration; +// use tokio::time::timeout; +// use tokio::sync::RwLock as AsyncRwLock; +// use serde::Deserialize; +// use thiserror::Error; + +// #[derive(Debug, Clone, PartialEq)] +// pub enum BucketTargetType { +// ReplicationService, +// // Add other service types as needed +// } + +// impl BucketTargetType { +// pub fn is_valid(&self) -> bool { +// matches!(self, BucketTargetType::ReplicationService) +// } +// } + +// #[derive(Debug, Clone)] +// pub struct BucketTarget { +// pub arn: String, +// pub target_bucket: String, +// pub endpoint: String, +// pub credentials: Credentials, +// pub secure: bool, +// pub bandwidth_limit: Option, +// pub target_type: BucketTargetType, +// } + +// #[derive(Debug, Clone)] +// pub struct Credentials { +// pub access_key: String, +// pub secret_key: String, +// } + +// #[derive(Debug)] +// pub struct BucketTargetSys { +// targets_map: Arc>>>, +// arn_remotes_map: Arc>>, +// } + +// impl BucketTargetSys { +// pub fn new() -> Self { +// Self { +// targets_map: Arc::new(RwLock::new(HashMap::new())), +// arn_remotes_map: Arc::new(Mutex::new(HashMap::new())), +// } +// } + +// pub async fn set_target( +// &self, +// bucket: &str, +// tgt: &BucketTarget, +// update: bool, +// ) -> Result<(), SetTargetError> { +// if !tgt.target_type.is_valid() && !update { +// return Err(SetTargetError::InvalidTargetType(bucket.to_string())); +// } + +// let client = self.get_remote_target_client(tgt).await?; + +// // Validate if target credentials are OK +// let exists = client.bucket_exists(&tgt.target_bucket).await?; +// if !exists { +// return Err(SetTargetError::TargetNotFound(tgt.target_bucket.clone())); +// } + +// if tgt.target_type == BucketTargetType::ReplicationService { +// if !self.is_bucket_versioned(bucket).await { +// return Err(SetTargetError::SourceNotVersioned(bucket.to_string())); +// } + +// let versioning_config = client.get_bucket_versioning(&tgt.target_bucket).await?; +// if !versioning_config.is_enabled() { +// return Err(SetTargetError::TargetNotVersioned(tgt.target_bucket.clone())); +// } +// } + +// // Check if target is a MinIO server and alive +// let hc_result = timeout(Duration::from_secs(3), client.health_check(&tgt.endpoint)).await; +// match hc_result { +// Ok(Ok(true)) => {} // Server is alive +// Ok(Ok(false)) | Ok(Err(_)) | Err(_) => { +// return Err(SetTargetError::HealthCheckFailed(tgt.target_bucket.clone())); +// } +// } + +// // Lock and update target maps +// let mut targets_map = self.targets_map.write().await; +// let mut arn_remotes_map = self.arn_remotes_map.lock().unwrap(); + +// let targets = targets_map.entry(bucket.to_string()).or_default(); +// let mut found = false; + +// for existing_target in targets.iter_mut() { +// if existing_target.target_type == tgt.target_type { +// if existing_target.arn == tgt.arn { +// if !update { +// return Err(SetTargetError::TargetAlreadyExists(existing_target.target_bucket.clone())); +// } +// *existing_target = tgt.clone(); +// found = true; +// break; +// } + +// if existing_target.endpoint == tgt.endpoint { +// return Err(SetTargetError::TargetAlreadyExists(existing_target.target_bucket.clone())); +// } +// } +// } + +// if !found && !update { +// targets.push(tgt.clone()); +// } + +// arn_remotes_map.insert(tgt.arn.clone(), ArnTarget { client }); +// self.update_bandwidth_limit(bucket, &tgt.arn, tgt.bandwidth_limit).await; + +// Ok(()) +// } + +// async fn get_remote_target_client(&self, tgt: &BucketTarget) -> Result { +// // Mocked implementation for obtaining a remote client +// Ok(Client {}) +// } + +// async fn is_bucket_versioned(&self, bucket: &str) -> bool { +// // Mocked implementation for checking if a bucket is versioned +// true +// } + +// async fn update_bandwidth_limit( +// &self, +// bucket: &str, +// arn: &str, +// limit: Option, +// ) { +// // Mocked implementation for updating bandwidth limits +// } +// } + +// #[derive(Debug)] +// pub struct Client; + +// impl Client { +// pub async fn bucket_exists(&self, _bucket: &str) -> Result { +// Ok(true) // Mocked implementation +// } + +// pub async fn get_bucket_versioning( +// &self, +// _bucket: &str, +// ) -> Result { +// Ok(VersioningConfig { enabled: true }) +// } + +// pub async fn health_check(&self, _endpoint: &str) -> Result { +// Ok(true) // Mocked health check +// } +// } + +// #[derive(Debug, Clone)] +// pub struct ArnTarget { +// pub client: Client, +// } + +#[derive(Debug, Error)] +pub enum SetTargetError { + #[error("Invalid target type for bucket {0}")] + InvalidTargetType(String), + + #[error("Target bucket {0} not found")] + TargetNotFound(String), + + #[error("Source bucket {0} is not versioned")] + SourceNotVersioned(String), + + #[error("Target bucket {0} is not versioned")] + TargetNotVersioned(String), + + #[error("Health check failed for bucket {0}")] + HealthCheckFailed(String), + + #[error("Target bucket {0} already exists")] + TargetAlreadyExists(String), +} diff --git a/ecstore/src/cmd/bucketreplicationhandler.rs b/ecstore/src/cmd/bucketreplicationhandler.rs new file mode 100644 index 00000000..e69de29b diff --git a/ecstore/src/cmd/mod.rs b/ecstore/src/cmd/mod.rs new file mode 100644 index 00000000..dadec5ab --- /dev/null +++ b/ecstore/src/cmd/mod.rs @@ -0,0 +1,2 @@ +pub mod bucket_targets; +pub mod bucket_replication; \ No newline at end of file diff --git a/ecstore/src/disk/local.rs b/ecstore/src/disk/local.rs index ecb7f042..55e5118d 100644 --- a/ecstore/src/disk/local.rs +++ b/ecstore/src/disk/local.rs @@ -2430,7 +2430,7 @@ impl DiskAPI for LocalDisk { for info in obj_infos.iter() { let done = ScannerMetrics::time(ScannerMetric::ApplyVersion); let sz: usize; - (obj_deleted, sz) = item.apply_actions(info, &size_s).await; + (obj_deleted, sz) = item.apply_actions(info, &mut size_s).await; done(); if obj_deleted { diff --git a/ecstore/src/heal/data_scanner.rs b/ecstore/src/heal/data_scanner.rs index d8607ed1..2c5bd717 100644 --- a/ecstore/src/heal/data_scanner.rs +++ b/ecstore/src/heal/data_scanner.rs @@ -19,9 +19,9 @@ use super::{ heal_commands::{HealScanMode, HEAL_DEEP_SCAN, HEAL_NORMAL_SCAN}, }; use crate::{ - bucket::{versioning::VersioningApi, versioning_sys::BucketVersioningSys}, - heal::data_usage::DATA_USAGE_ROOT, + bucket::{metadata_sys, versioning::VersioningApi, versioning_sys::BucketVersioningSys}, cmd::bucket_replication::{ReplicationStatusType}, heal::data_usage::DATA_USAGE_ROOT }; +use crate::cmd::bucket_replication::queue_replication_heal; use crate::{ cache_value::metacache_set::{list_path_raw, ListPathRawOptions}, config::{ @@ -62,7 +62,7 @@ use tokio::{ }, time::sleep, }; -use tracing::{error, info}; +use tracing::{error, info, debug}; const DATA_SCANNER_SLEEP_PER_FOLDER: Duration = Duration::from_millis(1); // Time to wait between folders. const DATA_USAGE_UPDATE_DIR_CYCLES: u32 = 16; // Visit all folders every n cycles. @@ -550,13 +550,107 @@ impl ScannerItem { Ok(object_infos) } - pub async fn apply_actions(&self, oi: &ObjectInfo, _size_s: &SizeSummary) -> (bool, usize) { + pub async fn apply_actions(&mut self, oi: &ObjectInfo, _size_s: &mut SizeSummary) -> (bool, usize) { let done = ScannerMetrics::time(ScannerMetric::Ilm); //todo: lifecycle + info!("apply_actions {} {} {:?} {:?}", oi.bucket.clone(), oi.name.clone(), oi.version_id.clone(), oi.user_defined.clone()); + + // Create a mutable clone if you need to modify fields + let mut oi = oi.clone(); + oi.replication_status = ReplicationStatusType::from( + oi.user_defined + .as_ref() + .and_then(|map| map.get("x-amz-bucket-replication-status")) + .unwrap_or(&"PENDING".to_string()) + ); + info!("apply status is: {:?}", oi.replication_status); + self.heal_replication(&oi, _size_s).await; done(); (false, oi.size) } + + pub async fn heal_replication(&mut self, oi: &ObjectInfo, size_s: &mut SizeSummary) { + if oi.version_id.is_none() { + error!("heal_replication: no version_id or replication config {} {} {}", oi.bucket, oi.name, oi.version_id.is_none()); + return; + } + + + //let config = s3s::dto::ReplicationConfiguration{ role: todo!(), rules: todo!() }; + // Use the provided variable instead of borrowing self mutably. + let replication = match metadata_sys::get_replication_config(&oi.bucket).await { + Ok((replication, _)) => replication, + Err(_) => { + error!("heal_replication: failed to get replication config for bucket {} {}", oi.bucket, oi.name); + return; + } + }; + if replication.rules.is_empty() { + error!("heal_replication: no replication rules for bucket {} {}", oi.bucket, oi.name); + return; + } + if replication.role.is_empty() { + // error!("heal_replication: no replication role for bucket {} {}", oi.bucket, oi.name); + // return; + } + + //if oi.delete_marker || !oi.version_purge_status.is_empty() { + if oi.delete_marker { + error!("heal_replication: delete marker or version purge status {} {} {:?} {} {:?}", oi.bucket, oi.name, oi.version_id, oi.delete_marker, oi.version_purge_status); + return; + } + + + if oi.replication_status == ReplicationStatusType::Completed { + return; + } + + + info!("replication status is: {:?} and user define {:?}", oi.replication_status, oi.user_defined); + + let roi = queue_replication_heal(&oi.bucket, oi, &replication, 3).await; + + if roi.is_none() { + info!("not need heal {} {} {:?}", oi.bucket, oi.name, oi.version_id); + return; + } + + for (arn, tgt_status) in &roi.unwrap().target_statuses { + let tgt_size_s = size_s + .repl_target_stats + .entry(arn.clone()) + .or_default(); + + match tgt_status { + ReplicationStatusType::Pending => { + tgt_size_s.pending_count += 1; + tgt_size_s.pending_size += oi.size; + size_s.pending_count += 1; + size_s.pending_size += oi.size; + } + ReplicationStatusType::Failed => { + tgt_size_s.failed_count += 1; + tgt_size_s.failed_size += oi.size; + size_s.failed_count += 1; + size_s.failed_size += oi.size; + } + ReplicationStatusType::Completed | ReplicationStatusType::CompletedLegacy => { + tgt_size_s.replicated_count += 1; + tgt_size_s.replicated_size += oi.size; + size_s.replicated_count += 1; + size_s.replicated_size += oi.size; + } + _ => {} + } + } + + if matches!(oi.replication_status, ReplicationStatusType::Replica) { + size_s.replica_count += 1; + size_s.replica_size += oi.size; + } + } + } #[derive(Debug, Default)] diff --git a/ecstore/src/lib.rs b/ecstore/src/lib.rs index 55ecf320..246b18ac 100644 --- a/ecstore/src/lib.rs +++ b/ecstore/src/lib.rs @@ -32,6 +32,7 @@ pub mod store_list_objects; mod store_utils; pub mod utils; pub mod xhttp; +pub mod cmd; pub use global::new_object_layer_fn; pub use global::set_global_endpoints; diff --git a/ecstore/src/peer.rs b/ecstore/src/peer.rs index 89aa02be..7d68744d 100644 --- a/ecstore/src/peer.rs +++ b/ecstore/src/peer.rs @@ -1,3 +1,17 @@ +use async_trait::async_trait; +use futures::future::join_all; +use madmin::heal_commands::{HealDriveInfo, HealResultItem}; +use protos::node_service_time_out_client; +use protos::proto_gen::node_service::{ + DeleteBucketRequest, GetBucketInfoRequest, HealBucketRequest, ListBucketRequest, MakeBucketRequest, +}; +use regex::Regex; +use std::{collections::HashMap, fmt::Debug, sync::Arc}; +use tokio::sync::RwLock; +use tonic::Request; +use tracing::info; + +use crate::bucket::metadata_sys; use crate::disk::error::is_all_buckets_not_found; use crate::disk::{DiskAPI, DiskStore}; use crate::error::clone_err; @@ -15,19 +29,7 @@ use crate::{ endpoints::{EndpointServerPools, Node}, store_api::{BucketInfo, BucketOptions, DeleteBucketOptions, MakeBucketOptions}, }; -use async_trait::async_trait; use common::error::{Error, Result}; -use futures::future::join_all; -use madmin::heal_commands::{HealDriveInfo, HealResultItem}; -use protos::node_service_time_out_client; -use protos::proto_gen::node_service::{ - DeleteBucketRequest, GetBucketInfoRequest, HealBucketRequest, ListBucketRequest, MakeBucketRequest, -}; -use regex::Regex; -use std::{collections::HashMap, fmt::Debug, sync::Arc}; -use tokio::sync::RwLock; -use tonic::Request; -use tracing::info; type Client = Arc>; @@ -430,14 +432,17 @@ impl PeerS3Client for LocalPeerS3Client { } // TODO: reduceWriteQuorumErrs - - // debug!("get_bucket_info errs:{:?}", errs); + let mut versioned = false; + if let Ok(sys) = metadata_sys::get(bucket).await { + versioned = sys.versioning(); + } ress.iter() .find_map(|op| { op.as_ref().map(|v| BucketInfo { name: v.name.clone(), created: v.created, + versionning: versioned, ..Default::default() }) }) @@ -496,14 +501,17 @@ pub struct RemotePeerS3Client { } impl RemotePeerS3Client { - fn new(node: Option, pools: Option>) -> Self { + pub fn new(node: Option, pools: Option>) -> Self { let addr = node.as_ref().map(|v| v.url.to_string()).unwrap_or_default().to_string(); Self { node, pools, addr } } + pub fn get_addr(&self)->String { + return self.addr.clone(); + } } #[async_trait] -impl PeerS3Client for RemotePeerS3Client { +impl PeerS3Client for RemotePeerS3Client { fn get_pools(&self) -> Option> { self.pools.clone() } diff --git a/ecstore/src/store.rs b/ecstore/src/store.rs index 608f06be..51d04667 100644 --- a/ecstore/src/store.rs +++ b/ecstore/src/store.rs @@ -1374,7 +1374,7 @@ impl StorageAPI for ECStore { info.versionning = sys.versioning(); info.object_locking = sys.object_locking(); } - + Ok(info) } #[tracing::instrument(skip(self))] diff --git a/ecstore/src/store_api.rs b/ecstore/src/store_api.rs index 25ae7efa..6de6b7f1 100644 --- a/ecstore/src/store_api.rs +++ b/ecstore/src/store_api.rs @@ -1,3 +1,4 @@ +use crate::cmd::bucket_replication::{ReplicationStatusType, VersionPurgeStatusType}; use crate::heal::heal_ops::HealSequence; use crate::io::FileReader; use crate::store_utils::clean_metadata; @@ -175,7 +176,6 @@ impl FileInfo { let content_type = meta.get("content-type").cloned(); let content_encoding = meta.get("content-encoding").cloned(); let etag = meta.get("etag").cloned(); - (content_type, content_encoding, etag) } else { (None, None, None) @@ -686,6 +686,12 @@ pub struct ObjectInfo { pub inlined: bool, pub metadata_only: bool, pub version_only: bool, + pub replication_status_internal:String, + pub replication_status:ReplicationStatusType, + pub version_purge_status_internal: String, + pub version_purge_status: VersionPurgeStatusType, + pub checksum:Vec, + } impl Clone for ObjectInfo { @@ -714,8 +720,14 @@ impl Clone for ObjectInfo { inlined: self.inlined, metadata_only: self.metadata_only, version_only: self.version_only, + replication_status_internal: self.replication_status_internal.clone(), + replication_status: self.replication_status.clone(), + version_purge_status_internal: self.version_purge_status_internal.clone(), + version_purge_status: self.version_purge_status.clone(), + checksum:Default::default(), } } + } impl ObjectInfo { diff --git a/ecstore/src/xhttp.rs b/ecstore/src/xhttp.rs index 8c34d8c0..a5df9268 100644 --- a/ecstore/src/xhttp.rs +++ b/ecstore/src/xhttp.rs @@ -1,3 +1,4 @@ pub const AMZ_OBJECT_TAGGING: &str = "X-Amz-Tagging"; +pub const AMZ_BUCKET_REPLICATION_STATUS: &str = "X-Amz-Replication-Status"; pub const AMZ_STORAGE_CLASS: &str = "x-amz-storage-class"; pub const AMZ_DECODED_CONTENT_LENGTH: &str = "X-Amz-Decoded-Content-Length"; diff --git a/rustfs/Cargo.toml b/rustfs/Cargo.toml index 9351676d..7e6cf977 100644 --- a/rustfs/Cargo.toml +++ b/rustfs/Cargo.toml @@ -92,6 +92,26 @@ libsystemd.workspace = true [target.'cfg(all(target_os = "linux", target_env = "gnu"))'.dependencies] tikv-jemallocator = "0.6" +uuid = "1.12.1" +url.workspace = true +#admin = { path = "../api/admin" } +axum.workspace = true +matchit = "0.8.3" +shadow-rs = "0.38.0" +const-str = { version = "0.6.1", features = ["std", "proc"] } +atoi = "2.0.0" +serde_urlencoded = "0.7.1" +crypto = { path = "../crypto" } +iam = { path = "../iam" } +jsonwebtoken = "9.3.0" +tower-http = { version = "0.6.2", features = ["cors"] } +chrono.workspace = true +thiserror.workspace = true +regex = "1.11.1" +aws-sdk-s3 = "1.29.0" +include_dir = "0.7.4" +percent-encoding = "2.3.1" +urlencoding = "2.1.3" [build-dependencies] prost-build.workspace = true diff --git a/rustfs/src/admin/handlers.rs b/rustfs/src/admin/handlers.rs index 45ee477a..0b1690db 100644 --- a/rustfs/src/admin/handlers.rs +++ b/rustfs/src/admin/handlers.rs @@ -6,6 +6,11 @@ use bytes::Bytes; use common::error::Error as ec_Error; use ecstore::admin_server_info::get_server_info; use ecstore::bucket::versioning_sys::BucketVersioningSys; +use ecstore::bucket::metadata_sys::{self, get_replication_config}; +use ecstore::bucket::target::{BucketTarget}; +use ecstore::cmd::bucket_targets::{self, GLOBAL_Bucket_Target_Sys}; +//use ecstore::error::Error as ec_Error; +use crate::storage::error::to_s3_error; use ecstore::global::GLOBAL_ALlHealState; use ecstore::heal::data_usage::load_data_usage_from_backend; use ecstore::heal::heal_commands::HealOpts; @@ -16,13 +21,14 @@ use ecstore::peer::is_reserved_or_invalid_bucket; use ecstore::pools::{get_total_usable_capacity, get_total_usable_capacity_free}; use ecstore::store::is_valid_object_prefix; use ecstore::store_api::BucketOptions; -use ecstore::store_api::StorageAPI; +use ecstore::store_api::{StorageAPI}; use ecstore::utils::path::path_join; use futures::{Stream, StreamExt}; use http::{HeaderMap, Uri}; use hyper::StatusCode; use iam::get_global_action_cred; use iam::store::MappedPolicy; +// use lazy_static::lazy_static; use madmin::metrics::RealtimeMetrics; use madmin::utils::parse_duration; use matchit::Params; @@ -31,11 +37,13 @@ use policy::policy::action::S3Action; use policy::policy::default::DEFAULT_POLICIES; use policy::policy::Args; use policy::policy::BucketPolicy; +use percent_encoding::{percent_encode, AsciiSet, CONTROLS}; use s3s::header::CONTENT_TYPE; use s3s::stream::{ByteStream, DynByteStream}; use s3s::{s3_error, Body, S3Error, S3Request, S3Response, S3Result}; use s3s::{S3ErrorCode, StdError}; use serde::{Deserialize, Serialize}; +// use serde_json::to_vec; use std::collections::{HashMap, HashSet}; use std::path::PathBuf; use std::pin::Pin; @@ -47,6 +55,7 @@ use tokio::time::interval; use tokio::{select, spawn}; use tokio_stream::wrappers::ReceiverStream; use tracing::{error, info, warn}; +// use url::UrlQuery; pub mod event; pub mod group; @@ -57,6 +66,7 @@ pub mod service_account; pub mod sts; pub mod trace; pub mod user; +use urlencoding::decode; #[derive(Debug, Serialize, Default)] #[serde(rename_all = "PascalCase", default)] @@ -745,6 +755,278 @@ impl Operation for BackgroundHealStatusHandler { } } +fn extract_query_params(uri: &Uri) -> HashMap { + let mut params = HashMap::new(); + + if let Some(query) = uri.query() { + query.split('&').for_each(|pair| { + if let Some((key, value)) = pair.split_once('=') { + params.insert(key.to_string(), value.to_string()); + } + }); + } + + params +} + +//disable encrypto from client because minio use len 8 Nonce but rustfs use 12 len Nonce + +#[allow(dead_code)] +fn is_local_host(_host: String) -> bool { + return false; +} + +//awscurl --service s3 --region us-east-1 --access_key rustfsadmin --secret_key rustfsadmin "http://:9000/minio/admin/v3/replicationmetrics?bucket=1" +pub struct GetReplicationMetricsHandler {} +#[async_trait::async_trait] +impl Operation for GetReplicationMetricsHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + error!("GetReplicationMetricsHandler"); + let querys = extract_query_params(&_req.uri); + if let Some(bucket) = querys.get("bucket") { + error!("get bucket:{} metris", bucket); + } + //return Err(s3_error!(InvalidArgument, "Invalid bucket name")); + //Ok(S3Response::with_headers((StatusCode::OK, Body::from()), header)) + return Ok(S3Response::new((StatusCode::OK, Body::from("Ok".to_string())))); + } +} + +pub struct SetRemoteTargetHandler {} +#[async_trait::async_trait] +impl Operation for SetRemoteTargetHandler { + async fn call(&self, mut _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + //return Ok(S3Response::new((StatusCode::OK, Body::from("OK".to_string())))); + // println!("handle MetricsHandler, params: {:?}", _req.input); + info!("handle MetricsHandler, params: {:?}", _req.credentials); + let querys = extract_query_params(&_req.uri); + let Some(_cred) = _req.credentials else { + error!("credentials null"); + return Err(s3_error!(InvalidRequest, "get cred failed")); + }; + let _is_owner = true; // 先按true处理,后期根据请求决定 + let body = _req.input.store_all_unlimited().await.unwrap(); + //println!("body: {}", std::str::from_utf8(&body.clone()).unwrap()); + + //println!("bucket is:{}", bucket.clone()); + if let Some(bucket) = querys.get("bucket") { + if bucket.is_empty() { + println!("have bucket: {}", bucket); + return Ok(S3Response::new((StatusCode::OK, Body::from("fuck".to_string())))); + } + let Some(store) = new_object_layer_fn() else { + return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string())); + }; + + // let binfo:BucketInfo = store + // .get_bucket_info(bucket, &ecstore::store_api::BucketOptions::default()).await; + match store + .get_bucket_info(bucket, &ecstore::store_api::BucketOptions::default()) + .await + { + Ok(info) => { + println!("Bucket Info: {:?}", info); + if !info.versionning { + return Ok(S3Response::new((StatusCode::FORBIDDEN, Body::from("bucket need versioned".to_string())))); + } + } + Err(err) => { + eprintln!("Error: {:?}", err); + return Ok(S3Response::new((StatusCode::BAD_REQUEST, Body::from("empty bucket".to_string())))); + } + } + + let mut remote_target: BucketTarget = serde_json::from_slice(&body).map_err(|arg0| to_s3_error(arg0.into()))?; // 错误会被传播 + remote_target.source_bucket = bucket.clone(); + + info!("remote target {} And arn is:", remote_target.source_bucket.clone()); + + if let Some(val) = remote_target.arn.clone() { + info!("arn is {}", val); + } + + if let Some(sys) = GLOBAL_Bucket_Target_Sys.get() { + let (arn, exist) = sys.get_remote_arn(&bucket, Some(&remote_target), "").await; + info!("exist: {} {}", exist, arn.clone().unwrap_or_default()); + if exist && arn.is_some() { + let jsonarn = serde_json::to_string(&arn).expect("failed to serialize"); + //Ok(S3Response::new) + return Ok(S3Response::new((StatusCode::OK, Body::from(jsonarn)))); + } else { + remote_target.arn = arn; + match sys.set_target(bucket, &remote_target, false, false).await { + Ok(_) => { + { + //todo 各种持久化的工作 + let targets = sys.list_targets(Some(&bucket), None).await; + info!("targets is {}", targets.len()); + match serde_json::to_vec(&targets) { + Ok(json) => { + //println!("json is:{:?}", json.clone().to_ascii_lowercase()); + //metadata_sys::GLOBAL_BucketMetadataSys:: + //BUCKET_TARGETS_FILE: &str = "bucket-targets.json" + let _ = metadata_sys::update(bucket, "bucket-targets.json", json).await; + // if let Err(err) = metadata_sys::GLOBAL_BucketMetadataSys.get(). + // .update(ctx, bucket, "bucketTargetsFile", tgt_bytes) + // .await + // { + // write_error_response(ctx, &err)?; + // return Err(err); + // } + } + Err(e) => { + error!("序列化失败{}", e); + } + } + } + + let jsonarn = serde_json::to_string(&remote_target.arn.clone()).expect("failed to serialize"); + return Ok(S3Response::new((StatusCode::OK, Body::from(jsonarn)))); + } + Err(e) => { + error!("set target error {}", e); + return Ok(S3Response::new(( + StatusCode::BAD_REQUEST, + Body::from("remote target not ready".to_string()), + ))); + } + } + } + } else { + error!("GLOBAL_BUCKET _TARGET_SYS is not initialized"); + return Err(S3Error::with_message( + S3ErrorCode::InternalError, + "GLOBAL_BUCKET_TARGET_SYS is not initialized".to_string(), + )); + } + } + // return Err(s3_error!(InvalidArgument)); + return Ok(S3Response::new((StatusCode::OK, Body::from("Ok".to_string())))); + } +} + +pub struct ListRemoteTargetHandler {} +#[async_trait::async_trait] +impl Operation for ListRemoteTargetHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + warn!("list GetRemoteTargetHandler, params: {:?}", _req.credentials); + + let querys = extract_query_params(&_req.uri); + let Some(_cred) = _req.credentials else { + error!("credentials null"); + return Err(s3_error!(InvalidRequest, "get cred failed")); + }; + + if let Some(bucket) = querys.get("bucket") { + if bucket.is_empty() { + error!("bucket parameter is empty"); + return Ok(S3Response::new(( + StatusCode::BAD_REQUEST, + Body::from("Bucket parameter is required".to_string()), + ))); + } + + let Some(store) = new_object_layer_fn() else { + return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not initialized".to_string())); + }; + + match store + .get_bucket_info(bucket, &ecstore::store_api::BucketOptions::default()) + .await + { + Ok(info) => { + println!("Bucket Info: {:?}", info); + if !info.versionning { + return Ok(S3Response::new(( + StatusCode::FORBIDDEN, + Body::from("Bucket needs versioning".to_string()), + ))); + } + } + Err(err) => { + eprintln!("Error fetching bucket info: {:?}", err); + return Ok(S3Response::new((StatusCode::BAD_REQUEST, Body::from("Invalid bucket".to_string())))); + } + } + + if let Some(sys) = GLOBAL_Bucket_Target_Sys.get() { + let targets = sys.list_targets(Some(&bucket), None).await; + error!("target sys len {}", targets.len()); + if targets.is_empty() { + return Ok(S3Response::new(( + StatusCode::NOT_FOUND, + Body::from("No remote targets found".to_string()), + ))); + } + + let json_targets = serde_json::to_string(&targets).map_err(|e| { + error!("Serialization error: {}", e); + S3Error::with_message(S3ErrorCode::InternalError, "Failed to serialize targets".to_string()) + })?; + + return Ok(S3Response::new((StatusCode::OK, Body::from(json_targets)))); + } else { + println!("GLOBAL_BUCKET_TARGET_SYS is not initialized"); + return Err(S3Error::with_message( + S3ErrorCode::InternalError, + "GLOBAL_BUCKET_TARGET_SYS is not initialized".to_string(), + )); + } + } + + println!("Bucket parameter missing in request"); + Ok(S3Response::new(( + StatusCode::BAD_REQUEST, + Body::from("Bucket parameter is required".to_string()), + ))) + //return Err(s3_error!(NotImplemented)); + } +} +const COLON: AsciiSet = CONTROLS.add(b':'); +pub struct RemoveRemoteTargetHandler {} +#[async_trait::async_trait] +impl Operation for RemoveRemoteTargetHandler { + async fn call(&self, _req: S3Request, _params: Params<'_, '_>) -> S3Result> { + error!("remove remote target called"); + let querys = extract_query_params(&_req.uri); + + if let Some(arnstr) = querys.get("arn") { + if let Some(bucket) = querys.get("bucket") { + if bucket.is_empty() { + error!("bucket parameter is empty"); + return Ok(S3Response::new((StatusCode::NOT_FOUND, Body::from("bucket not found".to_string())))); + } + let _arn = bucket_targets::ARN::parse(&arnstr); + + match get_replication_config(&bucket).await { + Ok((conf, _ts)) => { + for ru in conf.rules { + let encoded = percent_encode(ru.destination.bucket.as_bytes(), &COLON); + let encoded_str = encoded.to_string(); + if *arnstr == encoded_str { + error!("target in use"); + return Ok(S3Response::new((StatusCode::FORBIDDEN, Body::from("Ok".to_string())))); + } + info!("bucket: {} and arn str is {} ", encoded_str, arnstr); + } + } + Err(err) => { + error!("get replication config err: {}", err); + return Ok(S3Response::new((StatusCode::NOT_FOUND, Body::from(err.to_string())))); + } + } + //percent_decode_str(&arnstr); + let decoded_str = decode(arnstr).unwrap(); + error!("need delete target is {}" , decoded_str); + bucket_targets::remove_bucket_target(bucket, arnstr).await; + } + } + //return Err(s3_error!(InvalidArgument, "Invalid bucket name")); + //Ok(S3Response::with_headers((StatusCode::OK, Body::from()), header)) + return Ok(S3Response::new((StatusCode::OK, Body::from("Ok".to_string())))); + } +} + #[cfg(test)] mod test { use ecstore::heal::heal_commands::HealOpts; diff --git a/rustfs/src/admin/mod.rs b/rustfs/src/admin/mod.rs index f0229f20..34041a10 100644 --- a/rustfs/src/admin/mod.rs +++ b/rustfs/src/admin/mod.rs @@ -11,12 +11,14 @@ use handlers::{ sts, user, }; +use handlers::{ListRemoteTargetHandler, SetRemoteTargetHandler, RemoveRemoteTargetHandler, GetReplicationMetricsHandler}; use hyper::Method; use router::{AdminOperation, S3Router}; use rpc::regist_rpc_route; use s3s::route::S3Route; const ADMIN_PREFIX: &str = "/rustfs/admin"; +const MINIO_ADMIN_PREFIX: &str = "/minio/admin"; pub fn make_admin_route() -> Result { let mut r: S3Router = S3Router::new(); @@ -228,6 +230,55 @@ fn register_user_route(r: &mut S3Router) -> Result<()> { AdminOperation(&AddServiceAccount {}), )?; + r.insert( + Method::GET, + format!("{}{}", MINIO_ADMIN_PREFIX, "/v3/list-remote-targets").as_str(), + AdminOperation(&ListRemoteTargetHandler {}), + )?; + + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/list-remote-targets").as_str(), + AdminOperation(&ListRemoteTargetHandler {}), + )?; + + r.insert( + Method::GET, + format!("{}{}", MINIO_ADMIN_PREFIX, "/v3/replicationmetrics").as_str(), + AdminOperation(&GetReplicationMetricsHandler {}), + )?; + + r.insert( + Method::GET, + format!("{}{}", ADMIN_PREFIX, "/v3/replicationmetrics").as_str(), + AdminOperation(&GetReplicationMetricsHandler {}), + )?; + + + r.insert( + Method::PUT, + format!("{}{}", MINIO_ADMIN_PREFIX, "/v3/set-remote-target").as_str(), + AdminOperation(&SetRemoteTargetHandler {}), + )?; + r.insert( + Method::PUT, + format!("{}{}", ADMIN_PREFIX, "/v3/set-remote-target").as_str(), + AdminOperation(&SetRemoteTargetHandler {}), + )?; + + + r.insert( + Method::DELETE, + format!("{}{}", MINIO_ADMIN_PREFIX, "/v3/remove-remote-target").as_str(), + AdminOperation(&RemoveRemoteTargetHandler {}), + )?; + + r.insert( + Method::DELETE, + format!("{}{}", ADMIN_PREFIX, "/v3/remove-remote-target").as_str(), + AdminOperation(&RemoveRemoteTargetHandler {}), + )?; + // list-canned-policies?bucket=xxx r.insert( Method::GET, diff --git a/rustfs/src/admin/router.rs b/rustfs/src/admin/router.rs index d19d4da2..c5086538 100644 --- a/rustfs/src/admin/router.rs +++ b/rustfs/src/admin/router.rs @@ -16,6 +16,7 @@ use s3s::S3Result; use super::rpc::RPC_PREFIX; use super::ADMIN_PREFIX; +use super::MINIO_ADMIN_PREFIX; pub struct S3Router { router: Router, @@ -64,7 +65,7 @@ where } } - uri.path().starts_with(ADMIN_PREFIX) || uri.path().starts_with(RPC_PREFIX) + uri.path().starts_with(ADMIN_PREFIX) || uri.path().starts_with(RPC_PREFIX) || uri.path().starts_with(MINIO_ADMIN_PREFIX) } async fn call(&self, req: S3Request) -> S3Result> { diff --git a/rustfs/src/grpc.rs b/rustfs/src/grpc.rs index 1c0ab803..88396ca3 100644 --- a/rustfs/src/grpc.rs +++ b/rustfs/src/grpc.rs @@ -240,6 +240,8 @@ impl Node for NodeService { })); } }; + + println!("bucket info {}", bucket_info.clone()); Ok(tonic::Response::new(GetBucketInfoResponse { success: true, bucket_info, @@ -247,6 +249,8 @@ impl Node for NodeService { })) } + // println!("vuc") + Err(err) => Ok(tonic::Response::new(GetBucketInfoResponse { success: false, bucket_info: String::new(), diff --git a/rustfs/src/main.rs b/rustfs/src/main.rs index c0abb79a..ea47a355 100644 --- a/rustfs/src/main.rs +++ b/rustfs/src/main.rs @@ -17,6 +17,7 @@ use crate::server::{wait_for_shutdown, ServiceState, ServiceStateManager, Shutdo use bytes::Bytes; use chrono::Datelike; use clap::Parser; +use ecstore::cmd::bucket_replication::init_bucket_replication_pool; use common::{ error::{Error, Result}, globals::set_global_addr, @@ -534,6 +535,11 @@ async fn run(opt: config::Opt) -> Result<()> { init_console_cfg(local_ip, server_port); + print_server_info(); + init_bucket_replication_pool().await; + + init_console_cfg(local_ip, server_port); + print_server_info(); if opt.console_enable { diff --git a/rustfs/src/storage/ecfs.rs b/rustfs/src/storage/ecfs.rs index 8eab14a3..07f445bd 100644 --- a/rustfs/src/storage/ecfs.rs +++ b/rustfs/src/storage/ecfs.rs @@ -4,14 +4,12 @@ use super::options::extract_metadata; use super::options::put_opts; use crate::auth::get_condition_values; use crate::storage::access::ReqInfo; -use crate::storage::error::to_s3_error; -use crate::storage::options::copy_dst_opts; -use crate::storage::options::copy_src_opts; -use crate::storage::options::{extract_metadata_from_mime, get_opts}; use api::query::Context; use api::query::Query; use api::server::dbms::DatabaseManagerSystem; use bytes::Bytes; +use chrono::DateTime; +use chrono::Utc; use common::error::Result; use datafusion::arrow::csv::WriterBuilder as CsvWriterBuilder; use datafusion::arrow::json::writer::JsonArray; @@ -31,6 +29,9 @@ use ecstore::bucket::tagging::decode_tags; use ecstore::bucket::tagging::encode_tags; use ecstore::bucket::versioning_sys::BucketVersioningSys; use ecstore::io::READ_BUFFER_SIZE; +use ecstore::cmd::bucket_replication::get_must_replicate_options; +use ecstore::cmd::bucket_replication::must_replicate; +use ecstore::cmd::bucket_replication::schedule_replication; use ecstore::new_object_layer_fn; use ecstore::store_api::BucketOptions; use ecstore::store_api::CompletePart; @@ -43,6 +44,7 @@ use ecstore::store_api::ObjectOptions; use ecstore::store_api::ObjectToDelete; use ecstore::store_api::PutObjReader; use ecstore::store_api::StorageAPI; +// use ecstore::store_api::RESERVED_METADATA_PREFIX; use ecstore::store_api::RESERVED_METADATA_PREFIX_LOWER; use ecstore::utils::path::path_join_buf; use ecstore::utils::xml; @@ -51,6 +53,7 @@ use futures::pin_mut; use futures::{Stream, StreamExt}; use http::HeaderMap; use lazy_static::lazy_static; +use tracing::debug; use policy::auth; use policy::policy::action::Action; use policy::policy::action::S3Action; @@ -78,13 +81,19 @@ use tokio_stream::wrappers::ReceiverStream; use tokio_tar::Archive; use tokio_util::io::ReaderStream; use tokio_util::io::StreamReader; -use tracing::debug; use tracing::error; use tracing::info; use tracing::warn; use transform_stream::AsyncTryStream; use uuid::Uuid; +use crate::storage::error::to_s3_error; +use crate::storage::options::copy_dst_opts; +use crate::storage::options::copy_src_opts; +use crate::storage::options::{extract_metadata_from_mime, get_opts}; +use ecstore::cmd::bucket_replication::ReplicationStatusType; +use ecstore::cmd::bucket_replication::ReplicationType; + macro_rules! try_ { ($result:expr) => { match $result { @@ -924,6 +933,7 @@ impl S3 for FS { return self.put_object_extract(req).await; } + info!("put object"); let input = req.input; if let Some(ref storage_class) = input.storage_class { @@ -976,10 +986,29 @@ impl S3 for FS { metadata.insert(xhttp::AMZ_OBJECT_TAGGING.to_owned(), tags); } - let opts: ObjectOptions = put_opts(&bucket, &key, version_id, &req.headers, Some(metadata)) + let mt = metadata.clone(); + let mt2 = metadata.clone(); + + let opts: ObjectOptions = put_opts(&bucket, &key, version_id, &req.headers, Some(mt)) .await .map_err(to_s3_error)?; + let repoptions = get_must_replicate_options(&mt2, "", ReplicationStatusType::Unknown, ReplicationType::ObjectReplicationType , &opts); + + let dsc = must_replicate(&bucket, &key, &repoptions).await; + warn!("dsc {}", &dsc.replicate_any().clone()); + if dsc.replicate_any() { + let k = format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-timestamp"); + let now: DateTime = Utc::now(); + let formatted_time = now.to_rfc3339(); + metadata.insert(k, formatted_time); + let k = format!("{}{}", RESERVED_METADATA_PREFIX_LOWER, "replication-status"); + metadata.insert(k, dsc.pending_status()); + } + + + + debug!("put_object opts {:?}", &opts); let obj_info = store @@ -987,9 +1016,17 @@ impl S3 for FS { .await .map_err(to_s3_error)?; - let e_tag = obj_info.etag; + let e_tag = obj_info.etag.clone(); - // store.put_object(bucket, object, data, opts); + + let repoptions = get_must_replicate_options(&mt2, "", ReplicationStatusType::Unknown, ReplicationType::ObjectReplicationType , &opts); + + let dsc = must_replicate(&bucket, &key, &repoptions).await; + + if dsc.replicate_any() { + let objectlayer = new_object_layer_fn(); + schedule_replication(obj_info, objectlayer.unwrap(), dsc, 1).await; + } let output = PutObjectOutput { e_tag, @@ -1152,17 +1189,30 @@ impl S3 for FS { return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string())); }; - let oi = store + let obj_info = store .complete_multipart_upload(&bucket, &key, &upload_id, uploaded_parts, opts) .await .map_err(to_s3_error)?; let output = CompleteMultipartUploadOutput { - bucket: Some(bucket), - key: Some(key), - e_tag: oi.etag, + bucket: Some(bucket.clone()), + key: Some(key.clone()), + e_tag:obj_info.etag.clone(), + location: Some("us-east-1".to_string()), ..Default::default() }; + + + let mt2 = HashMap::new(); + let repoptions = get_must_replicate_options(&mt2, "", ReplicationStatusType::Unknown, ReplicationType::ObjectReplicationType , &opts); + + let dsc = must_replicate(&bucket, &key, &repoptions).await; + + if dsc.replicate_any() { + warn!("need multipart replication"); + let objectlayer = new_object_layer_fn(); + schedule_replication(obj_info, objectlayer.unwrap(), dsc, 1).await; + } Ok(S3Response::new(output)) } @@ -1725,17 +1775,40 @@ impl S3 for FS { .await .map_err(to_s3_error)?; - let replication_configuration = match metadata_sys::get_replication_config(&bucket).await { + let rcfg = match metadata_sys::get_replication_config(&bucket).await { Ok((cfg, _created)) => Some(cfg), Err(err) => { - warn!("get_object_lock_config err {:?}", err); - None + error!("get_replication_config err {:?}", err); + return Err(to_s3_error(err)); } }; - Ok(S3Response::new(GetBucketReplicationOutput { - replication_configuration, - })) + if let None = rcfg { + return Err(S3Error::with_message(S3ErrorCode::NoSuchBucket, "replication not found".to_string())); + } + + + + // Ok(S3Response::new(GetBucketReplicationOutput { + // replication_configuration: rcfg, + // })) + + + if rcfg.is_some() { + Ok(S3Response::new(GetBucketReplicationOutput { + replication_configuration: rcfg, + })) + } else { + let rep = ReplicationConfiguration{ + role: "".to_string(), + rules: vec![], + }; + Ok(S3Response::new(GetBucketReplicationOutput { + replication_configuration: Some(rep), + })) + } + + } async fn put_bucket_replication( @@ -1747,6 +1820,7 @@ impl S3 for FS { replication_configuration, .. } = req.input; + warn!("put bucket replication"); let Some(store) = new_object_layer_fn() else { return Err(S3Error::with_message(S3ErrorCode::InternalError, "Not init".to_string())); @@ -1786,6 +1860,7 @@ impl S3 for FS { .map_err(to_s3_error)?; // TODO: remove targets + error!("delete bucket"); Ok(S3Response::new(DeleteBucketReplicationOutput::default())) } diff --git a/rustfs/src/storage/error.rs b/rustfs/src/storage/error.rs index 1678c05d..e0452817 100644 --- a/rustfs/src/storage/error.rs +++ b/rustfs/src/storage/error.rs @@ -1,5 +1,5 @@ use common::error::Error; -use ecstore::{disk::error::is_err_file_not_found, store_err::StorageError}; +use ecstore::{bucket::error::BucketMetadataError, disk::error::is_err_file_not_found, store_err::StorageError}; use s3s::{s3_error, S3Error, S3ErrorCode}; pub fn to_s3_error(err: Error) -> S3Error { if let Some(storage_err) = err.downcast_ref::() { @@ -80,6 +80,15 @@ pub fn to_s3_error(err: Error) -> S3Error { StorageError::DoneForNow => s3_error!(InternalError, "DoneForNow"), }; } + //需要添加 not found bucket replication config + if let Some(meta_err) = err.downcast_ref::() { + return match meta_err { + BucketMetadataError::BucketReplicationConfigNotFound => { + S3Error::with_message(S3ErrorCode::ReplicationConfigurationNotFoundError, format!("{}", err)) + } + _ => S3Error::with_message(S3ErrorCode::InternalError, format!("{}", err)), // 处理其他情况 + }; + } if is_err_file_not_found(&err) { return S3Error::with_message(S3ErrorCode::NoSuchKey, format!(" ec err {}", err));