From e0c5ed2a449cd5b90923ce75db93d17095752652 Mon Sep 17 00:00:00 2001 From: Patrick Siegl <3261314+psiegl@users.noreply.github.com> Date: Fri, 14 Nov 2025 19:04:17 +0100 Subject: [PATCH 1/7] Add zenoh as transport --- Cargo.lock | 2539 ++++++++++++++--- Cargo.toml | 14 +- ZENOH.md | 157 + crates/cli/Cargo.toml | 4 +- crates/cli/src/lib.rs | 2 + crates/cli/src/zenoh.rs | 10 + crates/test/Cargo.toml | 5 +- crates/test/src/lib.rs | 51 + crates/transport-zenoh/Cargo.toml | 33 + crates/transport-zenoh/src/lib.rs | 1439 ++++++++++ crates/wasmtime-cli/Cargo.toml | 2 + crates/wasmtime-cli/src/lib.rs | 14 +- crates/wasmtime-cli/src/zenoh.rs | 98 + .../rust/hello-component-zclient/Cargo.toml | 13 + .../rust/hello-component-zclient/src/main.rs | 19 + .../hello-component-zclient/wit/deps.lock | 4 + .../hello-component-zclient/wit/deps.toml | 1 + .../wit/deps/hello/hello.wit | 13 + .../hello-component-zclient/wit/world.wit | 5 + examples/rust/hello-zenoh-client/Cargo.toml | 27 + examples/rust/hello-zenoh-client/src/main.rs | 81 + .../rust/hello-zenoh-client/wit/deps.lock | 4 + .../rust/hello-zenoh-client/wit/deps.toml | 1 + .../wit/deps/hello/hello.wit | 43 + .../rust/hello-zenoh-client/wit/world.wit | 5 + examples/rust/hello-zenoh-server/Cargo.toml | 34 + examples/rust/hello-zenoh-server/src/main.rs | 101 + .../rust/hello-zenoh-server/wit/deps.lock | 4 + .../rust/hello-zenoh-server/wit/deps.toml | 1 + .../wit/deps/hello/hello.wit | 43 + .../rust/hello-zenoh-server/wit/world.wit | 5 + examples/rust/streams-zenoh-client/Cargo.toml | 35 + .../rust/streams-zenoh-client/src/main.rs | 87 + .../rust/streams-zenoh-client/wit/deps.lock | 4 + .../rust/streams-zenoh-client/wit/deps.toml | 1 + .../wit/deps/streams/streams.wit | 17 + .../rust/streams-zenoh-client/wit/world.wit | 5 + examples/rust/streams-zenoh-server/Cargo.toml | 39 + .../rust/streams-zenoh-server/src/main.rs | 119 + .../rust/streams-zenoh-server/wit/deps.lock | 4 + .../rust/streams-zenoh-server/wit/deps.toml | 1 + .../wit/deps/streams/streams.wit | 17 + .../rust/streams-zenoh-server/wit/world.wit | 5 + tests/rust.rs | 42 + zenoh_conf.json5 | 7 + zenoh_conf.json5.template | 6 + 46 files changed, 4815 insertions(+), 346 deletions(-) create mode 100644 ZENOH.md create mode 100644 crates/cli/src/zenoh.rs create mode 100644 crates/transport-zenoh/Cargo.toml create mode 100644 crates/transport-zenoh/src/lib.rs create mode 100644 crates/wasmtime-cli/src/zenoh.rs create mode 100644 examples/rust/hello-component-zclient/Cargo.toml create mode 100644 examples/rust/hello-component-zclient/src/main.rs create mode 100644 examples/rust/hello-component-zclient/wit/deps.lock create mode 100644 examples/rust/hello-component-zclient/wit/deps.toml create mode 100644 examples/rust/hello-component-zclient/wit/deps/hello/hello.wit create mode 100644 examples/rust/hello-component-zclient/wit/world.wit create mode 100644 examples/rust/hello-zenoh-client/Cargo.toml create mode 100644 examples/rust/hello-zenoh-client/src/main.rs create mode 100644 examples/rust/hello-zenoh-client/wit/deps.lock create mode 100644 examples/rust/hello-zenoh-client/wit/deps.toml create mode 100644 examples/rust/hello-zenoh-client/wit/deps/hello/hello.wit create mode 100644 examples/rust/hello-zenoh-client/wit/world.wit create mode 100644 examples/rust/hello-zenoh-server/Cargo.toml create mode 100644 examples/rust/hello-zenoh-server/src/main.rs create mode 100644 examples/rust/hello-zenoh-server/wit/deps.lock create mode 100644 examples/rust/hello-zenoh-server/wit/deps.toml create mode 100644 examples/rust/hello-zenoh-server/wit/deps/hello/hello.wit create mode 100644 examples/rust/hello-zenoh-server/wit/world.wit create mode 100644 examples/rust/streams-zenoh-client/Cargo.toml create mode 100644 examples/rust/streams-zenoh-client/src/main.rs create mode 100644 examples/rust/streams-zenoh-client/wit/deps.lock create mode 100644 examples/rust/streams-zenoh-client/wit/deps.toml create mode 100644 examples/rust/streams-zenoh-client/wit/deps/streams/streams.wit create mode 100644 examples/rust/streams-zenoh-client/wit/world.wit create mode 100644 examples/rust/streams-zenoh-server/Cargo.toml create mode 100644 examples/rust/streams-zenoh-server/src/main.rs create mode 100644 examples/rust/streams-zenoh-server/wit/deps.lock create mode 100644 examples/rust/streams-zenoh-server/wit/deps.toml create mode 100644 examples/rust/streams-zenoh-server/wit/deps/streams/streams.wit create mode 100644 examples/rust/streams-zenoh-server/wit/world.wit create mode 100644 zenoh_conf.json5 create mode 100644 zenoh_conf.json5.template diff --git a/Cargo.lock b/Cargo.lock index 59855ec95..80d5d3b6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,36 @@ dependencies = [ "gimli", ] +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[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 = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.4", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.4" @@ -99,9 +129,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" [[package]] name = "arbitrary" @@ -111,9 +141,24 @@ checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" [[package]] name = "arc-swap" -version = "1.7.1" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9f3647c145568cec02c42054e07bdf9a5a698e15b466fb2341bfc393cd24aa5" +dependencies = [ + "rustversion", +] + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "ascii" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" +checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16" [[package]] name = "asn1-rs" @@ -127,7 +172,7 @@ dependencies = [ "nom", "num-traits", "rusticata-macros", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", ] @@ -139,7 +184,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", "synstructure", ] @@ -151,7 +196,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -199,7 +244,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -287,9 +332,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.1" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e050f626429857a27ddccb31e0aca21356bfa709c04041aefddac081a8f068a" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "beef" @@ -305,9 +350,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +dependencies = [ + "serde_core", +] [[package]] name = "block-buffer" @@ -320,13 +368,19 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" dependencies = [ "allocator-api2", ] +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.11.1" @@ -356,7 +410,7 @@ checksum = "20a158160765c6a7d0d8c072a53d772e4cb243f38b04bfcf6b4939cfbe7482e7" dependencies = [ "cap-primitives", "cap-std", - "rustix 1.0.8", + "rustix 1.1.3", "smallvec", ] @@ -372,7 +426,7 @@ dependencies = [ "io-lifetimes", "ipnet", "maybe-owned", - "rustix 1.0.8", + "rustix 1.1.3", "rustix-linux-procfs", "windows-sys 0.59.0", "winx", @@ -397,7 +451,7 @@ dependencies = [ "cap-primitives", "io-extras", "io-lifetimes", - "rustix 1.0.8", + "rustix 1.1.3", ] [[package]] @@ -410,7 +464,7 @@ dependencies = [ "cap-primitives", "iana-time-zone", "once_cell", - "rustix 1.0.8", + "rustix 1.1.3", "winx", ] @@ -422,9 +476,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.49" +version = "1.2.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90583009037521a116abf44494efecd645ba48b6622457080f080b85544e2215" +checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", "jobserver", @@ -450,6 +504,24 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chrono" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +dependencies = [ + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + +[[package]] +name = "chunked_transfer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901" + [[package]] name = "ciborium" version = "0.2.2" @@ -477,11 +549,21 @@ dependencies = [ "half", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "clap" -version = "4.5.57" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6899ea499e3fb9305a65d5ebf6e3d2248c5fab291f300ad0a704fbe142eae31a" +checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806" dependencies = [ "clap_builder", "clap_derive", @@ -489,9 +571,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.57" +version = "4.5.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b12c8b680195a62a8364d16b8447b01b6c2c8f9aaf68bee653be34d4245e238" +checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2" dependencies = [ "anstream", "anstyle", @@ -508,14 +590,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] name = "clap_lex" -version = "0.7.6" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" [[package]] name = "cobs" @@ -523,7 +605,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.17", + "thiserror 2.0.18", ] [[package]] @@ -540,6 +622,15 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "colored" +version = "3.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faf9468729b8cbcea668e36183cb69d317348c2e08e994829fb56ebfdfbaac34" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "combine" version = "4.6.7" @@ -554,12 +645,41 @@ dependencies = [ "tokio-util", ] +[[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 = "const-oid" version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" +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 = "core-foundation" version = "0.9.4" @@ -789,6 +909,28 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[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-deque" version = "0.8.6" @@ -808,6 +950,15 @@ 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" @@ -853,14 +1004,49 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.116", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.116", ] [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" [[package]] name = "debugid" @@ -898,9 +1084,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" +checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" dependencies = [ "powerfmt", "serde_core", @@ -914,6 +1100,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -926,6 +1113,37 @@ dependencies = [ "dirs-sys-next", ] +[[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-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[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 0.5.2", + "windows-sys 0.61.2", +] + [[package]] name = "dirs-sys-next" version = "0.1.2" @@ -933,7 +1151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.6", "winapi", ] @@ -945,9 +1163,15 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + [[package]] name = "ed25519" version = "2.2.3" @@ -988,6 +1212,12 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "encoding_rs" version = "0.8.35" @@ -999,18 +1229,18 @@ dependencies = [ [[package]] name = "env_filter" -version = "0.1.4" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf3c259d255ca70051b30e2e95b5446cdb8949ac4cd22c0d7fd634d89f568e2" +checksum = "7a1c3cc8e57274ec99de65301228b537f1e4eedc1b8e0f9411c6caac8ae7308f" dependencies = [ "log", ] [[package]] name = "env_logger" -version = "0.11.8" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c863f0904021b108aa8b2f55046443e6b1ebde8fd4a15c399893aae4fa069f" +checksum = "b2daee4ea451f429a58296525ddf28b45a3b64f1acf6587e2067437bb11e218d" dependencies = [ "anstream", "anstyle", @@ -1034,6 +1264,27 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "event-listener" +version = "5.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "eyre" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +dependencies = [ + "indenter", + "once_cell", +] + [[package]] name = "fallible-iterator" version = "0.3.0" @@ -1053,7 +1304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 1.0.8", + "rustix 1.1.3", "windows-sys 0.59.0", ] @@ -1065,9 +1316,37 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "find-msvc-tools" -version = "0.1.5" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "fixedbitset" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "flume" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin 0.9.8", +] [[package]] name = "fnv" @@ -1081,6 +1360,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -1097,15 +1382,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a" dependencies = [ "io-lifetimes", - "rustix 1.0.8", + "rustix 1.1.3", "windows-sys 0.59.0", ] [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -1118,9 +1403,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -1128,15 +1413,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -1145,38 +1430,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -1186,7 +1471,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -1196,7 +1480,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "25234f20a3ec0a962a61770cfe39ecf03cb529a6e474ad8cff025ed497eda557" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "debugid", "rustc-hash", "serde", @@ -1216,9 +1500,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", @@ -1241,6 +1525,19 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", + "wasip3", +] + [[package]] name = "gimli" version = "0.32.3" @@ -1248,10 +1545,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" dependencies = [ "fallible-iterator", - "indexmap", + "indexmap 2.13.0", "stable_deref_trait", ] +[[package]] +name = "git-version" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ad568aa3db0fcbc81f2f116137f263d7304f512a1209b35b85150d3ef88ad19" +dependencies = [ + "git-version-macro", +] + +[[package]] +name = "git-version-macro" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.116", +] + [[package]] name = "h2" version = "0.3.27" @@ -1264,7 +1581,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -1273,9 +1590,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" dependencies = [ "atomic-waker", "bytes", @@ -1283,7 +1600,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.4.0", - "indexmap", + "indexmap 2.13.0", "slab", "tokio", "tokio-util", @@ -1301,13 +1618,29 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + [[package]] name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "foldhash", + "foldhash 0.1.5", "serde", ] @@ -1316,6 +1649,21 @@ name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" +dependencies = [ + "byteorder", + "num-traits", +] [[package]] name = "heck" @@ -1367,7 +1715,14 @@ dependencies = [ ] [[package]] -name = "hello-http-tcp-proxy" +name = "hello-component-zclient" +version = "0.1.0" +dependencies = [ + "wit-bindgen 0.45.1", +] + +[[package]] +name = "hello-http-tcp-proxy" version = "0.1.0" dependencies = [ "anyhow", @@ -1422,7 +1777,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tracing", "tracing-subscriber", @@ -1441,7 +1796,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tracing", "tracing-subscriber", @@ -1482,7 +1837,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tracing-subscriber", "url", @@ -1500,7 +1855,7 @@ dependencies = [ "clap", "futures", "rcgen", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tracing", "tracing-subscriber", @@ -1510,12 +1865,106 @@ dependencies = [ "wtransport", ] +[[package]] +name = "hello-zenoh-client" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "tokio", + "tracing-subscriber", + "url", + "wit-bindgen-wrpc", + "wrpc-transport-zenoh", + "zenoh", +] + +[[package]] +name = "hello-zenoh-server" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "futures", + "hotpath", + "tokio", + "tracing", + "tracing-subscriber", + "url", + "wit-bindgen-wrpc", + "wrpc-transport-zenoh", + "zenoh", +] + [[package]] name = "hermit-abi" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "hotpath" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3554f9fc054c95f68e9f31196ca3aa77c6ce299f2e5877788e68168d01b7cfab" +dependencies = [ + "arc-swap", + "base64 0.22.1", + "cfg-if", + "clap", + "colored", + "crossbeam-channel", + "eyre", + "futures-util", + "hdrhistogram", + "hotpath-macros", + "libc", + "mach2 0.6.0", + "pin-project-lite", + "prettytable-rs", + "quanta", + "regex", + "serde", + "serde_json", + "tiny_http", + "tokio", +] + +[[package]] +name = "hotpath-macros" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8cf5fa828dd9b99de52bb85f9027c0d5205971cb3c45842b4bf6d7c7f6c679" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.116", +] + [[package]] name = "httlib-huffman" version = "0.3.4" @@ -1635,7 +2084,7 @@ dependencies = [ "bytes", "futures-channel", "futures-core", - "h2 0.4.12", + "h2 0.4.13", "http 1.4.0", "http-body 1.0.1", "httparse", @@ -1650,12 +2099,11 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "bytes", - "futures-core", "http 1.4.0", "http-body 1.0.1", "hyper 1.8.1", @@ -1666,9 +2114,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.64" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1736,9 +2184,9 @@ checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ "icu_collections", "icu_locale_core", @@ -1750,9 +2198,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" @@ -1771,9 +2219,15 @@ dependencies = [ [[package]] name = "id-arena" -version = "2.2.1" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a2bc672d1148e28034f176e01fffebb08b35768468cc954630da77a1449005" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" @@ -1796,11 +2250,28 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "indenter" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" + +[[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.12.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown 0.16.1", @@ -1808,6 +2279,15 @@ dependencies = [ "serde_core", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "io-extras" version = "0.18.4" @@ -1830,6 +2310,15 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "ipnetwork" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" +dependencies = [ + "serde", +] + [[package]] name = "is-terminal" version = "0.4.17" @@ -1876,9 +2365,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "ittapi" @@ -1934,14 +2423,43 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" +checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" 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 = "keccak" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb26cec98cce3a3d96cbb7bced3c4b16e3d13f27ec56dbd62cbc8f39cfb9d653" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keyed-set" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d255a6b6ecd77bb93ce91de984d7039bff7503f500eb4851a1269732f22baf" +dependencies = [ + "hashbrown 0.14.5", +] + [[package]] name = "lazy_static" version = "1.5.0" @@ -1967,23 +2485,33 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.178" +version = "0.2.182" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link", +] [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" +checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "libc", ] @@ -1995,9 +2523,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" @@ -2005,6 +2533,15 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.29" @@ -2032,7 +2569,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax", - "syn", + "syn 2.0.116", ] [[package]] @@ -2050,6 +2587,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "lz4_flex" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" +dependencies = [ + "twox-hash", +] + [[package]] name = "mach2" version = "0.4.3" @@ -2059,6 +2605,12 @@ dependencies = [ "libc", ] +[[package]] +name = "mach2" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae608c151f68243f2b000364e1f7b186d9c29845f7d2d85bd31b9ad77ad552b" + [[package]] name = "matchers" version = "0.2.0" @@ -2082,9 +2634,9 @@ checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" [[package]] name = "memchr" -version = "2.7.6" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memfd" @@ -2092,7 +2644,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" dependencies = [ - "rustix 1.0.8", + "rustix 1.1.3", ] [[package]] @@ -2117,6 +2669,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + [[package]] name = "mio" version = "1.1.1" @@ -2128,6 +2690,15 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom 0.2.17", +] + [[package]] name = "nkeys" version = "0.4.5" @@ -2137,12 +2708,18 @@ dependencies = [ "data-encoding", "ed25519", "ed25519-dalek", - "getrandom 0.2.16", + "getrandom 0.2.17", "log", "rand 0.8.5", "signatory", ] +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + [[package]] name = "nom" version = "7.1.3" @@ -2153,6 +2730,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nonempty-collections" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e216d0e8cf9d54fa66e5780f6e1d5dc96d1c1b3c25aeba3b6758548bcbbd8b9d" +dependencies = [ + "serde", +] + [[package]] name = "nu-ansi-term" version = "0.50.3" @@ -2205,6 +2791,16 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "object" version = "0.37.3" @@ -2213,7 +2809,7 @@ checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ "crc32fast", "hashbrown 0.15.5", - "indexmap", + "indexmap 2.13.0", "memchr", ] @@ -2256,6 +2852,53 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[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.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pem" version = "3.0.6" @@ -2281,6 +2924,104 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "pest" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" +dependencies = [ + "memchr", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.116", +] + +[[package]] +name = "pest_meta" +version = "2.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" +dependencies = [ + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +dependencies = [ + "fixedbitset", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "serde", +] + +[[package]] +name = "phf" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" +dependencies = [ + "phf_macros", + "phf_shared", + "serde", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.116", +] + +[[package]] +name = "phf_shared" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", +] + [[package]] name = "pin-project" version = "1.1.10" @@ -2298,7 +3039,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -2357,11 +3098,43 @@ dependencies = [ "plotters-backend", ] +[[package]] +name = "pnet_base" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc190d4067df16af3aba49b3b74c469e611cad6314676eaf1157f31aa0fb2f7" +dependencies = [ + "no-std-net", +] + +[[package]] +name = "pnet_datalink" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79e70ec0be163102a332e1d2d5586d362ad76b01cec86f830241f2b6452a7b7" +dependencies = [ + "ipnetwork", + "libc", + "pnet_base", + "pnet_sys", + "winapi", +] + +[[package]] +name = "pnet_sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d4643d3d4db6b08741050c2f3afa9a892c4244c085a72fcda93c9c2c9a00f4b" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "postcard" @@ -2406,14 +3179,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn", + "syn 2.0.116", +] + +[[package]] +name = "prettytable-rs" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eea25e07510aa6ab6547308ebe3c036016d162b8da920dbb079e3ba8acf3d95a" +dependencies = [ + "encode_unicode", + "is-terminal", + "lazy_static", + "term", + "unicode-width 0.1.14", +] + +[[package]] +name = "proc-macro-crate" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +dependencies = [ + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.103" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -2438,7 +3233,22 @@ checksum = "2cf194f5b1a415ef3a44ee35056f4009092cc4038a9f7e3c7c1e392f48ee7dbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", +] + +[[package]] +name = "quanta" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi 0.11.1+wasi-snapshot-preview1", + "web-sys", + "winapi", ] [[package]] @@ -2453,9 +3263,9 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.35", - "socket2 0.6.1", - "thiserror 2.0.17", + "rustls 0.23.36", + "socket2 0.6.2", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -2473,11 +3283,11 @@ dependencies = [ "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.35", + "rustls 0.23.36", "rustls-pki-types", "rustls-platform-verifier", "slab", - "thiserror 2.0.17", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -2492,16 +3302,16 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.1", + "socket2 0.6.2", "tracing", "windows-sys 0.60.2", ] [[package]] name = "quote" -version = "1.0.42" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] @@ -2530,7 +3340,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -2550,7 +3360,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -2559,18 +3369,27 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "rayon" version = "1.11.0" @@ -2636,22 +3455,62 @@ dependencies = [ "url", ] +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.0", +] + [[package]] name = "redox_users" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror 1.0.69", ] +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.17", + "libredox", + "thiserror 2.0.18", +] + +[[package]] +name = "ref-cast" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.116", +] + [[package]] name = "regalloc2" -version = "0.13.3" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e249c660440317032a71ddac302f25f1d5dff387667bcc3978d1f77aa31ac34" +checksum = "08effbc1fa53aaebff69521a5c05640523fab037b34a4a2c109506bc938246fa" dependencies = [ "allocator-api2", "bumpalo", @@ -2663,9 +3522,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.12.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -2675,9 +3534,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -2686,9 +3545,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "reqwest" @@ -2748,17 +3607,41 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", "untrusted", "windows-sys 0.52.0", ] +[[package]] +name = "ringbuffer-spsc" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3e7aa0a681b232e7cd7f856a53b10603df88ca74b79a8d8088845185492e35" +dependencies = [ + "array-init", + "crossbeam", +] + +[[package]] +name = "ron" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd490c5b18261893f14449cbd28cb9c0b637aebf161cd77900bfdedaff21ec32" +dependencies = [ + "bitflags 2.11.0", + "once_cell", + "serde", + "serde_derive", + "typeid", + "unicode-ident", +] + [[package]] name = "rustc-demangle" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d" [[package]] name = "rustc-hash" @@ -2790,7 +3673,7 @@ version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys 0.4.15", @@ -2799,15 +3682,15 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.9.4", - "windows-sys 0.60.2", + "linux-raw-sys 0.11.0", + "windows-sys 0.61.2", ] [[package]] @@ -2817,7 +3700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056" dependencies = [ "once_cell", - "rustix 1.0.8", + "rustix 1.1.3", ] [[package]] @@ -2836,15 +3719,15 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.35" +version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.8", + "rustls-webpki 0.103.9", "subtle", "zeroize", ] @@ -2855,7 +3738,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ - "openssl-probe", + "openssl-probe 0.1.6", "rustls-pemfile", "rustls-pki-types", "schannel", @@ -2864,14 +3747,14 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ - "openssl-probe", + "openssl-probe 0.2.1", "rustls-pki-types", "schannel", - "security-framework 3.5.1", + "security-framework 3.6.0", ] [[package]] @@ -2885,9 +3768,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.13.1" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c" +checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ "web-time", "zeroize", @@ -2904,11 +3787,11 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.35", - "rustls-native-certs 0.8.2", + "rustls 0.23.36", + "rustls-native-certs 0.8.3", "rustls-platform-verifier-android", - "rustls-webpki 0.103.8", - "security-framework 3.5.1", + "rustls-webpki 0.103.9", + "security-framework 3.6.0", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -2933,9 +3816,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.8" +version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ "ring", "rustls-pki-types", @@ -2950,9 +3833,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "same-file" @@ -2963,6 +3846,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scc" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc" +dependencies = [ + "sdd", +] + [[package]] name = "schannel" version = "0.1.28" @@ -2972,13 +3864,73 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2b42f36aa1cd011945615b92222f6bf73c599a102a300334cd7f8dbeec726cc" +dependencies = [ + "dyn-clone", + "either", + "ref-cast", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d115b50f4aaeea07e79c1912f645c7513d81715d0420f8bc77a18c6260b307f" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 2.0.116", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sdd" +version = "3.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca" + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "serde", + "zeroize", +] + [[package]] name = "security-framework" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.9.4", "core-foundation-sys", "libc", @@ -2987,11 +3939,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.5.1" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef" +checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -3000,9 +3952,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.15.0" +version = "2.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a" dependencies = [ "core-foundation-sys", "libc", @@ -3051,20 +4003,31 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", +] + +[[package]] +name = "serde_derive_internals" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.116", ] [[package]] name = "serde_json" -version = "1.0.145" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", "serde_core", + "zmij", ] [[package]] @@ -3084,7 +4047,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -3097,15 +4060,85 @@ dependencies = [ ] [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.13.0", + "schemars 0.9.0", + "schemars 1.2.1", + "serde_core", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.116", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap 2.13.0", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "serial_test" +version = "3.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" +dependencies = [ + "futures-executor", + "futures-util", + "log", + "once_cell", + "parking_lot", + "scc", + "serial_test_derive", +] + +[[package]] +name = "serial_test_derive" +version = "3.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", + "proc-macro2", + "quote", + "syn 2.0.116", ] [[package]] @@ -3119,6 +4152,22 @@ dependencies = [ "digest", ] +[[package]] +name = "sha2-const-stable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f179d4e11094a893b82fff208f74d448a7512f99f5a0acbd5c679b705f83ed9" + +[[package]] +name = "sha3" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75872d278a8f37ef87fa0ddbda7802605cb18344497949862c0d4dcb291eba60" +dependencies = [ + "digest", + "keccak", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -3128,6 +4177,15 @@ 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" @@ -3136,10 +4194,11 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.7" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7664a098b8e616bdfcc2dc0e9ac44eb231eedf41db4e9fe95d8d32ec728dedad" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -3165,11 +4224,23 @@ dependencies = [ "rand_core 0.6.4", ] +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "siphasher" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" + [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" @@ -3192,14 +4263,29 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" dependencies = [ "libc", "windows-sys 0.60.2", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "spin" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591" + [[package]] name = "spki" version = "0.7.3" @@ -3210,6 +4296,41 @@ dependencies = [ "der", ] +[[package]] +name = "stabby" +version = "72.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976399a0c48ea769ef7f5dc303bb88240ab8d84008647a6b2303eced3dab3945" +dependencies = [ + "rustversion", + "stabby-abi", +] + +[[package]] +name = "stabby-abi" +version = "72.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b54832a9a1f92a0e55e74a5c0332744426edc515bb3fbad82f10b874a87f0d" +dependencies = [ + "rustc_version", + "rustversion", + "sha2-const-stable", + "stabby-macros", +] + +[[package]] +name = "stabby-macros" +version = "72.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a768b1e51e4dbfa4fa52ae5c01241c0a41e2938fdffbb84add0c8238092f9091" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "rand 0.8.5", + "syn 1.0.109", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -3261,7 +4382,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tokio-stream", "tracing", @@ -3282,7 +4403,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tracing", "tracing-subscriber", @@ -3292,6 +4413,42 @@ dependencies = [ "wrpc-transport-quic", ] +[[package]] +name = "streams-zenoh-client" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "clap", + "futures", + "tokio", + "tokio-stream", + "tracing", + "tracing-subscriber", + "url", + "wit-bindgen-wrpc", + "wrpc-transport-zenoh", + "zenoh", +] + +[[package]] +name = "streams-zenoh-server" +version = "0.1.0" +dependencies = [ + "anyhow", + "bytes", + "clap", + "futures", + "hotpath", + "tokio", + "tracing", + "tracing-subscriber", + "url", + "wit-bindgen-wrpc", + "wrpc-transport-zenoh", + "zenoh", +] + [[package]] name = "strsim" version = "0.11.1" @@ -3306,9 +4463,20 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.111" +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.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" +checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" dependencies = [ "proc-macro2", "quote", @@ -3335,7 +4503,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -3365,7 +4533,7 @@ version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc4592f674ce18521c2a81483873a49596655b179f71c5e05d10c1fe66c78745" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "cap-fs-ext", "cap-std", "fd-lock", @@ -3377,22 +4545,33 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7f62577c25e07834649fc3b39fafdc597c0a3527dc1c60129201ccfcbaa50c" +checksum = "b1dd07eb858a2067e2f3c7155d54e929265c264e6f37efe3ee7a8d1b5a1dd0ba" [[package]] name = "tempfile" -version = "3.23.0" +version = "3.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" +checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" dependencies = [ "fastrand", "once_cell", - "rustix 1.0.8", + "rustix 1.1.3", "windows-sys 0.61.2", ] +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + [[package]] name = "termcolor" version = "1.4.1" @@ -3430,7 +4609,7 @@ checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -3444,11 +4623,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.17", + "thiserror-impl 2.0.18", ] [[package]] @@ -3459,18 +4638,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] name = "thiserror-impl" -version = "2.0.17" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -3513,6 +4692,18 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny_http" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82" +dependencies = [ + "ascii", + "chunked_transfer", + "httpdate", + "log", +] + [[package]] name = "tinystr" version = "0.8.2" @@ -3548,18 +4739,29 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" +[[package]] +name = "token-cell" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb48920ae769b58126c8c93269805011c793201f95fde28b479b81a9a531bbde" +dependencies = [ + "paste", + "portable-atomic", + "rustversion", +] + [[package]] name = "tokio" -version = "1.48.0" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ "bytes", "libc", "mio", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.1", + "socket2 0.6.2", "tokio-macros", "windows-sys 0.61.2", ] @@ -3572,7 +4774,7 @@ checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -3592,15 +4794,15 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.35", + "rustls 0.23.36", "tokio", ] [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -3610,14 +4812,15 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.17" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", "futures-io", "futures-sink", + "futures-util", "pin-project-lite", "tokio", ] @@ -3645,11 +4848,11 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.10+spec-1.1.0" +version = "0.9.12+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0825052159284a1a8b4d6c0c86cbc801f2da5afd2b225fa548c72f2e74002f48" +checksum = "cf92845e79fc2e2def6a5d828f0801e29a2f8acc037becc5ab08595c7d5e9863" dependencies = [ - "indexmap", + "indexmap 2.13.0", "serde_core", "serde_spanned", "toml_datetime", @@ -3667,11 +4870,23 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_edit" +version = "0.23.10+spec-1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +dependencies = [ + "indexmap 2.13.0", + "toml_datetime", + "toml_parser", + "winnow", +] + [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.0.8+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" dependencies = [ "winnow", ] @@ -3684,9 +4899,9 @@ checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -3699,11 +4914,11 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures-core", "futures-util", @@ -3737,9 +4952,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "log", "pin-project-lite", @@ -3755,14 +4970,14 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] name = "tracing-core" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -3779,6 +4994,16 @@ dependencies = [ "tracing-core", ] +[[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.22" @@ -3789,12 +5014,15 @@ dependencies = [ "nu-ansi-term", "once_cell", "regex-automata", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] @@ -3813,23 +5041,61 @@ dependencies = [ "tokio", ] +[[package]] +name = "twox-hash" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea3136b675547379c4bd395ca6b938e5ad3c3d20fad76e7fe85f9e0d011419c" + +[[package]] +name = "typeid" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" + [[package]] name = "typenum" version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +[[package]] +name = "ucd-trie" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" + +[[package]] +name = "uhlc" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b62a645e3e4e6c85b7abe49b086aa3204119431f42b6123b0070419fb6e9d24e" +dependencies = [ + "humantime", + "lazy_static", + "log", + "rand 0.8.5", + "serde", + "spin 0.10.0", +] + [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" -version = "1.0.22" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" + +[[package]] +name = "unicode-width" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unicode-width" @@ -3843,17 +5109,34 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "unzip-n" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b5bb2756c16fb66f80cfbf5fb0e0c09a7001e739f453c9ec241b9c8b1556fda" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.116", +] + [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -3885,21 +5168,51 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.19.0" +version = "1.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a" +checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" dependencies = [ - "getrandom 0.3.4", + "getrandom 0.4.1", "js-sys", "wasm-bindgen", ] +[[package]] +name = "validated_struct" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "869a93e8a7286e339e1128630051d82babbcd75d585975af07b9f3327220e60e" +dependencies = [ + "json5", + "serde", + "serde_json", + "validated_struct_macros", +] + +[[package]] +name = "validated_struct_macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c44ce98e7227a04eeb4cf9c784109a5c9710e54849ceb4f09f8597247897f1e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.116", + "unzip-n", +] + [[package]] name = "valuable" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.5" @@ -3998,7 +5311,7 @@ dependencies = [ "clap", "quinn", "rcgen", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tracing", "tracing-subscriber", @@ -4016,7 +5329,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tracing", "tracing-subscriber", @@ -4083,7 +5396,7 @@ dependencies = [ "clap", "futures", "quinn", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tower", "tower-http", @@ -4122,24 +5435,33 @@ dependencies = [ [[package]] name = "wasi-preview1-component-adapter-provider" -version = "41.0.1" +version = "41.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff0438c62c6bf0c99884538a60546d91310b7e5b947207fd1590e2da4d076d69" +checksum = "d9dd9d6d3211a4f0109862b49dc1de3b7148cc5cdc272cb1700684c9c65f8a0b" [[package]] name = "wasip2" -version = "1.0.1+wasi-0.2.4" +version = "1.0.2+wasi-0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +dependencies = [ + "wit-bindgen 0.51.0", +] + +[[package]] +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "wit-bindgen 0.46.0", + "wit-bindgen 0.51.0", ] [[package]] name = "wasm-bindgen" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" +checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" dependencies = [ "cfg-if", "once_cell", @@ -4150,11 +5472,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.56" +version = "0.4.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" +checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" dependencies = [ "cfg-if", + "futures-util", "js-sys", "once_cell", "wasm-bindgen", @@ -4163,9 +5486,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" +checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4173,22 +5496,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" +checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.116", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.106" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" +checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" dependencies = [ "unicode-ident", ] @@ -4223,6 +5546,26 @@ dependencies = [ "wasmparser 0.243.0", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser 0.244.0", +] + +[[package]] +name = "wasm-encoder" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9dca005e69bf015e45577e415b9af8c67e8ee3c0e38b5b0add5aa92581ed5c" +dependencies = [ + "leb128fmt", + "wasmparser 0.245.1", +] + [[package]] name = "wasm-metadata" version = "0.238.1" @@ -4230,7 +5573,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00094573b000c92134f2ef0f8afa4f6f892de37e78442988c946243a8c44364e" dependencies = [ "anyhow", - "indexmap", + "indexmap 2.13.0", "wasm-encoder 0.238.1", "wasmparser 0.238.1", ] @@ -4242,11 +5585,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20b3ec880a9ac69ccd92fbdbcf46ee833071cf09f82bb005b2327c7ae6025ae2" dependencies = [ "anyhow", - "indexmap", + "indexmap 2.13.0", "wasm-encoder 0.239.0", "wasmparser 0.239.0", ] +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap 2.13.0", + "wasm-encoder 0.244.0", + "wasmparser 0.244.0", +] + [[package]] name = "wasm-tokio" version = "0.6.0" @@ -4266,9 +5621,9 @@ version = "0.243.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bd23c879ec35d708f4eff3456f33c415d113363a2e38420098bf42976bacb31" dependencies = [ - "indexmap", + "indexmap 2.13.0", "logos", - "thiserror 2.0.17", + "thiserror 2.0.18", "wit-parser 0.243.0", ] @@ -4278,8 +5633,8 @@ version = "0.220.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d07b6a3b550fefa1a914b6d54fc175dd11c3392da11eee604e6ffc759805d25" dependencies = [ - "bitflags 2.10.0", - "indexmap", + "bitflags 2.11.0", + "indexmap 2.13.0", "semver", ] @@ -4289,9 +5644,9 @@ version = "0.238.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fa99c8328024423875ae4a55345cfde8f0371327fb2d0f33b0f52a06fc44408" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "hashbrown 0.15.5", - "indexmap", + "indexmap 2.13.0", "semver", ] @@ -4301,9 +5656,9 @@ version = "0.239.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c9d90bb93e764f6beabf1d02028c70a2156a6583e63ac4218dd07ef733368b0" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "hashbrown 0.15.5", - "indexmap", + "indexmap 2.13.0", "semver", ] @@ -4313,13 +5668,36 @@ version = "0.243.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6d8db401b0528ec316dfbe579e6ab4152d61739cfe076706d2009127970159d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "hashbrown 0.15.5", - "indexmap", + "indexmap 2.13.0", "semver", "serde", ] +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags 2.11.0", + "hashbrown 0.15.5", + "indexmap 2.13.0", + "semver", +] + +[[package]] +name = "wasmparser" +version = "0.245.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f08c9adee0428b7bddf3890fc27e015ac4b761cc608c822667102b8bfd6995e" +dependencies = [ + "bitflags 2.11.0", + "indexmap 2.13.0", + "semver", +] + [[package]] name = "wasmprinter" version = "0.243.0" @@ -4340,7 +5718,7 @@ dependencies = [ "addr2line", "anyhow", "async-trait", - "bitflags 2.10.0", + "bitflags 2.11.0", "bumpalo", "cc", "cfg-if", @@ -4348,18 +5726,18 @@ dependencies = [ "fxprof-processed-profile", "gimli", "hashbrown 0.15.5", - "indexmap", + "indexmap 2.13.0", "ittapi", "libc", "log", - "mach2", + "mach2 0.4.3", "memfd", "object", "once_cell", "postcard", "pulley-interpreter", "rayon", - "rustix 1.0.8", + "rustix 1.1.3", "semver", "serde", "serde_derive", @@ -4411,7 +5789,7 @@ dependencies = [ "cranelift-bitset", "cranelift-entity", "gimli", - "indexmap", + "indexmap 2.13.0", "log", "object", "postcard", @@ -4437,7 +5815,7 @@ dependencies = [ "directories-next", "log", "postcard", - "rustix 1.0.8", + "rustix 1.1.3", "serde", "serde_derive", "sha2", @@ -4456,7 +5834,7 @@ dependencies = [ "anyhow", "proc-macro2", "quote", - "syn", + "syn 2.0.116", "wasmtime-internal-component-util", "wasmtime-internal-wit-bindgen", "wit-parser 0.243.0", @@ -4487,7 +5865,7 @@ dependencies = [ "pulley-interpreter", "smallvec", "target-lexicon", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasmparser 0.243.0", "wasmtime-environ", "wasmtime-internal-math", @@ -4504,7 +5882,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "rustix 1.0.8", + "rustix 1.1.3", "wasmtime-environ", "wasmtime-internal-versioned-export-macros", "windows-sys 0.61.2", @@ -4518,7 +5896,7 @@ checksum = "db673148f26e1211db3913c12c75594be9e3858a71fa297561e9162b1a49cfb0" dependencies = [ "cc", "object", - "rustix 1.0.8", + "rustix 1.1.3", "wasmtime-internal-versioned-export-macros", ] @@ -4570,7 +5948,7 @@ checksum = "63ba3124cc2cbcd362672f9f077303ccc4cd61daa908f73447b7fdaece75ff9f" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -4597,9 +5975,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87acbd416227cdd279565ba49e57cf7f08d112657c3b3f39b70250acdfd094fe" dependencies = [ "anyhow", - "bitflags 2.10.0", + "bitflags 2.11.0", "heck", - "indexmap", + "indexmap 2.13.0", "wit-parser 0.243.0", ] @@ -4611,7 +5989,7 @@ checksum = "d9a1bdb4948463ed22559a640e687fed0df50b66353144aa6a9496c041ecd927" dependencies = [ "anyhow", "async-trait", - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "cap-fs-ext", "cap-net-ext", @@ -4622,9 +6000,9 @@ dependencies = [ "futures", "io-extras", "io-lifetimes", - "rustix 1.0.8", + "rustix 1.1.3", "system-interface", - "thiserror 2.0.17", + "thiserror 2.0.18", "tokio", "tracing", "url", @@ -4672,31 +6050,31 @@ dependencies = [ [[package]] name = "wast" -version = "243.0.0" +version = "245.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df21d01c2d91e46cb7a221d79e58a2d210ea02020d57c092e79255cc2999ca7f" +checksum = "28cf1149285569120b8ce39db8b465e8a2b55c34cbb586bd977e43e2bc7300bf" dependencies = [ "bumpalo", "leb128fmt", "memchr", - "unicode-width", - "wasm-encoder 0.243.0", + "unicode-width 0.2.2", + "wasm-encoder 0.245.1", ] [[package]] name = "wat" -version = "1.243.0" +version = "1.245.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226a9a91cd80a50449312fef0c75c23478fcecfcc4092bdebe1dc8e760ef521b" +checksum = "cd48d1679b6858988cb96b154dda0ec5bbb09275b71db46057be37332d5477be" dependencies = [ "wast", ] [[package]] name = "web-sys" -version = "0.3.83" +version = "0.3.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" +checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" dependencies = [ "js-sys", "wasm-bindgen", @@ -4714,9 +6092,9 @@ dependencies = [ [[package]] name = "webpki-root-certs" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee3e3b5f5e80bc89f30ce8d0343bf4e5f12341c51f3e26cbeecbc7c85443e85b" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" dependencies = [ "rustls-pki-types", ] @@ -4727,14 +6105,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.4", + "webpki-roots 1.0.6", ] [[package]] name = "webpki-roots" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" dependencies = [ "rustls-pki-types", ] @@ -4783,7 +6161,7 @@ dependencies = [ "regalloc2", "smallvec", "target-lexicon", - "thiserror 2.0.17", + "thiserror 2.0.18", "wasmparser 0.243.0", "wasmtime-environ", "wasmtime-internal-cranelift", @@ -4811,7 +6189,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -4822,7 +6200,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -5151,6 +6529,9 @@ name = "winnow" version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +dependencies = [ + "memchr", +] [[package]] name = "winreg" @@ -5168,7 +6549,7 @@ version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f3fd376f71958b862e7afb20cfe5a22830e1963462f3a17f49d82a6c1d1f42d" dependencies = [ - "bitflags 2.10.0", + "bitflags 2.11.0", "windows-sys 0.59.0", ] @@ -5178,14 +6559,17 @@ version = "0.45.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" dependencies = [ - "wit-bindgen-rust-macro", + "wit-bindgen-rust-macro 0.45.1", ] [[package]] name = "wit-bindgen" -version = "0.46.0" +version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro 0.51.0", +] [[package]] name = "wit-bindgen-core" @@ -5209,6 +6593,17 @@ dependencies = [ "wit-parser 0.238.1", ] +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck", + "wit-parser 0.244.0", +] + [[package]] name = "wit-bindgen-rust" version = "0.45.1" @@ -5217,14 +6612,30 @@ checksum = "f089b7beb50fdcf0b9dc68be920843d743c00cbbd5ef1fa21c727f9b5089dac5" dependencies = [ "anyhow", "heck", - "indexmap", + "indexmap 2.13.0", "prettyplease", - "syn", + "syn 2.0.116", "wasm-metadata 0.238.1", "wit-bindgen-core 0.45.1", "wit-component 0.238.1", ] +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.13.0", + "prettyplease", + "syn 2.0.116", + "wasm-metadata 0.244.0", + "wit-bindgen-core 0.51.0", + "wit-component 0.244.0", +] + [[package]] name = "wit-bindgen-rust-macro" version = "0.45.1" @@ -5235,9 +6646,24 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.116", "wit-bindgen-core 0.45.1", - "wit-bindgen-rust", + "wit-bindgen-rust 0.45.1", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.116", + "wit-bindgen-core 0.51.0", + "wit-bindgen-rust 0.51.0", ] [[package]] @@ -5245,7 +6671,7 @@ name = "wit-bindgen-wrpc" version = "0.11.0" dependencies = [ "anyhow", - "bitflags 2.10.0", + "bitflags 2.11.0", "bytes", "futures", "tokio", @@ -5280,7 +6706,7 @@ dependencies = [ "prettyplease", "serde", "serde_json", - "syn", + "syn 2.0.116", "test-helpers", "tokio", "wit-bindgen-core 0.36.0", @@ -5297,7 +6723,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.116", "wit-bindgen-core 0.36.0", "wit-bindgen-wrpc-rust", ] @@ -5309,8 +6735,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7d31c985f541330d1a809547043ad19dd58739a2f83c7f116aeabcab86aed597" dependencies = [ "anyhow", - "bitflags 2.10.0", - "indexmap", + "bitflags 2.11.0", + "indexmap 2.13.0", "log", "serde", "serde_derive", @@ -5328,8 +6754,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88a866b19dba2c94d706ec58c92a4c62ab63e482b4c935d2a085ac94caecb136" dependencies = [ "anyhow", - "bitflags 2.10.0", - "indexmap", + "bitflags 2.11.0", + "indexmap 2.13.0", "log", "serde", "serde_derive", @@ -5340,6 +6766,25 @@ dependencies = [ "wit-parser 0.239.0", ] +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags 2.11.0", + "indexmap 2.13.0", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder 0.244.0", + "wasm-metadata 0.244.0", + "wasmparser 0.244.0", + "wit-parser 0.244.0", +] + [[package]] name = "wit-parser" version = "0.220.1" @@ -5348,7 +6793,7 @@ checksum = "ae2a7999ed18efe59be8de2db9cb2b7f84d88b27818c79353dfc53131840fe1a" dependencies = [ "anyhow", "id-arena", - "indexmap", + "indexmap 2.13.0", "log", "semver", "serde", @@ -5366,7 +6811,7 @@ checksum = "1eea12c964ed423ed14745e51aac2f1e28e5572ca012b0503bdcf65ffee3b44c" dependencies = [ "anyhow", "id-arena", - "indexmap", + "indexmap 2.13.0", "log", "semver", "serde", @@ -5384,7 +6829,7 @@ checksum = "55c92c939d667b7bf0c6bf2d1f67196529758f99a2a45a3355cc56964fd5315d" dependencies = [ "anyhow", "id-arena", - "indexmap", + "indexmap 2.13.0", "log", "semver", "serde", @@ -5402,7 +6847,7 @@ checksum = "df983a8608e513d8997f435bb74207bf0933d0e49ca97aa9d8a6157164b9b7fc" dependencies = [ "anyhow", "id-arena", - "indexmap", + "indexmap 2.13.0", "log", "semver", "serde", @@ -5412,6 +6857,24 @@ dependencies = [ "wasmparser 0.243.0", ] +[[package]] +name = "wit-parser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.13.0", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser 0.244.0", +] + [[package]] name = "writeable" version = "0.6.2" @@ -5428,6 +6891,7 @@ dependencies = [ "clap", "criterion", "futures", + "serial_test", "tempfile", "test-log", "tokio", @@ -5447,7 +6911,9 @@ dependencies = [ "wrpc-transport-nats", "wrpc-transport-quic", "wrpc-transport-web", + "wrpc-transport-zenoh", "wrpc-wasmtime-cli", + "zenoh", ] [[package]] @@ -5458,6 +6924,7 @@ dependencies = [ "async-nats", "tokio", "tracing-subscriber", + "zenoh", ] [[package]] @@ -5505,11 +6972,13 @@ dependencies = [ "async-nats", "quinn", "rcgen", - "rustls 0.23.35", + "rustls 0.23.36", "tokio", "tracing", "wrpc-cli", + "wrpc-transport-zenoh", "wtransport", + "zenoh", ] [[package]] @@ -5578,6 +7047,28 @@ dependencies = [ "wtransport", ] +[[package]] +name = "wrpc-transport-zenoh" +version = "0.29.0" +dependencies = [ + "anyhow", + "bytes", + "flume", + "futures", + "hotpath", + "nuid", + "serde", + "serde_json", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", + "uuid", + "wasm-tokio", + "wrpc-transport", + "zenoh", +] + [[package]] name = "wrpc-wasi-keyvalue" version = "0.1.1" @@ -5639,6 +7130,8 @@ dependencies = [ "wrpc-runtime-wasmtime", "wrpc-transport", "wrpc-transport-nats", + "wrpc-transport-zenoh", + "zenoh", ] [[package]] @@ -5668,13 +7161,13 @@ dependencies = [ "pem", "quinn", "rcgen", - "rustls 0.23.35", - "rustls-native-certs 0.8.2", + "rustls 0.23.36", + "rustls-native-certs 0.8.3", "rustls-pemfile", "rustls-pki-types", "sha2", "socket2 0.5.10", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", "tokio", "tracing", @@ -5691,7 +7184,7 @@ checksum = "1a09d89a8dba201c2439d9d5eca55a0faa08909d69da50decdb5ec00be0ac504" dependencies = [ "httlib-huffman", "octets", - "thiserror 2.0.17", + "thiserror 2.0.18", "url", ] @@ -5708,7 +7201,7 @@ dependencies = [ "nom", "oid-registry", "rusticata-macros", - "thiserror 2.0.17", + "thiserror 2.0.18", "time", ] @@ -5740,28 +7233,390 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", "synstructure", ] +[[package]] +name = "zenoh" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f9ff8cb89f5267b8486a69466bc42f240f1ee2d5089e72395a23094e7b74f21" +dependencies = [ + "ahash", + "arc-swap", + "async-trait", + "bytes", + "const_format", + "flate2", + "flume", + "futures", + "git-version", + "itertools 0.14.0", + "json5", + "lazy_static", + "nonempty-collections", + "once_cell", + "petgraph", + "phf", + "rand 0.8.5", + "ref-cast", + "rustc_version", + "serde", + "serde_json", + "socket2 0.5.10", + "tokio", + "tokio-util", + "tracing", + "uhlc", + "vec_map", + "zenoh-buffers", + "zenoh-codec", + "zenoh-collections", + "zenoh-config", + "zenoh-core", + "zenoh-keyexpr", + "zenoh-link", + "zenoh-link-commons", + "zenoh-macros", + "zenoh-plugin-trait", + "zenoh-protocol", + "zenoh-result", + "zenoh-runtime", + "zenoh-sync", + "zenoh-task", + "zenoh-transport", + "zenoh-util", +] + +[[package]] +name = "zenoh-buffers" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9216c3d6c84b56f3e3be634e52365022038e1ac1b9f662f10d425cbf6c0fa8" +dependencies = [ + "zenoh-collections", +] + +[[package]] +name = "zenoh-codec" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14bc6747664aa9ecf17becd6e9a29282e535a350cd7c6bd8de7bf2dc662fb93d" +dependencies = [ + "tracing", + "uhlc", + "zenoh-buffers", + "zenoh-protocol", +] + +[[package]] +name = "zenoh-collections" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d642ecfe0d85f0cd846be9bc92805d926c092a6e6c7a575b6346752f8c3ae16" +dependencies = [ + "ahash", +] + +[[package]] +name = "zenoh-config" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39765a5f9975aba204c99f2f65308db4952dbea8e5ac79c78ac1eaf5711e970a" +dependencies = [ + "json5", + "nonempty-collections", + "num_cpus", + "secrecy", + "serde", + "serde_json", + "serde_with", + "serde_yaml", + "tracing", + "uhlc", + "validated_struct", + "zenoh-core", + "zenoh-keyexpr", + "zenoh-macros", + "zenoh-protocol", + "zenoh-result", + "zenoh-util", +] + +[[package]] +name = "zenoh-core" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c0c1388dccf287aec4e9d5e638630dc9d536db9f1da3522889b42697723b9b" +dependencies = [ + "lazy_static", + "tokio", + "zenoh-result", + "zenoh-runtime", +] + +[[package]] +name = "zenoh-crypto" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b433e08df3b03f2af2d23bd29a32aa5f5522c52e66d63e3d135bfa66373736dd" +dependencies = [ + "aes", + "hmac", + "rand 0.8.5", + "rand_chacha 0.3.1", + "sha3", + "zenoh-result", +] + +[[package]] +name = "zenoh-keyexpr" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19a3c47c89cb55ea45a1b3fe7d1fe8682ea93530b1fc5245257812db14b55b3d" +dependencies = [ + "getrandom 0.2.17", + "hashbrown 0.16.1", + "keyed-set", + "rand 0.8.5", + "schemars 1.2.1", + "serde", + "token-cell", + "zenoh-result", +] + +[[package]] +name = "zenoh-link" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6218cecab58435f31fb8b2e185f74f35af8aedd96e8bdd3557b333206b1acfda" +dependencies = [ + "zenoh-config", + "zenoh-link-commons", + "zenoh-link-tcp", + "zenoh-protocol", + "zenoh-result", +] + +[[package]] +name = "zenoh-link-commons" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98adc618f7edb570b9333ce583934a7c63e3a619cb49666515bfc06a000d7b6" +dependencies = [ + "async-trait", + "flume", + "futures", + "serde", + "socket2 0.5.10", + "time", + "tokio", + "tokio-util", + "tracing", + "zenoh-buffers", + "zenoh-codec", + "zenoh-core", + "zenoh-protocol", + "zenoh-result", + "zenoh-runtime", + "zenoh-util", +] + +[[package]] +name = "zenoh-link-tcp" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f23bd5d06a0014ce5a205961d6d47c8e8d792d9fd050ae9d0c9b609a187995" +dependencies = [ + "async-trait", + "socket2 0.5.10", + "tokio", + "tokio-util", + "tracing", + "zenoh-config", + "zenoh-core", + "zenoh-link-commons", + "zenoh-protocol", + "zenoh-result", +] + +[[package]] +name = "zenoh-macros" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b760a458cd906ac888b37fd1abdb21a0f58ecc64cc3882f83a976cb5ca8e0632" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.116", + "zenoh-keyexpr", +] + +[[package]] +name = "zenoh-plugin-trait" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7325b773c43a86a94f800cb971ab7e4b7e01ce76819c9c100ea783a47c3a25e4" +dependencies = [ + "git-version", + "libloading", + "serde", + "stabby", + "tracing", + "zenoh-config", + "zenoh-keyexpr", + "zenoh-macros", + "zenoh-result", + "zenoh-util", +] + +[[package]] +name = "zenoh-protocol" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4d3dad7aeeea780495692b195cd56515569c32b76b9dd077cc408c3ebca03f" +dependencies = [ + "const_format", + "rand 0.8.5", + "serde", + "uhlc", + "zenoh-buffers", + "zenoh-keyexpr", + "zenoh-result", +] + +[[package]] +name = "zenoh-result" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b4dbfea68b947a790d5525bcf061e91e2fdc2798bce619851919b353a8580fa" +dependencies = [ + "anyhow", +] + +[[package]] +name = "zenoh-runtime" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "760a1f7880f98427ad849d600257d1455a18afe981681f362684a3f91042537e" +dependencies = [ + "lazy_static", + "ron", + "serde", + "tokio", + "tracing", + "zenoh-macros", + "zenoh-result", +] + +[[package]] +name = "zenoh-sync" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98f132137bb003f10b7fff086cb18addf8e8273b9c0d2722a53b5074c8a79965" +dependencies = [ + "arc-swap", + "event-listener", + "futures", + "tokio", + "zenoh-buffers", + "zenoh-collections", + "zenoh-core", +] + +[[package]] +name = "zenoh-task" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b17d10136fdabec7e21a3fcef568c210ee6a2d71cde6adcde99e9236584f3a1" +dependencies = [ + "futures", + "tokio", + "tokio-util", + "tracing", + "zenoh-core", + "zenoh-runtime", +] + +[[package]] +name = "zenoh-transport" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50739b4c45e0963df8377abddb74701a4b708b178590eae92f27a604e25daf44" +dependencies = [ + "async-trait", + "crossbeam-utils", + "flume", + "lazy_static", + "lz4_flex", + "rand 0.8.5", + "ringbuffer-spsc", + "serde", + "sha3", + "tokio", + "tokio-util", + "tracing", + "zenoh-buffers", + "zenoh-codec", + "zenoh-config", + "zenoh-core", + "zenoh-crypto", + "zenoh-link", + "zenoh-link-commons", + "zenoh-protocol", + "zenoh-result", + "zenoh-runtime", + "zenoh-sync", + "zenoh-task", + "zenoh-util", +] + +[[package]] +name = "zenoh-util" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9512987c13925d32d3331507c8807853d5b682ea8da94d0ba6534c7a8ace48aa" +dependencies = [ + "async-trait", + "const_format", + "flume", + "home", + "humantime", + "lazy_static", + "libc", + "libloading", + "pnet_datalink", + "schemars 1.2.1", + "serde", + "serde_json", + "shellexpand", + "tokio", + "tracing", + "tracing-subscriber", + "winapi", + "zenoh-core", + "zenoh-result", +] + [[package]] name = "zerocopy" -version = "0.8.31" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3" +checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.31" +version = "0.8.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a" +checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] [[package]] @@ -5781,7 +7636,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", "synstructure", ] @@ -5821,9 +7676,15 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.116", ] +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zstd" version = "0.13.3" diff --git a/Cargo.toml b/Cargo.toml index 09e27cb92..cf6f57b00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ members = [ ] [features] -default = ["bin", "nats", "net", "quic", "wasmtime", "web-transport"] +default = ["bin", "nats", "net", "quic", "wasmtime", "web-transport", "zenoh-transport"] bin = ["bin-bindgen", "bin-wasmtime"] bin-bindgen = [ @@ -43,6 +43,7 @@ net = ["wrpc-transport/net"] quic = ["dep:wrpc-transport-quic"] wasmtime = ["dep:wrpc-runtime-wasmtime"] web-transport = ["dep:wrpc-transport-web"] +zenoh-transport = ["dep:zenoh", "dep:wrpc-transport-zenoh", "wrpc-cli/zenoh-transport"] [[bin]] name = "wit-bindgen-wrpc" @@ -84,6 +85,10 @@ wrpc-transport-nats = { workspace = true, optional = true } wrpc-transport-quic = { workspace = true, optional = true } wrpc-transport-web = { workspace = true, optional = true } wrpc-wasmtime-cli = { workspace = true, optional = true } +wrpc-transport-zenoh = { workspace = true, features = [ + "zenoh-1_5_0", +], optional = true } +zenoh = { workspace = true, optional = true } [dev-dependencies] anyhow = { workspace = true } @@ -114,8 +119,10 @@ wasmtime-cli-flags = { workspace = true, features = [ "pooling-allocator", "threads", ] } -wrpc-test = { workspace = true, features = ["nats", "quic", "web-transport"] } +wrpc-test = { workspace = true, features = ["nats", "quic", "web-transport", "zenoh-transport"] } wrpc-transport = { workspace = true, features = ["net"] } +serial_test = "*" + [workspace.dependencies] anyhow = { version = "1", default-features = false } @@ -182,8 +189,11 @@ wrpc-transport = { version = "0.29", path = "./crates/transport", default-featur wrpc-transport-nats = { version = "0.31", path = "./crates/transport-nats", default-features = false } wrpc-transport-quic = { version = "0.6", path = "./crates/transport-quic", default-features = false } wrpc-transport-web = { version = "0.3", path = "./crates/transport-web", default-features = false } +wrpc-transport-zenoh = { version = "0.29", path = "./crates/transport-zenoh", default-features = false } wrpc-wasi-keyvalue = { version = "0.1.1", path = "./crates/wasi-keyvalue", default-features = false } wrpc-wasi-keyvalue-mem = { version = "0.2", path = "./crates/wasi-keyvalue-mem", default-features = false } wrpc-wasi-keyvalue-redis = { version = "0.2", path = "./crates/wasi-keyvalue-redis", default-features = false } wrpc-wasmtime-cli = { version = "0.9", path = "./crates/wasmtime-cli", default-features = false } wtransport = { version = "0.6.1", default-features = false } +zenoh = {version = "1.5.0", default-features = false} +flume = {version = "0.11.0", default-features = false} diff --git a/ZENOH.md b/ZENOH.md new file mode 100644 index 000000000..4360b3d7d --- /dev/null +++ b/ZENOH.md @@ -0,0 +1,157 @@ +### Requirements ******************* + +#### Setup zenohd on NixOS + +1. Add zenoh to your configuration.nix file in the environment.systemPackages + ``` + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + ... + zenoh + ]; + ``` + +2. Rebuild NixOS + ``` + sudo nixos-rebuild switch + ``` + +3. Test zenohd + ``` + zenohd + ``` + + - Sample output: + 2025-12-08T12:27:11.419376Z INFO main ThreadId(01) zenohd: zenohd v1.6.1 built with rustc 1.85.0 (4d91de4e4 2025-02-17) + 2025-12-08T12:27:11.423016Z INFO main ThreadId(01) zenohd: Initial conf: {"access_control":{"def ........ ,"qos":{"enabled":true}}}} + 2025-12-08T12:27:11.428864Z INFO main ThreadId(01) zenoh::net::runtime: Using ZID: ba0e4a24bdf641c79bfe9ee37eb9bc4 + 2025-12-08T12:27:11.438761Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::215:5dff:fe00:b079]:7447 + 2025-12-08T12:27:11.439328Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::3842:4ff:fe75:baf1]:7447 + 2025-12-08T12:27:11.439331Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::209d:11ff:fe06:8e06]:7447 + 2025-12-08T12:27:11.439333Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/10.255.255.254:7447 + 2025-12-08T12:27:11.439334Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/172.21.8.176:7447 + 2025-12-08T12:27:11.439336Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/172.18.0.1:7447 + 2025-12-08T12:27:11.439428Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: zenohd listening scout messages on 224.0.0.224:7446 + +#### Using [zenoh] transport + +We will use the following two Rust wRPC applications using [zenoh] transport: +- [examples/rust/hello-zenoh-client](examples/rust/hello-zenoh-client) +- [examples/rust/hello-zenoh-server](examples/rust/hello-zenoh-server) + +1. Run [zenoh]: + + - Build the repo, so that zenoh transport is compiled for wrpc-wasmtime (runtime) using + ```sh + cargo build --release + ``` + + - Create a zenoh config file at /path/to/config/zenoh_conf.json5 + ```sh + { + mode: "client", + listen: { + endpoints: ["tcp/0.0.0.0:7447"], + }, + } + ``` + This is a minimal example config. + + - Set the config environment variable for zenoh: + > export ZENOH_CONFIG="/path/to/config/zenoh_conf.json5" + + - Running as a daemon with the config above in order to run zenoh as a transport (in Client mode): + ```sh + zenohd + ``` + +2. Serve Wasm `hello` server via [zenoh] + + ```sh + ./target/release/wrpc-wasmtime zenoh serve ./target/wasm32-wasip2/debug/hello_component_server.wasm + ``` + + - Sample output: + > INFO zenoh::net::runtime: Using ZID: 638a012883d98f769cf4367f8457bc66 + > INFO zenoh::net::runtime::orchestrator: Scouting... + > INFO zenoh::net::runtime::orchestrator: Found HelloProto { version: 9, whatami: Router, zid: f3ae70a723144e6675f4c72d30196797, locators: [tcp/[fe80::215:5dff:fe83:cd20]:7447, tcp/[fe80::8d2:a4ff:fed2:f33d]:7447, tcp/[fe80::c431:38ff:fe58:9310]:7447, tcp/10.255.255.254:7447, tcp/172.21.8.176:7447, tcp/172.18.0.1:7447] } + > INFO zenoh::net::runtime::orchestrator: Found HelloProto { version: 9, whatami: Router, zid: f3ae70a723144e6675f4c72d30196797, locators: [tcp/[fe80::215:5dff:fe83:cd20]:7447, tcp/[fe80::8d2:a4ff:fed2:f33d]:7447, tcp/[fe80::c431:38ff:fe58:9310]:7447, tcp/10.255.255.254:7447, tcp/172.21.8.176:7447, tcp/172.18.0.1:7447] } + > INFO wrpc_wasmtime_cli: serving instance function name="hello" + +3. Call Wasm `hello` server using a Wasm `hello` client via [zenoh]: + + ```sh + ./target/release/wrpc-wasmtime zenoh run ./target/wasm32-wasip2/debug/hello-component-client.wasm + ``` + + - Sample output: + > INFO zenoh::net::runtime: Using ZID: e4b5dcb134469e2e5773dd88dfb7a8a + > INFO zenoh::net::runtime::orchestrator: Scouting... + > INFO zenoh::net::runtime::orchestrator: Found HelloProto { version: 9, whatami: Router, zid: f3ae70a723144e6675f4c72d30196797, locators: [tcp/[fe80::215:5dff:fe83:cd20]:7447, tcp/[fe80::8d2:a4ff:fed2:f33d]:7447, tcp/[fe80::c431:38ff:fe58:9310]:7447, tcp/10.255.255.254:7447, tcp/172.21.8.176:7447, tcp/172.18.0.1:7447] } + > INFO zenoh::net::runtime::orchestrator: Found HelloProto { version: 9, whatami: Router, zid: f3ae70a723144e6675f4c72d30196797, locators: [tcp/[fe80::215:5dff:fe83:cd20]:7447, tcp/[fe80::8d2:a4ff:fed2:f33d]:7447, tcp/[fe80::c431:38ff:fe58:9310]:7447, tcp/10.255.255.254:7447, tcp/172.21.8.176:7447, tcp/172.18.0.1:7447] } + hello from Rust + > INFO zenoh::api::session: close session zid=e4b5dcb134469e2e5773dd88dfb7a8a + +4. Call the Wasm `hello` server using a native wRPC `hello` client via [zenoh]: + + ```sh + cargo run -p hello-zenoh-client + ``` + +5. Serve native wRPC `hello` server via [zenoh]: + + ```sh + cargo run -p hello-zenoh-server + ``` + + +#### Testing + +To test the transport-zenoh package run: + + ```sh + cargo test zenoh -- --nocapture + ``` + + - Sample output: + > test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 13 filtered out; finished in 6.17s + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +6. Call both the native wRPC `hello` server and Wasm `hello` server using native wRPC `hello` client via [zenoh]: + + ```sh + cargo run -p hello-zenoh-client rust native + ``` + +7. Call native wRPC `hello` server using Wasm `hello` client via [zenoh]: + + ```sh + wrpc-wasmtime zenoh run --import native ./target/wasm32-wasip2/release/hello-component-client.wasm \ No newline at end of file diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index b2d37fd3f..a87497830 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -11,8 +11,9 @@ license.workspace = true repository.workspace = true [features] -default = ["nats"] +default = ["nats", "zenoh-transport"] nats = ["async-nats/ring", "dep:async-nats", "dep:tokio", "tokio/sync"] +zenoh-transport = ["dep:zenoh", "dep:tokio", "tokio/sync"] [dependencies] anyhow = { workspace = true, features = ["std"] } @@ -25,3 +26,4 @@ tracing-subscriber = { workspace = true, features = [ "smallvec", "tracing-log", ] } +zenoh = { workspace = true, optional = true, features = ["transport_tcp"] } diff --git a/crates/cli/src/lib.rs b/crates/cli/src/lib.rs index f6e19896d..34ac85549 100644 --- a/crates/cli/src/lib.rs +++ b/crates/cli/src/lib.rs @@ -1,3 +1,5 @@ #[cfg(feature = "nats")] pub mod nats; pub mod tracing; +#[cfg(feature = "zenoh-transport")] +pub mod zenoh; diff --git a/crates/cli/src/zenoh.rs b/crates/cli/src/zenoh.rs new file mode 100644 index 000000000..a9c2c2784 --- /dev/null +++ b/crates/cli/src/zenoh.rs @@ -0,0 +1,10 @@ +use zenoh::{Config, Session}; + +/// Open a regular Zenoh session with configs supplied by an environment variable. +pub async fn connect() -> anyhow::Result { + let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + + let session = zenoh::open(cfg) + .await.unwrap(); + Ok(session) +} \ No newline at end of file diff --git a/crates/test/Cargo.toml b/crates/test/Cargo.toml index 899055684..b505f4529 100644 --- a/crates/test/Cargo.toml +++ b/crates/test/Cargo.toml @@ -11,7 +11,7 @@ license.workspace = true repository.workspace = true [features] -default = ["nats", "quic", "web-transport"] +default = ["nats", "quic", "web-transport", "zenoh-transport"] nats = ["dep:async-nats", "async-nats/ring", "wrpc-cli/nats"] quic = [ "dep:quinn", @@ -22,6 +22,7 @@ quic = [ "quinn/rustls", ] web-transport = ["dep:wtransport", "wtransport/self-signed"] +zenoh-transport = ["dep:zenoh", "dep:wrpc-transport-zenoh", "wrpc-cli/zenoh-transport"] [dependencies] anyhow = { workspace = true } @@ -33,3 +34,5 @@ tokio = { workspace = true, features = ["net", "process", "rt-multi-thread"] } tracing = { workspace = true } wrpc-cli = { workspace = true } wtransport = { workspace = true, features = ["ring"], optional = true } +wrpc-transport-zenoh = { workspace = true, features = [ "zenoh-1_5_0",], optional = true } +zenoh = { workspace = true, optional = true } diff --git a/crates/test/src/lib.rs b/crates/test/src/lib.rs index b71d6f407..3942087f9 100644 --- a/crates/test/src/lib.rs +++ b/crates/test/src/lib.rs @@ -2,6 +2,7 @@ use core::net::Ipv6Addr; use std::process::ExitStatus; +use std::sync::Arc; use anyhow::Context; use rcgen::{generate_simple_self_signed, CertifiedKey}; use rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer}; @@ -12,6 +13,7 @@ use tokio::process::Command; use tokio::sync::oneshot; use tokio::task::JoinHandle; use tokio::{select, spawn}; +use zenoh::{Config}; pub async fn free_port() -> anyhow::Result { TcpListener::bind((Ipv6Addr::LOCALHOST, 0)) @@ -120,6 +122,55 @@ pub async fn start_nats() -> anyhow::Result<( Ok((port, client, server, stop_tx)) } +#[cfg(feature = "zenoh-transport")] +pub async fn start_zenoh() -> anyhow::Result<( + u16, + wrpc_transport_zenoh::Client, + JoinHandle>, + oneshot::Sender<()>, +)> { + let port = free_port().await?; // not used in setup -- just return + let (server, stop_tx) = + spawn_server(Command::new("zenohd").args(&[] as &[&str])) + .await + .context("failed to start zenohd server")?; + + // connect to zenoh + let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + + let session = zenoh::open(cfg) + .await + .expect("Failed to open a Zenoh session"); + + let arc_session = Arc::new(session); + + let prefix = Arc::::from(""); + + let client = wrpc_transport_zenoh::Client::new(arc_session, prefix) + .await + .context("failed to construct transport client")?; + + Ok((port, client, server, stop_tx)) +} + +#[cfg(feature = "zenoh-transport")] +pub async fn with_zenoh(f: impl FnOnce(u16, wrpc_transport_zenoh::Client) -> Fut) -> anyhow::Result +where + Fut: core::future::Future>, +{ + let (port, zenoh_client, zenoh_server, stop_tx) = start_zenoh() + .await + .context("failed to start Zenoh server")?; + let res = f(port, zenoh_client).await.context("closure failed")?; + + stop_tx.send(()).expect("failed to stop Zenoh server"); + zenoh_server + .await + .context("failed to await Zenoh server stop")? + .context("Zenoh server failed to stop")?; + Ok(res) +} + #[cfg(feature = "nats")] pub async fn with_nats(f: impl FnOnce(u16, async_nats::Client) -> Fut) -> anyhow::Result where diff --git a/crates/transport-zenoh/Cargo.toml b/crates/transport-zenoh/Cargo.toml new file mode 100644 index 000000000..f7284f7e2 --- /dev/null +++ b/crates/transport-zenoh/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "wrpc-transport-zenoh" +version = "0.29.0" +description = "wRPC Zenoh transport" + +authors.workspace = true +categories.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[features] +default = ["zenoh-1_5_0"] +hotpath = ["hotpath/hotpath"] +hotpath-alloc = ["hotpath/hotpath-alloc"] + +[dependencies] +anyhow = { workspace = true, features = ["std"] } +bytes = { workspace = true, features = ["serde"] } +futures = { workspace = true, features = ["async-await"] } +nuid = { workspace = true } +tokio = { workspace = true, features = ["io-util", "rt-multi-thread"] } +tokio-stream = { workspace = true, features = ["sync"] } +tokio-util = { workspace = true, features = ["codec", "io"] } +tracing = { workspace = true, features = ["attributes"] } +wasm-tokio = { workspace = true } +wrpc-transport = { workspace = true } +zenoh-1_5_0 = { package = "zenoh", version = "1.5.0", default-features = false, optional = true } +serde_json = { workspace = true } +serde = { workspace = true } +uuid = { workspace = true } +flume = { workspace = true } +hotpath = "0.9" diff --git a/crates/transport-zenoh/src/lib.rs b/crates/transport-zenoh/src/lib.rs new file mode 100644 index 000000000..8f2ad07fc --- /dev/null +++ b/crates/transport-zenoh/src/lib.rs @@ -0,0 +1,1439 @@ +//! wRPC Zenoh transport + +#![allow(clippy::type_complexity)] + +use anyhow::{anyhow, ensure, Context as _}; +use wrpc_transport::Index; + +use zenoh_1_5_0::sample::Sample; +#[cfg(feature = "zenoh-1_5_0")] +use zenoh_1_5_0 as zenoh; + +use core::ops::{Deref, DerefMut}; +use std::iter::zip; +use std::{io, mem}; +use zenoh::Session; +use zenoh::bytes::ZBytes; +use zenoh::Wait; + +use core::future::Future; +use core::pin::{pin, Pin}; +use core::task::{Context, Poll}; +use core::{str}; + +use std::collections::{HashMap}; +use std::sync::{Arc}; + +use bytes::{Buf as _, Bytes}; +use futures::{Stream, StreamExt}; +use tokio::io::{AsyncRead, AsyncWrite, ReadBuf}; +use tokio::select; +use tokio::sync::{mpsc, oneshot}; +use tokio::task::JoinSet; +use tokio_stream::wrappers::ReceiverStream; + +use tracing::{debug, error, instrument, trace, warn}; + +pub const PROTOCOL: &str = "wrpc.0.0.1"; + +// wrpc_transport_zenoh.rs +// Minimal wRPC transport over Zenoh (no NATS extras) + + +// ---------- Key helpers (slash-separated Zenoh style) ---------- +#[hotpath::measure] +fn send_sync(session: &Session, key: &str, payload: &[u8]) -> io::Result<()> { + // Using the synchronous (blocking) API + // Note: session.put returns a builder; calling `.wait()` executes it synchronously. + session + .put(key, payload) + .wait() + .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + Ok(()) +} + +#[hotpath::measure] +async fn publish_with_reply( + session: &zenoh::Session, + subject: String, + reply: String, + payload: Bytes, + ) -> Result<(), zenoh::Error> { + let zbytes = prepare_payload_zbytes(Some(reply), &payload, None, None); + session.put(subject, zbytes).await.unwrap(); + + Ok(()) + } + +#[hotpath::measure] +fn spawn_async(fut: impl Future + Send + 'static) { + match tokio::runtime::Handle::try_current() { + Ok(rt) => { + rt.spawn(fut); + } + Err(_) => match tokio::runtime::Runtime::new() { + Ok(rt) => { + rt.spawn(fut); + } + Err(err) => error!(?err, "failed to create a new Tokio runtime"), + }, + } +} + +fn child_inbox(base: &str) -> String { + let base = if base.ends_with('/') { base } else { &format!("{base}/") }; + format!("{base}{}", nuid::next()) +} + + +// fn new_inbox() -> String { +// let inbox = "_inbox/"; +// let id = nuid::next(); +// let mut s = String::with_capacity(inbox.len().saturating_add(id.len())); +// s.push_str(inbox); +// s.push_str(&id); +// s +// } + +#[must_use] +#[inline] +pub fn param_subject(prefix: &str) -> String { + format!("{prefix}/params") +} + +#[must_use] +#[inline] +pub fn result_subject(prefix: &str) -> String { + format!("{prefix}/results") +} + +#[must_use] +#[inline] +pub fn index_path(prefix: &str, path: &[usize]) -> String { + let mut s = String::with_capacity(prefix.len() + path.len() * 2); + if !prefix.is_empty() { + s.push_str(prefix); + } + for p in path { + if !s.is_empty() { + s.push('/'); + } + s.push_str(&p.to_string()); + } + s +} + +#[must_use] +#[inline] +pub fn subscribe_path(prefix: &str, path: &[Option]) -> String { + let mut s = String::with_capacity(prefix.len() + path.len() * 2); + if !prefix.is_empty() { + s.push_str(prefix); + } + for p in path { + if !s.is_empty() { + s.push('/'); + } + if let Some(p) = p { + s.push_str(&p.to_string()); + } else { + s.push('*'); + } + } + s +} + +#[must_use] +#[inline] +pub fn invocation_subject(prefix: &str, instance: &str, func: &str) -> String { + let mut s = + String::with_capacity(prefix.len() + PROTOCOL.len() + instance.len() + func.len() + 3); + if !prefix.is_empty() { + s.push_str(prefix); + s.push('/'); + } + s.push_str(PROTOCOL); + s.push('/'); + if !instance.is_empty() { + s.push_str(instance); + s.push('/'); + } + s.push_str(func); + s +} + +fn corrupted_memory_error() -> std::io::Error { + std::io::Error::other("corrupted memory state") +} + + +/// Transport subscriber +pub struct Subscriber { + rx: ReceiverStream, + subject: String, + commands: mpsc::Sender, + tasks: Arc>, +} + +#[hotpath::measure_all] +impl Drop for Subscriber { + fn drop(&mut self) { + let commands = self.commands.clone(); + let subject = self.subject.clone(); + let tasks = Arc::clone(&self.tasks); + spawn_async(async move { + trace!(?subject, "shutting down subscriber"); + if let Err(err) = commands.send(Command::Unsubscribe(subject)).await { + warn!(?err, "failed to shutdown subscriber"); + } + drop(tasks); + }); + } +} + +#[hotpath::measure_all] +impl Deref for Subscriber { + type Target = ReceiverStream; + + fn deref(&self) -> &Self::Target { + &self.rx + } +} + +#[hotpath::measure_all] +impl DerefMut for Subscriber { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.rx + } +} + + +enum Command { + Subscribe(String, mpsc::Sender), + Unsubscribe(String), + Batch(Box<[Command]>, oneshot::Sender<()>), +} + + +/// Subset of [`async_nats::Message`](async_nats::Message) used by this crate +pub struct Message { + subject: String, + reply: Option, + payload: Bytes, + status: Option, + description: Option, +} + +#[derive(Clone, Debug)] +pub struct Client { + session: Arc, + prefix: Arc, + inbox: Arc, + //queue_group: Option>, + commands: mpsc::Sender, + tasks: Arc>, +} + +#[hotpath::measure] +fn parse_zbytes_message(sample: Sample) -> (String, Option, Bytes, Option, Option) { + let key = sample.key_expr().as_str().to_string(); + let zbytes = sample.payload(); + + let bytes = zbytes.to_bytes(); + let mut cursor = 0; + + // Decode reply + let reply = if cursor < bytes.len() && bytes[cursor] == 1 { + cursor += 1; + let len = u32::from_le_bytes([bytes[cursor], bytes[cursor+1], bytes[cursor+2], bytes[cursor+3]]) as usize; + cursor += 4; + let reply_str = String::from_utf8_lossy(&bytes[cursor..cursor+len]).into_owned(); + cursor += len; + Some(reply_str) + } else { + cursor += 1; + None + }; + + // Decode status + let status = if cursor < bytes.len() && bytes[cursor] == 1 { + cursor += 1; + let len = u32::from_le_bytes([bytes[cursor], bytes[cursor+1], bytes[cursor+2], bytes[cursor+3]]) as usize; + cursor += 4; + let status_str = String::from_utf8_lossy(&bytes[cursor..cursor+len]).into_owned(); + cursor += len; + Some(status_str) + } else { + cursor += 1; + None + }; + + // Decode description + let description = if cursor < bytes.len() && bytes[cursor] == 1 { + cursor += 1; + let len = u32::from_le_bytes([bytes[cursor], bytes[cursor+1], bytes[cursor+2], bytes[cursor+3]]) as usize; + cursor += 4; + let desc_str = String::from_utf8_lossy(&bytes[cursor..cursor+len]).into_owned(); + cursor += len; + Some(desc_str) + } else { + cursor += 1; + None + }; + + // Remaining bytes are payload + let payload = if cursor < bytes.len() { + Bytes::copy_from_slice(&bytes[cursor..]) + } else { + Bytes::new() + }; + + (key, reply, payload, status, description) +} + +#[hotpath::measure] +fn prepare_payload_zbytes( + reply: Option, + payload: &[u8], + status: Option, + description: Option +) -> ZBytes { + // use std::io::Write; + + let mut buf = Vec::new(); + + // Encode reply + if let Some(reply) = reply { + buf.push(1u8); // has_reply = true + let reply_bytes = reply.as_bytes(); + buf.extend_from_slice(&(reply_bytes.len() as u32).to_le_bytes()); + buf.extend_from_slice(reply_bytes); + } else { + buf.push(0u8); // has_reply = false + } + + // Encode status + if let Some(status) = status { + buf.push(1u8); + let status_bytes = status.as_bytes(); + buf.extend_from_slice(&(status_bytes.len() as u32).to_le_bytes()); + buf.extend_from_slice(status_bytes); + } else { + buf.push(0u8); + } + + // Encode description + if let Some(description) = description { + buf.push(1u8); + let desc_bytes = description.as_bytes(); + buf.extend_from_slice(&(desc_bytes.len() as u32).to_le_bytes()); + buf.extend_from_slice(desc_bytes); + } else { + buf.push(0u8); + } + + // Append payload + buf.extend_from_slice(payload); + + ZBytes::from(buf) +} + +#[hotpath::measure_all] +impl Client { + pub async fn new( + session: impl Into>, + prefix: impl Into>, + //queue_group: Option>, + ) -> anyhow::Result { + let session: Arc = session.into(); + let root = format!("_inbox/{}/", nuid::next()); + let wildcard = format!("{root}**"); + let mut sub = session + .declare_subscriber(wildcard) + .with(flume::bounded(8192)) + .await.unwrap(); + + let mut tasks = JoinSet::new(); + let (cmd_tx, mut cmd_rx) = mpsc::channel(8192); + tasks.spawn({ + async move { + fn handle_command(subs: &mut HashMap>, cmd: Command) { + //println!("Handle Command Called"); + match cmd { + Command::Subscribe(s, tx) => { + //println!("Handle Command Subcribe: {}", s); + subs.insert(s, tx); + } + Command::Unsubscribe(s) => { + //println!("Handle Command Unsubscribe: {}", s); + subs.remove(&s); + } + Command::Batch(cmds, ack) => { + //println!("Handle Command Batch"); + for cmd in cmds { + handle_command(subs, cmd); + } + let _ = ack.send(()); + } + } + } + + async fn handle_message( + subs: &mut HashMap>, + sample: Sample, + ) { + //println!("Handle Command Called"); + let key = sample.key_expr().clone().as_str().to_string(); + // let msg = parse_message(sample); + + let Some(sub) = subs.get_mut(&key) else { + debug!(?key, "drop message with no subscriber"); + return; + }; + let Ok(sub) = sub.reserve().await else { + debug!(?key, "drop message with closed subscriber"); + subs.remove(&key); + return; + }; + + let (_key_parsed, + reply, + payload, + status, + description) = parse_zbytes_message(sample); + + sub.send(Message { + subject: key, + reply, + payload, + status, + description + }); + } + + let mut subs = HashMap::new(); + loop { + //println!("Loop Called"); + select! { + Ok(msg) = sub.recv_async() => handle_message(&mut subs, msg).await, + Some(cmd) = cmd_rx.recv() => handle_command(&mut subs, cmd), + else => return, + } + } + } + }); + Ok(Self { + session, + prefix: prefix.into(), + inbox: root.into(), + commands: cmd_tx, + tasks: Arc::new(tasks), + }) + } +} + + +pub struct ByteSubscription(Subscriber); + +#[hotpath::measure_all] +impl Stream for ByteSubscription { + type Item = std::io::Result; + + #[instrument(level = "trace", skip_all)] + fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.0.poll_next_unpin(cx) { + Poll::Ready(Some(Message { payload, .. })) => Poll::Ready(Some(Ok(payload))), + Poll::Ready(None) => Poll::Ready(None), + Poll::Pending => Poll::Pending, + } + } +} + +#[derive(Default)] +enum IndexTrie { + #[default] + Empty, + Leaf(Subscriber), + IndexNode { + subscriber: Option, + nested: Vec>, + }, + WildcardNode { + subscriber: Option, + nested: Option>, + }, +} + +#[hotpath::measure_all] +impl<'a> From<(&'a [Option], Subscriber)> for IndexTrie { + fn from((path, sub): (&'a [Option], Subscriber)) -> Self { + match path { + [] => Self::Leaf(sub), + [None, path @ ..] => Self::WildcardNode { + subscriber: None, + nested: Some(Box::new(Self::from((path, sub)))), + }, + [Some(i), path @ ..] => Self::IndexNode { + subscriber: None, + nested: { + let n = i.saturating_add(1); + let mut nested = Vec::with_capacity(n); + nested.resize_with(n, Option::default); + nested[*i] = Some(Self::from((path, sub))); + nested + }, + }, + } + } +} + +impl]>> FromIterator<(P, Subscriber)> for IndexTrie { + fn from_iter>(iter: T) -> Self { + let mut root = Self::Empty; + for (path, sub) in iter { + if !root.insert(path.as_ref(), sub) { + return Self::Empty; + } + } + root + } +} + +#[hotpath::measure_all] +impl IndexTrie { + #[inline] + fn is_empty(&self) -> bool { + matches!(self, IndexTrie::Empty) + } + + #[instrument(level = "trace", skip_all)] + fn take(&mut self, path: &[usize]) -> Option { + let Some((i, path)) = path.split_first() else { + return match mem::take(self) { + // TODO: Demux the subscription + //IndexTrie::WildcardNode { subscriber, nested } => { + // if let Some(nested) = nested { + // *self = IndexTrie::WildcardNode { + // subscriber: None, + // nested: Some(nested), + // } + // } + // subscriber + //} + IndexTrie::Empty | IndexTrie::WildcardNode { .. } => None, + IndexTrie::Leaf(subscriber) => Some(subscriber), + IndexTrie::IndexNode { subscriber, nested } => { + if !nested.is_empty() { + *self = IndexTrie::IndexNode { + subscriber: None, + nested, + } + } + subscriber + } + }; + }; + match self { + // TODO: Demux the subscription + //Self::WildcardNode { ref mut nested, .. } => { + // nested.as_mut().and_then(|nested| nested.take(path)) + //} + Self::Empty | Self::Leaf(..) | Self::WildcardNode { .. } => None, + Self::IndexNode { ref mut nested, .. } => nested + .get_mut(*i) + .and_then(|nested| nested.as_mut().and_then(|nested| nested.take(path))), + } + } + + /// Inserts `sub` under a `path` - returns `false` if it failed and `true` if it succeeded. + /// Tree state after `false` is returned in undefined + #[instrument(level = "trace", skip_all)] + fn insert(&mut self, path: &[Option], sub: Subscriber) -> bool { + match self { + Self::Empty => { + *self = Self::from((path, sub)); + true + } + Self::Leaf(..) => { + let Some((i, path)) = path.split_first() else { + return false; + }; + let Self::Leaf(subscriber) = mem::take(self) else { + return false; + }; + if let Some(i) = i { + let n = i.saturating_add(1); + let mut nested = Vec::with_capacity(n); + nested.resize_with(n, Option::default); + nested[*i] = Some(Self::from((path, sub))); + *self = Self::IndexNode { + subscriber: Some(subscriber), + nested, + }; + } else { + *self = Self::WildcardNode { + subscriber: Some(subscriber), + nested: Some(Box::new(Self::from((path, sub)))), + }; + } + true + } + Self::WildcardNode { + ref mut subscriber, + ref mut nested, + } => match (&subscriber, path) { + (None, []) => { + *subscriber = Some(sub); + true + } + (_, [None, path @ ..]) => { + if let Some(nested) = nested { + nested.insert(path, sub) + } else { + *nested = Some(Box::new(Self::from((path, sub)))); + true + } + } + _ => false, + }, + Self::IndexNode { + ref mut subscriber, + ref mut nested, + } => match (&subscriber, path) { + (None, []) => { + *subscriber = Some(sub); + true + } + (_, [Some(i), path @ ..]) => { + let cap = i.saturating_add(1); + if nested.len() < cap { + nested.resize_with(cap, Option::default); + } + let nested = &mut nested[*i]; + if let Some(nested) = nested { + nested.insert(path, sub) + } else { + *nested = Some(Self::from((path, sub))); + true + } + } + _ => false, + }, + } + } +} + + + + +pub struct Reader { + buffer: Bytes, + incoming: Option, + nested: Arc>, + path: Box<[usize]>, +} + +#[hotpath::measure_all] +impl wrpc_transport::Index for Reader { + #[instrument(level = "trace", skip(self))] + fn index(&self, path: &[usize]) -> anyhow::Result { + ensure!(!path.is_empty()); + trace!("locking index tree"); + let mut nested = self + .nested + .lock() + .map_err(|err| anyhow!(err.to_string()).context("failed to lock map"))?; + trace!("taking index subscription"); + let mut p = self.path.to_vec(); + p.extend_from_slice(path); + let incoming = nested.take(&p); + Ok(Self { + buffer: Bytes::default(), + incoming, + nested: Arc::clone(&self.nested), + path: p.into_boxed_slice(), + }) + } +} + +#[hotpath::measure_all] +impl AsyncRead for Reader { + #[instrument(level = "trace", skip_all, ret)] + fn poll_read( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &mut ReadBuf<'_>, + ) -> Poll> { + let cap = buf.remaining(); + if cap == 0 { + trace!("attempt to read empty buffer"); + return Poll::Ready(Ok(())); + } + + if !self.buffer.is_empty() { + if self.buffer.len() > cap { + trace!(cap, len = self.buffer.len(), "reading part of buffer"); + buf.put_slice(&self.buffer.split_to(cap)); + } else { + trace!(cap, len = self.buffer.len(), "reading full buffer"); + buf.put_slice(&mem::take(&mut self.buffer)); + } + return Poll::Ready(Ok(())); + } + let Some(incoming) = self.incoming.as_mut() else { + return Poll::Ready(Err(std::io::Error::new( + std::io::ErrorKind::NotFound, + format!("subscription not found for path {:?}", self.path), + ))); + }; + trace!("polling for next message"); + match incoming.poll_next_unpin(cx) { + Poll::Ready(Some(Message { mut payload, .. })) => { + trace!(?payload, "received message"); + if payload.is_empty() { + trace!("received stream shutdown message"); + return Poll::Ready(Ok(())); + } + if payload.len() > cap { + trace!(len = payload.len(), cap, "partially reading the message"); + buf.put_slice(&payload.split_to(cap)); + self.buffer = payload; + } else { + trace!(len = payload.len(), cap, "filling the buffer with payload"); + buf.put_slice(&payload); + } + Poll::Ready(Ok(())) + } + Poll::Ready(None) => { + trace!("subscription finished"); + Poll::Ready(Ok(())) + } + Poll::Pending => Poll::Pending, + } + } +} + + + +#[derive(Clone, Debug)] +pub struct SubjectWriter { + session: Arc, + tx: String, + shutdown: bool, + tasks: Arc>, +} + +impl SubjectWriter { + fn new(session: Arc, tx: String, tasks: Arc>) -> Self { + Self { + session, + tx, + shutdown: false, + tasks, + } + } +} + +#[hotpath::measure_all] +impl wrpc_transport::Index for SubjectWriter { + #[instrument(level = "trace", skip(self))] + fn index(&self, path: &[usize]) -> anyhow::Result { + ensure!(!path.is_empty()); + let tx = index_path(&self.tx, path); + Ok(Self { + session: self.session.clone(), + tx, + shutdown: false, + tasks: Arc::clone(&self.tasks), + }) + } +} + +impl AsyncWrite for SubjectWriter { + #[instrument(level = "trace", skip_all, ret, fields(subject = self.tx, buf = format!("{buf:02x?}")))] + fn poll_write( + mut self: Pin<&mut Self>, + _cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + trace!("starting send"); + + // let msg = prepare_payload_json(None, Bytes::copy_from_slice(buf), None, None); + let zbytes = prepare_payload_zbytes(None, buf, None, None); + let zbytes_bytes = zbytes.to_bytes(); + + let subject = &self.tx; + let session = &self.session; + + trace!("writing message synchronously: key={} size={}", subject, buf.len()); + + match send_sync(session, subject, &zbytes_bytes) { + Ok(()) => { + trace!("put completed"); + Poll::Ready(Ok(buf.len())) + } + Err(e) => { + warn!(?e, "failed to publish sync put"); + Poll::Ready(Err(e)) + } + } + } + + + #[instrument(level = "trace", skip_all, ret, fields(subject = self.tx))] + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + trace!("flushing"); + Poll::Ready(Ok(())) + } + + #[instrument(level = "trace", skip_all, ret, fields(subject = self.tx))] + fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + trace!("writing stream shutdown message"); + if !self.shutdown { + let session = self.session.clone(); + let key = self.tx.clone(); + self.shutdown = true; + + spawn_async(async move { + trace!("writing stream shutdown message (explicit)"); + let zbytes = prepare_payload_zbytes(None, &[], None, None); + if let Err(err) = session.put(key, zbytes).await { + warn!(?err, "failed to publish stream shutdown message"); + } + }); + } + Poll::Ready(Ok(())) + } +} + +#[hotpath::measure_all] +impl Drop for SubjectWriter { + fn drop(&mut self) { + if !self.shutdown { + let session = self.session.clone(); + let key = self.tx.clone(); + let tasks = Arc::clone(&self.tasks); + spawn_async(async move { + trace!("writing stream shutdown message"); + let zbytes = prepare_payload_zbytes(None, &[],None, None); + if let Err(err) = session.put(key, zbytes).await { + warn!(?err, "failed to publish stream shutdown message"); + } + drop(tasks); + }); + } + } +} + + + +#[derive(Default)] +pub enum RootParamWriter { + #[default] + Corrupted, + Handshaking { + session: Arc, + sub: Subscriber, + indexed: std::sync::Mutex, oneshot::Sender)>>, + buffer: Bytes, + tasks: Arc>, + }, + Draining { + tx: SubjectWriter, + buffer: Bytes, + }, + Active(SubjectWriter), +} + +impl RootParamWriter { + fn new( + session: Arc, + sub: Subscriber, + buffer: Bytes, + tasks: Arc>, + ) -> Self { + Self::Handshaking { + session, + sub, + indexed: std::sync::Mutex::default(), + buffer, + tasks, + } + } +} + +#[hotpath::measure] +fn map_status_to_error_kind(code: &str) -> Option { + let c = code.trim(); + match c { + // Allow either symbolic names or common numeric equivalents + c if c.eq_ignore_ascii_case("NO_RESPONDERS") || c == "503" => Some(io::ErrorKind::NotConnected), + c if c.eq_ignore_ascii_case("TIMEOUT") || c == "408" => Some(io::ErrorKind::TimedOut), + c if c.eq_ignore_ascii_case("REQUEST_TERMINATED") => Some(io::ErrorKind::UnexpectedEof), + _ => None, + } +} + +#[hotpath::measure_all] +impl RootParamWriter { + #[instrument(level = "trace", skip_all, ret)] + fn poll_active(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match &mut *self { + Self::Corrupted => Poll::Ready(Err(corrupted_memory_error())), + Self::Handshaking { sub, .. } => { + trace!("polling for handshake response 1"); + match sub.poll_next_unpin(cx) { + Poll::Ready(Some(Message { status: Some(code), description, .. })) => { + if let Some(kind) = map_status_to_error_kind(&code) { + return Poll::Ready(Err(kind.into())); + } + if !code.is_empty() { + let msg = match description { + Some(desc) if !desc.is_empty() => + format!("received a response with code `{code}` ({desc})"), + _ => + format!("received a response with code `{code}`"), + }; + return Poll::Ready(Err(io::Error::other(msg))); + } + // Empty status string: fall through to the generic error below + return Poll::Ready(Err(io::Error::new( + io::ErrorKind::InvalidInput, + "empty status string in handshake response", + ))); + } + Poll::Ready(Some(Message { + reply: Some(tx), .. + })) => { + let Self::Handshaking { + session, + indexed, + buffer, + tasks, + .. + } = mem::take(&mut *self) + else { + return Poll::Ready(Err(corrupted_memory_error())); + }; + let tx = SubjectWriter::new(session, param_subject(&tx), tasks); + let indexed = indexed + .into_inner() + .map_err(|err| std::io::Error::other(err.to_string()))?; + for (path, tx_tx) in indexed { + let tx = tx.index(&path).map_err(std::io::Error::other)?; + tx_tx.send(tx).map_err(|_| { + std::io::Error::from(std::io::ErrorKind::BrokenPipe) + })?; + } + trace!("handshake succeeded"); + if buffer.is_empty() { + *self = Self::Active(tx); + Poll::Ready(Ok(())) + } else { + *self = Self::Draining { tx, buffer }; + self.poll_active(cx) + } + } + Poll::Ready(Some(..)) => Poll::Ready(Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "peer did not specify a reply subject", + ))), + Poll::Ready(None) => { + *self = Self::Corrupted; + Poll::Ready(Err(std::io::Error::from(std::io::ErrorKind::BrokenPipe))) + } + Poll::Pending => Poll::Pending, + } + } + Self::Draining { tx, buffer } => { + let mut tx = pin!(tx); + while !buffer.is_empty() { + trace!(?tx.tx, "draining parameter buffer"); + match tx.as_mut().poll_write(cx, buffer) { + Poll::Ready(Ok(n)) => { + buffer.advance(n); + } + Poll::Ready(Err(e)) => return Poll::Ready(Err(e)), + Poll::Pending => return Poll::Pending, + } + } + let Self::Draining { tx, .. } = mem::take(&mut *self) else { + return Poll::Ready(Err(corrupted_memory_error())); + }; + trace!("parameter buffer draining succeeded"); + *self = Self::Active(tx); + Poll::Ready(Ok(())) + } + Self::Active(..) => Poll::Ready(Ok(())), + } + } +} + +#[hotpath::measure_all] +impl wrpc_transport::Index for RootParamWriter { + #[instrument(level = "trace", skip(self))] + fn index(&self, path: &[usize]) -> anyhow::Result { + ensure!(!path.is_empty()); + match self { + Self::Corrupted => Err(anyhow!(corrupted_memory_error())), + Self::Handshaking { indexed, .. } => { + let (tx_tx, tx_rx) = oneshot::channel(); + let mut indexed = indexed + .lock() + .map_err(|err| std::io::Error::other(err.to_string()))?; + indexed.push((path.to_vec(), tx_tx)); + Ok(IndexedParamWriter::Handshaking { + tx_rx, + indexed: std::sync::Mutex::default(), + }) + } + Self::Draining { tx, .. } | Self::Active(tx) => { + tx.index(path).map(IndexedParamWriter::Active) + } + } + } +} + +#[hotpath::measure_all] +impl AsyncWrite for RootParamWriter { + #[instrument(level = "trace", skip_all, ret, fields(buf = format!("{buf:02x?}")))] + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + match self.as_mut().poll_active(cx)? { + Poll::Ready(()) => { + let Self::Active(tx) = &mut *self else { + return Poll::Ready(Err(corrupted_memory_error())); + }; + trace!("writing buffer"); + pin!(tx).poll_write(cx, buf) + } + Poll::Pending => Poll::Pending, + } + } + + #[instrument(level = "trace", skip_all, ret)] + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_mut().poll_active(cx)? { + Poll::Ready(()) => { + let Self::Active(tx) = &mut *self else { + return Poll::Ready(Err(corrupted_memory_error())); + }; + trace!("flushing"); + pin!(tx).poll_flush(cx) + } + Poll::Pending => Poll::Pending, + } + } + + #[instrument(level = "trace", skip_all, ret)] + fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_mut().poll_active(cx)? { + Poll::Ready(()) => { + let Self::Active(tx) = &mut *self else { + return Poll::Ready(Err(corrupted_memory_error())); + }; + trace!("shutting down"); + pin!(tx).poll_shutdown(cx) + } + Poll::Pending => Poll::Pending, + } + } +} + +#[derive(Debug, Default)] +pub enum IndexedParamWriter { + #[default] + Corrupted, + Handshaking { + tx_rx: oneshot::Receiver, + indexed: std::sync::Mutex, oneshot::Sender)>>, + }, + Active(SubjectWriter), +} + + +#[hotpath::measure_all] +impl IndexedParamWriter { + #[instrument(level = "trace", skip_all, ret)] + fn poll_active(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match &mut *self { + Self::Corrupted => Poll::Ready(Err(corrupted_memory_error())), + Self::Handshaking { tx_rx, .. } => { + trace!("polling for handshake"); + match pin!(tx_rx).poll(cx) { + Poll::Ready(Ok(tx)) => { + let Self::Handshaking { indexed, .. } = mem::take(&mut *self) else { + return Poll::Ready(Err(corrupted_memory_error())); + }; + let indexed = indexed + .into_inner() + .map_err(|err| std::io::Error::other(err.to_string()))?; + for (path, tx_tx) in indexed { + let tx = tx.index(&path).map_err(std::io::Error::other)?; + tx_tx.send(tx).map_err(|_| { + std::io::Error::from(std::io::ErrorKind::BrokenPipe) + })?; + } + *self = Self::Active(tx); + Poll::Ready(Ok(())) + } + Poll::Ready(Err(..)) => Poll::Ready(Err(std::io::ErrorKind::BrokenPipe.into())), + Poll::Pending => Poll::Pending, + } + } + Self::Active(..) => Poll::Ready(Ok(())), + } + } +} + + +#[hotpath::measure_all] +impl wrpc_transport::Index for IndexedParamWriter { + #[instrument(level = "trace", skip_all)] + fn index(&self, path: &[usize]) -> anyhow::Result { + ensure!(!path.is_empty()); + match self { + Self::Corrupted => Err(anyhow!(corrupted_memory_error())), + Self::Handshaking { indexed, .. } => { + let (tx_tx, tx_rx) = oneshot::channel(); + let mut indexed = indexed + .lock() + .map_err(|err| std::io::Error::other(err.to_string()))?; + indexed.push((path.to_vec(), tx_tx)); + Ok(Self::Handshaking { + tx_rx, + indexed: std::sync::Mutex::default(), + }) + } + Self::Active(tx) => tx.index(path).map(Self::Active), + } + } +} + + +#[hotpath::measure_all] +impl AsyncWrite for IndexedParamWriter { + #[instrument(level = "trace", skip_all, ret, fields(buf = format!("{buf:02x?}")))] + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + match self.as_mut().poll_active(cx)? { + Poll::Ready(()) => { + let Self::Active(tx) = &mut *self else { + return Poll::Ready(Err(corrupted_memory_error())); + }; + trace!("writing buffer"); + pin!(tx).poll_write(cx, buf) + } + Poll::Pending => Poll::Pending, + } + } + + #[instrument(level = "trace", skip_all, ret)] + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_mut().poll_active(cx)? { + Poll::Ready(()) => { + let Self::Active(tx) = &mut *self else { + return Poll::Ready(Err(corrupted_memory_error())); + }; + trace!("flushing"); + pin!(tx).poll_flush(cx) + } + Poll::Pending => Poll::Pending, + } + } + + #[instrument(level = "trace", skip_all, ret)] + fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match self.as_mut().poll_active(cx)? { + Poll::Ready(()) => { + let Self::Active(tx) = &mut *self else { + return Poll::Ready(Err(corrupted_memory_error())); + }; + trace!("shutting down"); + pin!(tx).poll_shutdown(cx) + } + Poll::Pending => Poll::Pending, + } + } +} + + +pub enum ParamWriter { + Root(RootParamWriter), + Nested(IndexedParamWriter), +} + +#[hotpath::measure_all] +impl wrpc_transport::Index for ParamWriter { + fn index(&self, path: &[usize]) -> anyhow::Result { + ensure!(!path.is_empty()); + match self { + ParamWriter::Root(w) => w.index(path), + ParamWriter::Nested(w) => w.index(path), + } + .map(Self::Nested) + } +} + +#[hotpath::measure_all] +impl AsyncWrite for ParamWriter { + #[instrument(level = "trace", skip_all, ret, fields(buf = format!("{buf:02x?}")))] + fn poll_write( + mut self: Pin<&mut Self>, + cx: &mut Context<'_>, + buf: &[u8], + ) -> Poll> { + match &mut *self { + ParamWriter::Root(w) => pin!(w).poll_write(cx, buf), + ParamWriter::Nested(w) => pin!(w).poll_write(cx, buf), + } + } + + #[instrument(level = "trace", skip_all, ret)] + fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match &mut *self { + ParamWriter::Root(w) => pin!(w).poll_flush(cx), + ParamWriter::Nested(w) => pin!(w).poll_flush(cx), + } + } + + #[instrument(level = "trace", skip_all, ret)] + fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + match &mut *self { + ParamWriter::Root(w) => pin!(w).poll_shutdown(cx), + ParamWriter::Nested(w) => pin!(w).poll_shutdown(cx), + } + } +} + +impl wrpc_transport::Invoke for Client { + type Context = (); + type Outgoing = ParamWriter; + type Incoming = Reader; + + #[instrument(level = "trace", skip(self, paths, params), fields(params = format!("{params:02x?}")))] + async fn invoke]> + Send + Sync>( + &self, + cx: Self::Context, + instance: &str, + func: &str, + mut params: Bytes, + paths: impl AsRef<[P]> + Send, + ) -> anyhow::Result<(Self::Outgoing, Self::Incoming)> { + let paths = paths.as_ref(); + let mut cmds = Vec::with_capacity(paths.len().saturating_add(2)); + + let rx = child_inbox(&self.inbox); + let (handshake_tx, handshake_rx) = mpsc::channel(1); + cmds.push(Command::Subscribe(rx.clone(), handshake_tx)); + + let result = result_subject(&rx); + let (result_tx, result_rx) = mpsc::channel(16); + cmds.push(Command::Subscribe(result.clone(), result_tx)); + + let nested = paths.iter().map(|path| { + let (tx, rx) = mpsc::channel(16); + let subject = subscribe_path(&result, path.as_ref()); + cmds.push(Command::Subscribe(subject.clone(), tx)); + Subscriber { + rx: ReceiverStream::new(rx), + commands: self.commands.clone(), + subject, + tasks: Arc::clone(&self.tasks), + } + }); + let nested: IndexTrie = zip(paths.iter(), nested).collect(); + ensure!( + paths.is_empty() == nested.is_empty(), + "failed to construct subscription tree" + ); + + let (ack_tx, ack_rx) = oneshot::channel(); + + self.commands + .send(Command::Batch(cmds.into_boxed_slice(), ack_tx)) + .await + .context("failed to subscribe")?; + + ack_rx.await?; + + let param_tx = invocation_subject(&self.prefix, instance, func); + trace!("publishing handshake"); + publish_with_reply( + &self.session, + param_tx, + rx.clone(), + params) + .await.unwrap(); + + // let session = Arc::clone(&self.session); + // tokio::spawn(async move { + // if let Err(err) = nats.flush().await { + // error!(?err, "failed to flush"); + // } + // }); + Ok(( + ParamWriter::Root(RootParamWriter::new( + (*self.session).clone().into(), + Subscriber { + rx: ReceiverStream::new(handshake_rx), + commands: self.commands.clone(), + subject: rx, + tasks: Arc::clone(&self.tasks), + }, + Bytes::new(), + Arc::clone(&self.tasks), + )), + Reader { + buffer: Bytes::default(), + incoming: Some(Subscriber { + rx: ReceiverStream::new(result_rx), + commands: self.commands.clone(), + subject: result, + tasks: Arc::clone(&self.tasks), + }), + nested: Arc::new(std::sync::Mutex::new(nested)), + path: Box::default(), + }, + )) + } +} + +#[hotpath::measure] +async fn handle_message( + session: &zenoh::Session, + rx: String, + commands: mpsc::Sender, + Message { + reply: tx, + payload, + .. + }: Message, + paths: &[Box<[Option]>], + tasks: Arc>, +) -> anyhow::Result<((), SubjectWriter, Reader)> { + let tx = tx.clone(); + + let mut cmds = Vec::with_capacity(paths.len().saturating_add(1)); + + let param = param_subject(&rx); + let (param_tx, param_rx) = mpsc::channel(16); + cmds.push(Command::Subscribe(param.clone(), param_tx)); + + let nested = paths.iter().map(|path| { + let (tx, rx) = mpsc::channel(16); + let subject = subscribe_path(¶m, path.as_ref()); + cmds.push(Command::Subscribe(subject.clone(), tx)); + Subscriber { + rx: ReceiverStream::new(rx), + commands: commands.clone(), + subject, + tasks: Arc::clone(&tasks), + } + }); + let nested: IndexTrie = zip(paths.iter(), nested).collect(); + ensure!( + paths.is_empty() == nested.is_empty(), + "failed to construct subscription tree" + ); + + let (ack_tx, ack_rx) = oneshot::channel(); + + commands + .send(Command::Batch(cmds.into_boxed_slice(), ack_tx)) + .await + .context("failed to subscribe")?; + + ack_rx.await?; + + trace!("publishing handshake response"); + publish_with_reply(session, tx.clone().unwrap(), rx, Bytes::default()) + .await.unwrap(); + Ok(( + (), + SubjectWriter::new( + session.clone().into(), + result_subject(&tx.unwrap()), + Arc::clone(&tasks), + ), + Reader { + buffer: payload, + incoming: Some(Subscriber { + rx: ReceiverStream::new(param_rx), + commands, + subject: param, + tasks, + }), + nested: Arc::new(std::sync::Mutex::new(nested)), + path: Box::default(), + }, + )) +} + +#[hotpath::measure_all] +impl wrpc_transport::Serve for Client { + type Context = (); + type Outgoing = SubjectWriter; + type Incoming = Reader; + + #[instrument(level = "trace", skip(self, paths))] + async fn serve( + &self, + instance: &str, + func: &str, + paths: impl Into]>]>> + Send, + ) -> anyhow::Result< + impl Stream> + 'static, + > { + let subject = invocation_subject(&self.prefix, instance, func); + + //println!("Client serve subscribe to: {}", subject); + + let sub = self.session.declare_subscriber(subject).await.unwrap(); + let session = Arc::clone(&self.session); + let paths = paths.into(); + let commands = self.commands.clone(); + let inbox_root = self.inbox.clone(); + let tasks = Arc::clone(&self.tasks); + + let stream = futures::stream::unfold( + (sub, session, paths, commands, tasks, inbox_root), + |(sub, session, paths, commands, tasks, inbox_root)| async move { + match sub.recv_async().await { + Ok(sample) => { + let (subject, + reply, + payload, + status, + description) = parse_zbytes_message(sample); + + let message = Message { + subject, + reply, + payload, + status, + description, + }; + + let rx = child_inbox(inbox_root.as_ref()); + let item = handle_message( + &session, rx, commands.clone(), message, &paths, Arc::clone(&tasks) + ).await; + + // put `inboxroot` back into state for the next loop + Some((item, (sub, session, paths, commands, tasks, inbox_root))) + } + Err(_) => None, + } + }, + ); + + Ok(stream) + } +} diff --git a/crates/wasmtime-cli/Cargo.toml b/crates/wasmtime-cli/Cargo.toml index eee5e0b5a..d547b58c6 100644 --- a/crates/wasmtime-cli/Cargo.toml +++ b/crates/wasmtime-cli/Cargo.toml @@ -69,4 +69,6 @@ wit-component = { workspace = true } wrpc-cli = { workspace = true, features = ["nats"] } wrpc-transport-nats = { workspace = true } wrpc-transport = { workspace = true, features = ["net"] } +wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } wrpc-runtime-wasmtime = { workspace = true } +zenoh = { workspace = true } \ No newline at end of file diff --git a/crates/wasmtime-cli/src/lib.rs b/crates/wasmtime-cli/src/lib.rs index 4f310adc7..a89eef419 100644 --- a/crates/wasmtime-cli/src/lib.rs +++ b/crates/wasmtime-cli/src/lib.rs @@ -32,6 +32,7 @@ use wrpc_transport::{Invoke, Serve}; mod nats; mod tcp; +mod zenoh; const DEFAULT_TIMEOUT: &str = "10s"; @@ -42,6 +43,8 @@ enum Command { Nats(nats::Command), #[command(subcommand)] Tcp(tcp::Command), + #[command(subcommand)] + Zenoh(zenoh::Command), } pub enum Workload { @@ -495,12 +498,15 @@ where name, ) .await?; + + let name_copy = name.to_owned(); + handlers.spawn(async move { let mut invocations = pin!(invocations); while let Some(invocation) = invocations.next().await { match invocation { Ok((_, fut)) => { - info!("serving instance function invocation"); + info!(?name_copy, "serving instance function invocation"); if let Err(err) = fut.await { warn!( ?err, @@ -508,7 +514,7 @@ where ); } else { info!( - "successfully served instance function invocation" + ?name_copy, "successfully served instance function invocation" ); } } @@ -651,6 +657,7 @@ where name, ) .await?; + handlers.spawn(async move { let mut invocations = pin!(invocations); while let Some(invocation) = invocations.next().await { @@ -664,7 +671,7 @@ where ); } else { info!( - "successfully served instance function invocation" + "successfully served instance function invocation: " ); } } @@ -766,5 +773,6 @@ pub async fn run() -> anyhow::Result<()> { match Command::parse() { Command::Nats(args) => nats::run(args).await, Command::Tcp(args) => tcp::run(args).await, + Command::Zenoh(args) => zenoh::run(args).await, } } diff --git a/crates/wasmtime-cli/src/zenoh.rs b/crates/wasmtime-cli/src/zenoh.rs new file mode 100644 index 000000000..87a7bb4a4 --- /dev/null +++ b/crates/wasmtime-cli/src/zenoh.rs @@ -0,0 +1,98 @@ +use std::sync::Arc; + +use anyhow::Context as _; +use clap::Parser; +use tracing::instrument; + +/// Zenoh transport +#[derive(Parser, Debug)] +pub enum Command { + Run(RunArgs), + Serve(ServeArgs), +} + +/// Run a command component +#[derive(Parser, Debug)] +pub struct RunArgs { + /// Invocation timeout + #[arg(long, default_value = crate::DEFAULT_TIMEOUT)] + timeout: humantime::Duration, + + /// Prefix to send import invocations to + #[arg(long, default_value = "")] + import: String, + + /// Path or URL to Wasm command component + workload: String, +} + +/// Serve a reactor component +#[derive(Parser, Debug)] +pub struct ServeArgs { + /// Invocation timeout + #[arg(long, default_value = crate::DEFAULT_TIMEOUT)] + timeout: humantime::Duration, + + /// Prefix to send import invocations to + #[arg(long, default_value = "")] + import: String, + + /// Prefix to listen for export invocations on + #[arg(long, default_value = "")] + export: String, + + /// Path or URL to Wasm command component + workload: String, +} + +#[instrument(level = "trace", ret(level = "trace"))] +pub async fn handle_run( + RunArgs { + timeout, + import, + ref workload, + }: RunArgs, +) -> anyhow::Result<()> { + let zenoh = wrpc_cli::zenoh::connect() + .await + .context("failed to connect to zenoh")?; + let zenoh_client = wrpc_transport_zenoh::Client::new(zenoh, import) + .await + .context("failed to construct zenoh transport")?; + let res = crate::handle_run(zenoh_client, (), *timeout, workload).await; + //println!("foooooo run"); + res +} + +#[instrument(level = "trace", ret(level = "trace"))] +pub async fn handle_serve( + ServeArgs { + timeout, + export, + import, + ref workload, + }: ServeArgs, +) -> anyhow::Result<()> { + let zenoh = wrpc_cli::zenoh::connect() + .await + .context("failed to connect to zenoh")?; + let zenoh = Arc::new(zenoh); + let exports = wrpc_transport_zenoh::Client::new(zenoh.clone(), export) + .await + .context("failed to construct zenoh transport export client")?; + let imports = wrpc_transport_zenoh::Client::new(zenoh.clone(), import) + .await + .context("failed to construct zenoh transport import client")?; + //println!("foooooo serve"); + // future::pending::<()>().await; + // res + crate::handle_serve(exports, imports, (), *timeout, workload).await +} + +#[instrument(level = "trace", ret(level = "trace"))] +pub async fn run(cmd: Command) -> anyhow::Result<()> { + match cmd { + Command::Run(args) => handle_run(args).await, + Command::Serve(args) => handle_serve(args).await, + } +} diff --git a/examples/rust/hello-component-zclient/Cargo.toml b/examples/rust/hello-component-zclient/Cargo.toml new file mode 100644 index 000000000..e2854e185 --- /dev/null +++ b/examples/rust/hello-component-zclient/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "hello-component-zclient" +version = "0.1.0" + +authors.workspace = true +categories.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +wit-bindgen = { workspace = true, features = ["realloc", "macros"] } diff --git a/examples/rust/hello-component-zclient/src/main.rs b/examples/rust/hello-component-zclient/src/main.rs new file mode 100644 index 000000000..045b3518e --- /dev/null +++ b/examples/rust/hello-component-zclient/src/main.rs @@ -0,0 +1,19 @@ +use std::time::Instant; + +//WRPC wasm/client to work with hello-zenoh-server(host) + +mod bindings { + wit_bindgen::generate!({ + with: { + "wrpc-examples:hello/handler": generate, + } + }); +} + +fn main() { + let start = Instant::now(); + let response_str = bindings::wrpc_examples::hello::handler::hello(); + println!("*** Response: {response_str}"); + let elapsed = start.elapsed(); + println!("*** Elapsed get: {elapsed:?}"); +} diff --git a/examples/rust/hello-component-zclient/wit/deps.lock b/examples/rust/hello-component-zclient/wit/deps.lock new file mode 100644 index 000000000..275cb66c0 --- /dev/null +++ b/examples/rust/hello-component-zclient/wit/deps.lock @@ -0,0 +1,4 @@ +[hello] +path = "../../../wit/hello" +sha256 = "3680bb734f3fa9f7325674142a2a9b558efd34ea2cb2df7ccb651ad869078d27" +sha512 = "688fdae594dc43bd65bd15ea66b77a8f97cb4bc1c3629719e91d6c1391c66f7c8c6517d096f686cca996188f64f075c4ccb0d70a40097ce76b8b4bcc71dc7506" diff --git a/examples/rust/hello-component-zclient/wit/deps.toml b/examples/rust/hello-component-zclient/wit/deps.toml new file mode 100644 index 000000000..084f03eb0 --- /dev/null +++ b/examples/rust/hello-component-zclient/wit/deps.toml @@ -0,0 +1 @@ +hello = "../../../wit/hello" diff --git a/examples/rust/hello-component-zclient/wit/deps/hello/hello.wit b/examples/rust/hello-component-zclient/wit/deps/hello/hello.wit new file mode 100644 index 000000000..6c84d66cc --- /dev/null +++ b/examples/rust/hello-component-zclient/wit/deps/hello/hello.wit @@ -0,0 +1,13 @@ +package wrpc-examples:hello; + +interface handler { + hello: func() -> string; +} + +world client { + import handler; +} + +world server { + export handler; +} diff --git a/examples/rust/hello-component-zclient/wit/world.wit b/examples/rust/hello-component-zclient/wit/world.wit new file mode 100644 index 000000000..97aae5a62 --- /dev/null +++ b/examples/rust/hello-component-zclient/wit/world.wit @@ -0,0 +1,5 @@ +package wrpc-examples:hello-component-client; + +world client { + include wrpc-examples:hello/client; +} diff --git a/examples/rust/hello-zenoh-client/Cargo.toml b/examples/rust/hello-zenoh-client/Cargo.toml new file mode 100644 index 000000000..caf6d67ea --- /dev/null +++ b/examples/rust/hello-zenoh-client/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "hello-zenoh-client" +version = "0.1.0" + +authors.workspace = true +categories.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +anyhow = { workspace = true } +zenoh = { workspace = true, features = ["transport_tcp"] } +clap = { workspace = true, features = [ + "color", + "derive", + "error-context", + "help", + "std", + "suggestions", + "usage", +] } +tokio = { workspace = true, features = ["rt-multi-thread"] } +tracing-subscriber = { workspace = true, features = ["ansi", "fmt"] } +url = { workspace = true } +wit-bindgen-wrpc = { workspace = true } +wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } diff --git a/examples/rust/hello-zenoh-client/src/main.rs b/examples/rust/hello-zenoh-client/src/main.rs new file mode 100644 index 000000000..7abbe08c5 --- /dev/null +++ b/examples/rust/hello-zenoh-client/src/main.rs @@ -0,0 +1,81 @@ +use std::sync::Arc; +use anyhow::Context as _; +use zenoh::{Config}; +use std::time::Instant; + +mod bindings { + wit_bindgen_wrpc::generate!({ + with: { + "wrpc-examples:hello/handler": generate + } + }); +} + + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt().init(); + + let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + + let session = zenoh::open(cfg) + .await + .expect("Failed to open a Zenoh session"); + + let arc_session = Arc::new(session); + + let prefix = Arc::::from(""); + + let wrpc = wrpc_transport_zenoh::Client::new(arc_session, prefix) + .await + .context("failed to construct transport client")?; + + // From hello-nats-client + // let hello = bindings::wrpc_examples::hello::handler::hello(&wrpc, ()) + // .await + // .context("failed to invoke `wrpc-examples.hello/handler.hello`")?; + + // eprintln!("NOT_USED_var:prefix: {hello}"); + + // actually useful stuff + let ipv4_address = bindings::wrpc_examples::hello::handler::Ipv4Address{octets: (0,0,0,0)}; + let timespec = bindings::wrpc_examples::hello::handler::Timespec{tv_sec:-111, tv_nsec:111}; + let tr = bindings::wrpc_examples::hello::handler::Tracking { + ref_id: 32, + ip_addr: ipv4_address, + stratum: 16, + leap_status: 16, + ref_time: timespec, + current_correction: 64.0, + last_offset: 64.0, + rms_offset: 64.0, + freq_ppm: 64.0, + resid_freq_ppm: 64.0, + skew_ppm: 64.0, + root_delay: 64.0, + root_dispersion: 64.0, + last_update_interval: 64.0, + }; + + let start = Instant::now(); + let limit = 100001; + for i in 1..limit { + let t1 = bindings::wrpc_examples::hello::handler::get_tracking(&wrpc, (), &tr) + .await + .context("failed to invoke `wrpc-examples.hello/handler.hello`")?; + + // tiny sleep to allow buffers to clear + // tokio::time::sleep(tokio::time::Duration::from_micros(33)).await; + + // println!("Call {i} {:?}", t1.ref_id); + } + + // Record the time after the loop finishes and calculate the duration + let duration = start.elapsed(); + + // Print the elapsed time + // The {:?} formatter uses the Debug implementation for Duration + println!("Time elapsed in the loop is for {limit} calls. Time Elapsed: {duration:?}"); + + Ok(()) +} diff --git a/examples/rust/hello-zenoh-client/wit/deps.lock b/examples/rust/hello-zenoh-client/wit/deps.lock new file mode 100644 index 000000000..275cb66c0 --- /dev/null +++ b/examples/rust/hello-zenoh-client/wit/deps.lock @@ -0,0 +1,4 @@ +[hello] +path = "../../../wit/hello" +sha256 = "3680bb734f3fa9f7325674142a2a9b558efd34ea2cb2df7ccb651ad869078d27" +sha512 = "688fdae594dc43bd65bd15ea66b77a8f97cb4bc1c3629719e91d6c1391c66f7c8c6517d096f686cca996188f64f075c4ccb0d70a40097ce76b8b4bcc71dc7506" diff --git a/examples/rust/hello-zenoh-client/wit/deps.toml b/examples/rust/hello-zenoh-client/wit/deps.toml new file mode 100644 index 000000000..084f03eb0 --- /dev/null +++ b/examples/rust/hello-zenoh-client/wit/deps.toml @@ -0,0 +1 @@ +hello = "../../../wit/hello" diff --git a/examples/rust/hello-zenoh-client/wit/deps/hello/hello.wit b/examples/rust/hello-zenoh-client/wit/deps/hello/hello.wit new file mode 100644 index 000000000..29ea9780f --- /dev/null +++ b/examples/rust/hello-zenoh-client/wit/deps/hello/hello.wit @@ -0,0 +1,43 @@ +package wrpc-examples:hello; + +interface handler { + record timespec { + tv-sec: s64, + tv-nsec: u32 + } + + record tracking { + ref-id: u32, + ip-addr: ipv4-address, + stratum: u16, + leap-status: u16, + ref-time: timespec, + current-correction: f64, + last-offset: f64, + rms-offset: f64, + freq-ppm: f64, + resid-freq-ppm: f64, + skew-ppm: f64, + root-delay: f64, + root-dispersion: f64, + last-update-interval: f64, + } + + record ipv4-address { + // It seems that a list with a fixed size is supported in the WIT standard. However I have no clue if wasmtime implements it... + // octets: list, // https: //github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#types + + octets: tuple // Backup solution: closest to a static u8 array with 4 elements + } + + hello: func() -> string; + get-tracking: func(t: tracking) -> tracking; +} + +world client { + import handler; +} + +world server { + export handler; +} diff --git a/examples/rust/hello-zenoh-client/wit/world.wit b/examples/rust/hello-zenoh-client/wit/world.wit new file mode 100644 index 000000000..f9a08b60d --- /dev/null +++ b/examples/rust/hello-zenoh-client/wit/world.wit @@ -0,0 +1,5 @@ +package wrpc-examples:hello-rust-client; + +world client { + include wrpc-examples:hello/client; +} diff --git a/examples/rust/hello-zenoh-server/Cargo.toml b/examples/rust/hello-zenoh-server/Cargo.toml new file mode 100644 index 000000000..02679ae94 --- /dev/null +++ b/examples/rust/hello-zenoh-server/Cargo.toml @@ -0,0 +1,34 @@ +[package] +name = "hello-zenoh-server" +version = "0.1.0" + +authors.workspace = true +categories.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +anyhow = { workspace = true } +zenoh = { workspace = true, features = ["transport_tcp"] } +clap = { workspace = true, features = [ + "color", + "derive", + "error-context", + "help", + "std", + "suggestions", + "usage", +] } +futures = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread", "signal"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = ["ansi", "fmt"] } +url = { workspace = true } +wit-bindgen-wrpc = { workspace = true } +wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } +hotpath = "0.9" + +[features] +hotpath = ["hotpath/hotpath"] +hotpath-alloc = ["hotpath/hotpath-alloc"] diff --git a/examples/rust/hello-zenoh-server/src/main.rs b/examples/rust/hello-zenoh-server/src/main.rs new file mode 100644 index 000000000..6a0bc8759 --- /dev/null +++ b/examples/rust/hello-zenoh-server/src/main.rs @@ -0,0 +1,101 @@ +use core::pin::pin; +use std::sync::Arc; + +use anyhow::Context as _; +use futures::stream::select_all; +use futures::StreamExt as _; +use tokio::task::JoinSet; +use tokio::{select, signal}; +use tracing::{debug, error, info, warn}; +use zenoh::{Config}; + +mod bindings { + wit_bindgen_wrpc::generate!({ + with: { + "wrpc-examples:hello/handler": generate, + } + }); +} + +#[derive(Clone, Copy)] +struct Server; + +impl bindings::exports::wrpc_examples::hello::handler::Handler<()> + for Server +{ + async fn hello(&self, _: ()) -> anyhow::Result { + Ok("hello from Rust".to_string()) + } + + async fn get_tracking(&self, _cx: (), t:bindings::exports::wrpc_examples::hello::handler::Tracking) -> Result { + Ok(t) + } +} + +#[tokio::main] +#[hotpath::main(percentiles = [99])] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt().init(); + + let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + + let session = zenoh::open(cfg) + .await + .expect("Failed to open a Zenoh session"); + + let arc_session = Arc::new(session); + + let prefix = Arc::::from(""); + + let wrpc = wrpc_transport_zenoh::Client::new(arc_session, prefix) + .await + .context("failed to construct transport client")?; + let invocations = bindings::serve(&wrpc, Server) + .await + .context("failed to serve `wrpc-examples.hello/handler.hello`")?; + // NOTE: This will conflate all invocation streams into a single stream via `futures::stream::SelectAll`, + // to customize this, iterate over the returned `invocations` and set up custom handling per export + let mut invocations = select_all( + invocations + .into_iter() + .map(|(instance, name, invocations)| invocations.map(move |res| (instance, name, res))), + ); + let shutdown = signal::ctrl_c(); + let mut shutdown = pin!(shutdown); + let mut tasks = JoinSet::new(); + loop { + select! { + Some((instance, name, res)) = invocations.next() => { + match res { + Ok(fut) => { + debug!(instance, name, "invocation accepted"); + tasks.spawn(async move { + if let Err(err) = fut.await { + warn!(?err, "failed to handle invocation"); + } else { + info!(instance, name, "invocation successfully handled"); + } + }); + } + Err(err) => { + warn!(?err, instance, name, "failed to accept invocation"); + } + } + } + Some(res) = tasks.join_next() => { + if let Err(err) = res { + error!(?err, "failed to join task") + } + } + res = &mut shutdown => { + // wait for all invocations to complete + while let Some(res) = tasks.join_next().await { + if let Err(err) = res { + error!(?err, "failed to join task") + } + } + return res.context("failed to listen for ^C") + } + } + } +} diff --git a/examples/rust/hello-zenoh-server/wit/deps.lock b/examples/rust/hello-zenoh-server/wit/deps.lock new file mode 100644 index 000000000..275cb66c0 --- /dev/null +++ b/examples/rust/hello-zenoh-server/wit/deps.lock @@ -0,0 +1,4 @@ +[hello] +path = "../../../wit/hello" +sha256 = "3680bb734f3fa9f7325674142a2a9b558efd34ea2cb2df7ccb651ad869078d27" +sha512 = "688fdae594dc43bd65bd15ea66b77a8f97cb4bc1c3629719e91d6c1391c66f7c8c6517d096f686cca996188f64f075c4ccb0d70a40097ce76b8b4bcc71dc7506" diff --git a/examples/rust/hello-zenoh-server/wit/deps.toml b/examples/rust/hello-zenoh-server/wit/deps.toml new file mode 100644 index 000000000..084f03eb0 --- /dev/null +++ b/examples/rust/hello-zenoh-server/wit/deps.toml @@ -0,0 +1 @@ +hello = "../../../wit/hello" diff --git a/examples/rust/hello-zenoh-server/wit/deps/hello/hello.wit b/examples/rust/hello-zenoh-server/wit/deps/hello/hello.wit new file mode 100644 index 000000000..29ea9780f --- /dev/null +++ b/examples/rust/hello-zenoh-server/wit/deps/hello/hello.wit @@ -0,0 +1,43 @@ +package wrpc-examples:hello; + +interface handler { + record timespec { + tv-sec: s64, + tv-nsec: u32 + } + + record tracking { + ref-id: u32, + ip-addr: ipv4-address, + stratum: u16, + leap-status: u16, + ref-time: timespec, + current-correction: f64, + last-offset: f64, + rms-offset: f64, + freq-ppm: f64, + resid-freq-ppm: f64, + skew-ppm: f64, + root-delay: f64, + root-dispersion: f64, + last-update-interval: f64, + } + + record ipv4-address { + // It seems that a list with a fixed size is supported in the WIT standard. However I have no clue if wasmtime implements it... + // octets: list, // https: //github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#types + + octets: tuple // Backup solution: closest to a static u8 array with 4 elements + } + + hello: func() -> string; + get-tracking: func(t: tracking) -> tracking; +} + +world client { + import handler; +} + +world server { + export handler; +} diff --git a/examples/rust/hello-zenoh-server/wit/world.wit b/examples/rust/hello-zenoh-server/wit/world.wit new file mode 100644 index 000000000..8fffd81fd --- /dev/null +++ b/examples/rust/hello-zenoh-server/wit/world.wit @@ -0,0 +1,5 @@ +package wrpc-examples:hello-rust-server; + +world server { + include wrpc-examples:hello/server; +} diff --git a/examples/rust/streams-zenoh-client/Cargo.toml b/examples/rust/streams-zenoh-client/Cargo.toml new file mode 100644 index 000000000..698874803 --- /dev/null +++ b/examples/rust/streams-zenoh-client/Cargo.toml @@ -0,0 +1,35 @@ +[package] +name = "streams-zenoh-client" +version = "0.1.0" + +authors.workspace = true +categories.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +anyhow = { workspace = true } +zenoh = { workspace = true, features = ["transport_tcp"] } +bytes = { workspace = true } +clap = { workspace = true, features = [ + "color", + "derive", + "error-context", + "help", + "std", + "suggestions", + "usage", +] } +futures = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread"] } +tokio-stream = { workspace = true, features = ["time"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = [ + "ansi", + "env-filter", + "fmt", +] } +url = { workspace = true } +wit-bindgen-wrpc = { workspace = true } +wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } diff --git a/examples/rust/streams-zenoh-client/src/main.rs b/examples/rust/streams-zenoh-client/src/main.rs new file mode 100644 index 000000000..93bf87bd8 --- /dev/null +++ b/examples/rust/streams-zenoh-client/src/main.rs @@ -0,0 +1,87 @@ +use core::time::Duration; +use std::sync::Arc; + +use anyhow::Context as _; +use bytes::Bytes; +use futures::{stream, StreamExt as _}; +use tokio::{time, try_join}; +use tokio_stream::wrappers::IntervalStream; +use tracing::debug; +use zenoh::{Config}; + +mod bindings { + wit_bindgen_wrpc::generate!({ + with: { + "wrpc-examples:streams/handler": generate + } + }); +} + +use bindings::wrpc_examples::streams::handler::{echo, Req}; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt().init(); + + let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + + let session = zenoh::open(cfg) + .await + .expect("Failed to open a Zenoh session"); + + let arc_session = Arc::new(session); + + let prefix = Arc::::from("rust"); + //let prefixes = vec!["Hello", "Zenoh", "streams!"]; // Expected was a string vec ... ! + + //for prefix in prefixes { + let numbers = Box::pin( + stream::iter(1..) + .take(10) + .zip(IntervalStream::new(time::interval(Duration::from_secs(1)))) + .map(|(i, _)| i) + .ready_chunks(10), + ); + + // `stream` items are chunked using [`Bytes`] + let bytes = Box::pin( + stream::iter(b"foo bar baz") + .zip(IntervalStream::new(time::interval(Duration::from_secs(1)))) + .map(|(i, _)| *i) + .ready_chunks(10) + .map(Bytes::from), + ); + + // Client creation moved here from top + let wrpc = wrpc_transport_zenoh::Client::new(arc_session, prefix) + .await + .context("failed to construct transport client")?; + + let (mut numbers, mut bytes, io) = echo(&wrpc, (), Req { numbers, bytes }) + .await + .context("failed to invoke `wrpc-examples:streams/handler.echo`")?; + try_join!( + async { + if let Some(io) = io { + debug!("performing async I/O"); + io.await.context("failed to complete async I/O") + } else { + Ok(()) + } + }, + async { + while let Some(item) = numbers.next().await { + eprintln!("numbers: {item:?}"); + } + Ok(()) + }, + async { + while let Some(item) = bytes.next().await { + eprintln!("bytes: {item:?}"); + } + Ok(()) + } + )?; + //} + Ok(()) +} diff --git a/examples/rust/streams-zenoh-client/wit/deps.lock b/examples/rust/streams-zenoh-client/wit/deps.lock new file mode 100644 index 000000000..640642729 --- /dev/null +++ b/examples/rust/streams-zenoh-client/wit/deps.lock @@ -0,0 +1,4 @@ +[streams] +path = "../../../wit/streams" +sha256 = "5064bee90ebea73f1695987191fbbfea71ed2dbb69839814009490b4fbe8e96f" +sha512 = "dfca3844d91c6c8e83fefd7b9511a366b464cf69d017c61b671409cb26dc9490a0e59a8e60ef15b77fdeb4fc1b8d9e6efa11c2fb1a1dabd0141e5e6afe8a59b9" diff --git a/examples/rust/streams-zenoh-client/wit/deps.toml b/examples/rust/streams-zenoh-client/wit/deps.toml new file mode 100644 index 000000000..7ad7d00c7 --- /dev/null +++ b/examples/rust/streams-zenoh-client/wit/deps.toml @@ -0,0 +1 @@ +streams = "../../../wit/streams" diff --git a/examples/rust/streams-zenoh-client/wit/deps/streams/streams.wit b/examples/rust/streams-zenoh-client/wit/deps/streams/streams.wit new file mode 100644 index 000000000..8520741c2 --- /dev/null +++ b/examples/rust/streams-zenoh-client/wit/deps/streams/streams.wit @@ -0,0 +1,17 @@ +package wrpc-examples:streams; + +interface handler { + record req { + numbers: stream, + bytes: stream, + } + echo: func(r: req) -> (numbers: stream, bytes: stream); +} + +world client { + import handler; +} + +world server { + export handler; +} diff --git a/examples/rust/streams-zenoh-client/wit/world.wit b/examples/rust/streams-zenoh-client/wit/world.wit new file mode 100644 index 000000000..5f6997fdc --- /dev/null +++ b/examples/rust/streams-zenoh-client/wit/world.wit @@ -0,0 +1,5 @@ +package wrpc-examples:streams-rust-client; + +world client { + include wrpc-examples:streams/client; +} diff --git a/examples/rust/streams-zenoh-server/Cargo.toml b/examples/rust/streams-zenoh-server/Cargo.toml new file mode 100644 index 000000000..3dbf317e1 --- /dev/null +++ b/examples/rust/streams-zenoh-server/Cargo.toml @@ -0,0 +1,39 @@ +[package] +name = "streams-zenoh-server" +version = "0.1.0" + +authors.workspace = true +categories.workspace = true +edition.workspace = true +license.workspace = true +repository.workspace = true + +[dependencies] +anyhow = { workspace = true } +zenoh = { workspace = true, features = ["transport_tcp"] } +bytes = { workspace = true } +clap = { workspace = true, features = [ + "color", + "derive", + "error-context", + "help", + "std", + "suggestions", + "usage", +] } +futures = { workspace = true } +tokio = { workspace = true, features = ["rt-multi-thread", "signal"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true, features = [ + "ansi", + "env-filter", + "fmt", +] } +url = { workspace = true } +wit-bindgen-wrpc = { workspace = true } +wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } +hotpath = "0.9" + +[features] +hotpath = ["hotpath/hotpath"] +hotpath-alloc = ["hotpath/hotpath-alloc"] \ No newline at end of file diff --git a/examples/rust/streams-zenoh-server/src/main.rs b/examples/rust/streams-zenoh-server/src/main.rs new file mode 100644 index 000000000..3c0c7f2e8 --- /dev/null +++ b/examples/rust/streams-zenoh-server/src/main.rs @@ -0,0 +1,119 @@ +use core::pin::{pin, Pin}; +use std::sync::Arc; + +use anyhow::Context as _; +use bytes::Bytes; +use futures::stream::select_all; +use futures::{Stream, StreamExt as _}; +use tokio::task::JoinSet; +use tokio::{select, signal}; +use tracing::{debug, error, info, warn}; +use zenoh::{Config}; + +mod bindings { + wit_bindgen_wrpc::generate!({ + with: { + "wrpc-examples:streams/handler": generate, + } + }); +} + +use bindings::exports::wrpc_examples::streams::handler::Req; + +// #[derive(Parser, Debug)] +// #[command(author, version, about, long_about = None)] +// struct Args { +// /// NATS.io URL to connect to +// #[arg(short, long, default_value = "nats://127.0.0.1:4222")] +// nats: Url, + +// /// Prefix to serve `wrpc-examples:streams/handler.echo` on +// #[arg(default_value = "rust")] +// prefix: String, +// } + +#[derive(Clone, Copy)] +struct Server; + +impl bindings::exports::wrpc_examples::streams::handler::Handler<()> for Server +{ + async fn echo( + &self, + _cx: (), + Req { numbers, bytes }: Req, + ) -> anyhow::Result<( + Pin> + Send>>, + Pin + Send>>, + )> { + Ok((numbers, bytes)) + } +} + +#[tokio::main] +#[hotpath::main(percentiles = [99])] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt().init(); + + let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + + let session = zenoh::open(cfg) + .await + .expect("Failed to open a Zenoh session"); + + let arc_session = Arc::new(session); + + let prefix = Arc::::from("rust"); + + let wrpc = wrpc_transport_zenoh::Client::new(arc_session, prefix) + .await + .context("failed to construct transport client")?; + let invocations = bindings::serve(&wrpc, Server) + .await + .context("failed to serve `wrpc-examples:streams/handler.echo`")?; + + // NOTE: This will conflate all invocation streams into a single stream via `futures::stream::SelectAll`, + // to customize this, iterate over the returned `invocations` and set up custom handling per export + let mut invocations = select_all( + invocations + .into_iter() + .map(|(instance, name, invocations)| invocations.map(move |res| (instance, name, res))), + ); + let shutdown = signal::ctrl_c(); + let mut shutdown = pin!(shutdown); + let mut tasks = JoinSet::new(); + loop { + select! { + Some((instance, name, res)) = invocations.next() => { + match res { + Ok(fut) => { + debug!(instance, name, "invocation accepted"); + tasks.spawn(async move { + if let Err(err) = fut.await { + warn!(?err, "failed to handle invocation"); + } else { + info!(instance, name, "invocation successfully handled"); + } + }); + } + Err(err) => { + warn!(?err, instance, name, "failed to accept invocation"); + } + } + } + Some(res) = tasks.join_next() => { + if let Err(err) = res { + error!(?err, "failed to join task") + } + } + res = &mut shutdown => { + // wait for all invocations to complete + while let Some(res) = tasks.join_next().await { + if let Err(err) = res { + error!(?err, "failed to join task") + } + } + return res.context("failed to listen for ^C") + } + } + } +} diff --git a/examples/rust/streams-zenoh-server/wit/deps.lock b/examples/rust/streams-zenoh-server/wit/deps.lock new file mode 100644 index 000000000..640642729 --- /dev/null +++ b/examples/rust/streams-zenoh-server/wit/deps.lock @@ -0,0 +1,4 @@ +[streams] +path = "../../../wit/streams" +sha256 = "5064bee90ebea73f1695987191fbbfea71ed2dbb69839814009490b4fbe8e96f" +sha512 = "dfca3844d91c6c8e83fefd7b9511a366b464cf69d017c61b671409cb26dc9490a0e59a8e60ef15b77fdeb4fc1b8d9e6efa11c2fb1a1dabd0141e5e6afe8a59b9" diff --git a/examples/rust/streams-zenoh-server/wit/deps.toml b/examples/rust/streams-zenoh-server/wit/deps.toml new file mode 100644 index 000000000..7ad7d00c7 --- /dev/null +++ b/examples/rust/streams-zenoh-server/wit/deps.toml @@ -0,0 +1 @@ +streams = "../../../wit/streams" diff --git a/examples/rust/streams-zenoh-server/wit/deps/streams/streams.wit b/examples/rust/streams-zenoh-server/wit/deps/streams/streams.wit new file mode 100644 index 000000000..8520741c2 --- /dev/null +++ b/examples/rust/streams-zenoh-server/wit/deps/streams/streams.wit @@ -0,0 +1,17 @@ +package wrpc-examples:streams; + +interface handler { + record req { + numbers: stream, + bytes: stream, + } + echo: func(r: req) -> (numbers: stream, bytes: stream); +} + +world client { + import handler; +} + +world server { + export handler; +} diff --git a/examples/rust/streams-zenoh-server/wit/world.wit b/examples/rust/streams-zenoh-server/wit/world.wit new file mode 100644 index 000000000..ba3ffa1b6 --- /dev/null +++ b/examples/rust/streams-zenoh-server/wit/world.wit @@ -0,0 +1,5 @@ +package wrpc-examples:streams-rust-server; + +world server { + include wrpc-examples:streams/server; +} diff --git a/tests/rust.rs b/tests/rust.rs index 7a628c25c..3b25c5678 100644 --- a/tests/rust.rs +++ b/tests/rust.rs @@ -21,6 +21,9 @@ use tracing::{info, info_span, instrument, Instrument, Span}; use wrpc_transport::frame::{AcceptExt as _, Oneshot}; use wrpc_transport::{Accept, InvokeExt as _, ResourceBorrow, ResourceOwn, ServeExt as _}; +use zenoh::{Config}; +use serial_test::serial; + #[instrument(skip_all, ret)] async fn assert_bindgen_async(clt: Arc, srv: Arc) -> anyhow::Result<()> where @@ -1028,6 +1031,45 @@ where Ok(()) } +#[cfg(feature = "zenoh-transport")] +#[test_log::test(tokio::test(flavor = "multi_thread"))] +#[serial(zenoh_tests)] +#[instrument(ret)] +async fn rust_bindgen_zenoh_sync() -> anyhow::Result<()> { + wrpc_test::with_zenoh(|_, zenoh_client| async { + let clt = Arc::new(zenoh_client); + assert_bindgen_sync(Arc::clone(&clt), clt).await + }) + .await +} + +#[cfg(feature = "zenoh-transport")] +#[test_log::test(tokio::test(flavor = "multi_thread"))] +#[serial(zenoh_tests)] +#[instrument(ret)] +async fn rust_bindgen_zenoh_async() -> anyhow::Result<()> { + wrpc_test::with_zenoh(|_, zenoh_client| { + async { + let clt = Arc::new(zenoh_client); + assert_bindgen_async(Arc::clone(&clt), clt).await + } + .in_current_span() + }) + .await +} + +#[cfg(feature = "zenoh-transport")] +#[test_log::test(tokio::test(flavor = "multi_thread"))] +#[serial(zenoh_tests)] +#[instrument(ret)] +async fn rust_dynamic_zenoh() -> anyhow::Result<()> { + wrpc_test::with_zenoh(|_, zenoh_client| async { + let clt = Arc::new(zenoh_client); + assert_dynamic(Arc::clone(&clt), clt).await + }) + .await +} + #[cfg(feature = "nats")] #[test_log::test(tokio::test(flavor = "multi_thread"))] #[instrument(ret)] diff --git a/zenoh_conf.json5 b/zenoh_conf.json5 new file mode 100644 index 000000000..6eaf1386b --- /dev/null +++ b/zenoh_conf.json5 @@ -0,0 +1,7 @@ +{ + "mode": "client", + "connect": { + "endpoints": ["tcp/0.0.0.0:7447"] + } +} + \ No newline at end of file diff --git a/zenoh_conf.json5.template b/zenoh_conf.json5.template new file mode 100644 index 000000000..c6ac22108 --- /dev/null +++ b/zenoh_conf.json5.template @@ -0,0 +1,6 @@ +{ + mode: "client", + listen: { + endpoints: ["tcp/172.21.8.176:7447"], + }, +} \ No newline at end of file From d0986f786ff59edc011e25ec9103161d91231f34 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Fri, 6 Mar 2026 17:29:52 +0100 Subject: [PATCH 2/7] changed payload handling in zenoh. WRPC data now in zenoh subject payload, reply added to zenoh subject attachment --- Cargo.lock | 564 ++++++++++-------- Cargo.toml | 9 +- benches/reactor/Cargo.toml | 2 +- crates/cli/src/zenoh.rs | 5 +- crates/test/Cargo.toml | 2 +- crates/test/src/lib.rs | 5 +- crates/transport-zenoh/Cargo.toml | 7 +- crates/transport-zenoh/src/lib.rs | 387 ++++-------- crates/wasmtime-cli/Cargo.toml | 2 +- examples/rust/hello-zenoh-client/Cargo.toml | 3 +- examples/rust/hello-zenoh-client/src/main.rs | 16 +- examples/rust/hello-zenoh-server/Cargo.toml | 5 +- examples/rust/hello-zenoh-server/src/main.rs | 16 +- examples/rust/streams-zenoh-client/Cargo.toml | 3 +- examples/rust/streams-zenoh-server/Cargo.toml | 5 +- tests/rust.rs | 86 +-- zenoh_conf.json5 | 7 - zenoh_conf.json5.template | 6 - 18 files changed, 530 insertions(+), 600 deletions(-) delete mode 100644 zenoh_conf.json5 delete mode 100644 zenoh_conf.json5.template diff --git a/Cargo.lock b/Cargo.lock index 80d5d3b6e..aee01cc85 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -129,9 +129,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.101" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e0fee31ef5ed1ba1316088939cea399010ed7731dba877ed44aeb407a75ea" +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arbitrary" @@ -184,7 +184,7 @@ checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure", ] @@ -196,7 +196,7 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -244,7 +244,16 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", ] [[package]] @@ -368,9 +377,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.1" +version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" +checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" dependencies = [ "allocator-api2", ] @@ -410,7 +419,7 @@ checksum = "20a158160765c6a7d0d8c072a53d772e4cb243f38b04bfcf6b4939cfbe7482e7" dependencies = [ "cap-primitives", "cap-std", - "rustix 1.1.3", + "rustix 1.1.4", "smallvec", ] @@ -426,7 +435,7 @@ dependencies = [ "io-lifetimes", "ipnet", "maybe-owned", - "rustix 1.1.3", + "rustix 1.1.4", "rustix-linux-procfs", "windows-sys 0.59.0", "winx", @@ -451,7 +460,7 @@ dependencies = [ "cap-primitives", "io-extras", "io-lifetimes", - "rustix 1.1.3", + "rustix 1.1.4", ] [[package]] @@ -464,7 +473,7 @@ dependencies = [ "cap-primitives", "iana-time-zone", "once_cell", - "rustix 1.1.3", + "rustix 1.1.4", "winx", ] @@ -506,9 +515,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.43" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ "iana-time-zone", "num-traits", @@ -561,9 +570,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.58" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63be97961acde393029492ce0be7a1af7e323e6bae9511ebfac33751be5e6806" +checksum = "2797f34da339ce31042b27d23607e051786132987f595b02ba4f6a6dffb7030a" dependencies = [ "clap_builder", "clap_derive", @@ -571,9 +580,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.58" +version = "4.5.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f13174bda5dfd69d7e947827e5af4b0f2f94a4a3ee92912fba07a66150f21e2" +checksum = "24a241312cea5059b13574bb9b3861cabf758b879c15190b37b6d6fd63ab6876" dependencies = [ "anstream", "anstyle", @@ -590,7 +599,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -726,36 +735,36 @@ dependencies = [ [[package]] name = "cranelift-assembler-x64" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0377b13bf002a0774fcccac4f1102a10f04893d24060cf4b7350c87e4cbb647c" +checksum = "50a04121a197fde2fe896f8e7cac9812fc41ed6ee9c63e1906090f9f497845f6" dependencies = [ "cranelift-assembler-x64-meta", ] [[package]] name = "cranelift-assembler-x64-meta" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa027979140d023b25bf7509fb7ede3a54c3d3871fb5ead4673c4b633f671a2" +checksum = "a09e699a94f477303820fb2167024f091543d6240783a2d3b01a3f21c42bc744" dependencies = [ "cranelift-srcgen", ] [[package]] name = "cranelift-bforest" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "618e4da87d9179a70b3c2f664451ca8898987aa6eb9f487d16988588b5d8cc40" +checksum = "f07732c662a9755529e332d86f8c5842171f6e98ba4d5976a178043dad838654" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-bitset" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db53764b5dad233b37b8f5dc54d3caa9900c54579195e00f17ea21f03f71aaa7" +checksum = "18391da761cf362a06def7a7cf11474d79e55801dd34c2e9ba105b33dc0aef88" dependencies = [ "serde", "serde_derive", @@ -763,9 +772,9 @@ dependencies = [ [[package]] name = "cranelift-codegen" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae927f1d8c0abddaa863acd201471d56e7fc6c3925104f4861ed4dc3e28b421" +checksum = "0b3a09b3042c69810d255aef59ddc3b3e4c0644d1d90ecfd6e3837798cc88a3c" dependencies = [ "bumpalo", "cranelift-assembler-x64", @@ -790,9 +799,9 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fcf1e3e6757834bd2584f4cbff023fcc198e9279dcb5d684b4bb27a9b19f54" +checksum = "75817926ec812241889208d1b190cadb7fedded4592a4bb01b8524babb9e4849" dependencies = [ "cranelift-assembler-x64-meta", "cranelift-codegen-shared", @@ -803,24 +812,24 @@ dependencies = [ [[package]] name = "cranelift-codegen-shared" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "205dcb9e6ccf9d368b7466be675ff6ee54a63e36da6fe20e72d45169cf6fd254" +checksum = "859158f87a59476476eda3884d883c32e08a143cf3d315095533b362a3250a63" [[package]] name = "cranelift-control" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "108eca9fcfe86026054f931eceaf57b722c1b97464bf8265323a9b5877238817" +checksum = "03b65a9aec442d715cbf54d14548b8f395476c09cef7abe03e104a378291ab88" dependencies = [ "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d96496910065d3165f84ff8e1e393916f4c086f88ac8e1b407678bc78735aa" +checksum = "8334c99a7e86060c24028732efd23bac84585770dcb752329c69f135d64f2fc1" dependencies = [ "cranelift-bitset", "serde", @@ -829,9 +838,9 @@ dependencies = [ [[package]] name = "cranelift-frontend" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e303983ad7e23c850f24d9c41fc3cb346e1b930f066d3966545e4c98dac5c9fb" +checksum = "43ac6c095aa5b3e845d7ca3461e67e2b65249eb5401477a5ff9100369b745111" dependencies = [ "cranelift-codegen", "log", @@ -841,15 +850,15 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b0cf8d867d891245836cac7abafb0a5b0ea040a019d720702b3b8bcba40bfa" +checksum = "69d3d992870ed4f0f2e82e2175275cb3a123a46e9660c6558c46417b822c91fa" [[package]] name = "cranelift-native" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e24b641e315443e27807b69c440fe766737d7e718c68beb665a2d69259c77bf3" +checksum = "ee32e36beaf80f309edb535274cfe0349e1c5cf5799ba2d9f42e828285c6b52e" dependencies = [ "cranelift-codegen", "libc", @@ -858,9 +867,9 @@ dependencies = [ [[package]] name = "cranelift-srcgen" -version = "0.128.3" +version = "0.128.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e378a54e7168a689486d67ee1f818b7e5356e54ae51a1d7a53f4f13f7f8b7a" +checksum = "903adeaf4938e60209a97b53a2e4326cd2d356aab9764a1934630204bae381c9" [[package]] name = "crc32fast" @@ -909,6 +918,12 @@ dependencies = [ "itertools 0.10.5", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + [[package]] name = "crossbeam" version = "0.8.4" @@ -1004,7 +1019,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1028,7 +1043,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1039,7 +1054,7 @@ checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ "darling_core", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1084,9 +1099,9 @@ dependencies = [ [[package]] name = "deranged" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc3dc5ad92c2e2d1c193bbbbdf2ea477cb81331de4f3103f267ca18368b988c4" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ "powerfmt", "serde_core", @@ -1163,7 +1178,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1304,7 +1319,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce92ff622d6dadf7349484f42c93271a0d49b7cc4d466a936405bacbe10aa78" dependencies = [ "cfg-if", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.59.0", ] @@ -1382,7 +1397,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94e7099f6313ecacbe1256e8ff9d617b75d1bcb16a6fddef94866d225a01a14a" dependencies = [ "io-lifetimes", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.59.0", ] @@ -1442,7 +1457,7 @@ checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1520,20 +1535,20 @@ dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139ef39800118c7683f2fd3c98c1b23c09ae076556b435f8e9064ae108aaeeec" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 6.0.0", "wasip2", "wasip3", ] @@ -1566,7 +1581,7 @@ checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -1618,6 +1633,15 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1665,6 +1689,20 @@ dependencies = [ "num-traits", ] +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "serde", + "spin 0.9.8", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.5.0" @@ -1777,7 +1815,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tracing", "tracing-subscriber", @@ -1796,7 +1834,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tracing", "tracing-subscriber", @@ -1837,7 +1875,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tracing-subscriber", "url", @@ -1855,7 +1893,7 @@ dependencies = [ "clap", "futures", "rcgen", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tracing", "tracing-subscriber", @@ -1871,6 +1909,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", + "serde_json", "tokio", "tracing-subscriber", "url", @@ -1887,6 +1926,7 @@ dependencies = [ "clap", "futures", "hotpath", + "serde_json", "tokio", "tracing", "tracing-subscriber", @@ -1928,12 +1968,11 @@ dependencies = [ [[package]] name = "hotpath" -version = "0.9.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3554f9fc054c95f68e9f31196ca3aa77c6ce299f2e5877788e68168d01b7cfab" +checksum = "51462b35dc551217e1d1dd3f8c5eebbb5df7103370b1e55d24c19a3411d290f7" dependencies = [ "arc-swap", - "base64 0.22.1", "cfg-if", "clap", "colored", @@ -1956,13 +1995,13 @@ dependencies = [ [[package]] name = "hotpath-macros" -version = "0.9.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8cf5fa828dd9b99de52bb85f9027c0d5205971cb3c45842b4bf6d7c7f6c679" +checksum = "f022365c90cc04455f17a2b9ba5fe0e661cde1ab27434d382f1f8693fe124e7d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2306,9 +2345,9 @@ checksum = "06432fb54d3be7964ecd3649233cddf80db2832f47fec34c01f65b3d9d774983" [[package]] name = "ipnet" -version = "2.11.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "ipnetwork" @@ -2423,9 +2462,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" dependencies = [ "once_cell", "wasm-bindgen", @@ -2507,11 +2546,10 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" [[package]] name = "libredox" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" dependencies = [ - "bitflags 2.11.0", "libc", ] @@ -2523,9 +2561,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.11.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" @@ -2569,7 +2607,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -2644,7 +2682,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" dependencies = [ - "rustix 1.1.3", + "rustix 1.1.4", ] [[package]] @@ -2815,9 +2853,9 @@ dependencies = [ [[package]] name = "octets" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ba5d98c13e549f6f26f7d70808688ab85c6b42eb350ba2524d96c24ebde27e9" +checksum = "8311fa8ab7a57759b4ff1f851a3048d9ef0effaa0130726426b742d26d8a88e7" [[package]] name = "oid-registry" @@ -2954,7 +2992,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3010,7 +3048,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3024,29 +3062,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "f1749c7ed4bcaf4c3d0a3efc28538844fb29bcdd7d2b67b2be7e20ba861ff517" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -3145,6 +3183,7 @@ dependencies = [ "cobs", "embedded-io 0.4.0", "embedded-io 0.6.1", + "heapless", "serde", ] @@ -3179,7 +3218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3197,9 +3236,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.4.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ "toml_edit", ] @@ -3215,9 +3254,9 @@ dependencies = [ [[package]] name = "pulley-interpreter" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01051a5b172e07f9197b85060e6583b942aec679dac08416647bf7e7dc916b65" +checksum = "e9812652c1feb63cf39f8780cecac154a32b22b3665806c733cd4072547233a4" dependencies = [ "cranelift-bitset", "log", @@ -3227,13 +3266,13 @@ dependencies = [ [[package]] name = "pulley-macros" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cf194f5b1a415ef3a44ee35056f4009092cc4038a9f7e3c7c1e392f48ee7dbb" +checksum = "56000349b6896e3d44286eb9c330891237f40b27fd43c1ccc84547d0b463cb40" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3263,7 +3302,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.36", + "rustls 0.23.37", "socket2 0.6.2", "thiserror 2.0.18", "tokio", @@ -3283,7 +3322,7 @@ dependencies = [ "rand 0.9.2", "ring", "rustc-hash", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-pki-types", "rustls-platform-verifier", "slab", @@ -3309,9 +3348,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.44" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] @@ -3322,6 +3361,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.8.5" @@ -3503,7 +3548,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3545,9 +3590,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.9" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" @@ -3682,14 +3727,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags 2.11.0", "errno", "libc", - "linux-raw-sys 0.11.0", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -3700,7 +3745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fc84bf7e9aa16c4f2c758f27412dc9841341e16aa682d9c7ac308fe3ee12056" dependencies = [ "once_cell", - "rustix 1.1.3", + "rustix 1.1.4", ] [[package]] @@ -3719,9 +3764,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.36" +version = "0.23.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" +checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ "log", "once_cell", @@ -3754,7 +3799,7 @@ dependencies = [ "openssl-probe 0.2.1", "rustls-pki-types", "schannel", - "security-framework 3.6.0", + "security-framework 3.7.0", ] [[package]] @@ -3787,11 +3832,11 @@ dependencies = [ "jni", "log", "once_cell", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-native-certs 0.8.3", "rustls-platform-verifier-android", "rustls-webpki 0.103.9", - "security-framework 3.6.0", + "security-framework 3.7.0", "security-framework-sys", "webpki-root-certs", "windows-sys 0.61.2", @@ -3899,7 +3944,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -3939,9 +3984,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "3.6.0" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d17b898a6d6948c3a8ee4372c17cb384f90d2e6e912ef00895b14fd7ab54ec38" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.11.0", "core-foundation 0.10.1", @@ -3952,9 +3997,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.16.0" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321c8673b092a9a42605034a9879d73cb79101ed5fd117bc9a597b89b4e9e61a" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ "core-foundation-sys", "libc", @@ -4003,7 +4048,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4014,7 +4059,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4047,7 +4092,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4073,9 +4118,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.16.1" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" +checksum = "381b283ce7bc6b476d903296fb59d0d36633652b633b27f64db4fb46dcbfc3b9" dependencies = [ "base64 0.22.1", "chrono", @@ -4092,14 +4137,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.16.1" +version = "3.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" +checksum = "a6d4e30573c8cb306ed6ab1dca8423eec9a463ea0e155f45399455e0368b27e0" dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4117,9 +4162,9 @@ dependencies = [ [[package]] name = "serial_test" -version = "3.3.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555" +checksum = "911bd979bf1070a3f3aa7b691a3b3e9968f339ceeec89e08c280a8a22207a32f" dependencies = [ "futures-executor", "futures-util", @@ -4132,13 +4177,13 @@ dependencies = [ [[package]] name = "serial_test_derive" -version = "3.3.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83" +checksum = "0a7d91949b85b0d2fb687445e448b40d322b6b3e4af6b44a29b21d9a5f33e6d9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4179,9 +4224,9 @@ dependencies = [ [[package]] name = "shellexpand" -version = "3.1.1" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" +checksum = "32824fab5e16e6c4d86dc1ba84489390419a39f97699852b66480bb87d297ed8" dependencies = [ "dirs", ] @@ -4382,7 +4427,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tokio-stream", "tracing", @@ -4403,7 +4448,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tracing", "tracing-subscriber", @@ -4421,6 +4466,7 @@ dependencies = [ "bytes", "clap", "futures", + "serde_json", "tokio", "tokio-stream", "tracing", @@ -4440,6 +4486,7 @@ dependencies = [ "clap", "futures", "hotpath", + "serde_json", "tokio", "tracing", "tracing-subscriber", @@ -4474,9 +4521,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.116" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3df424c70518695237746f84cede799c9c58fcb37450d7b23716568cc8bc69cb" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -4503,7 +4550,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4545,19 +4592,19 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.13.4" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1dd07eb858a2067e2f3c7155d54e929265c264e6f37efe3ee7a8d1b5a1dd0ba" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tempfile" -version = "3.25.0" +version = "3.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1" +checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" dependencies = [ "fastrand", "once_cell", - "rustix 1.1.3", + "rustix 1.1.4", "windows-sys 0.61.2", ] @@ -4609,7 +4656,7 @@ checksum = "be35209fd0781c5401458ab66e4f98accf63553e8fae7425503e92fdd319783b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4638,7 +4685,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4649,7 +4696,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4752,9 +4799,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.49.0" +version = "1.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" +checksum = "27ad5e34374e03cfffefc301becb44e9dc3c17584f414349ebe29ed26661822d" dependencies = [ "bytes", "libc", @@ -4768,13 +4815,13 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -4794,7 +4841,7 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ - "rustls 0.23.36", + "rustls 0.23.37", "tokio", ] @@ -4855,7 +4902,7 @@ dependencies = [ "indexmap 2.13.0", "serde_core", "serde_spanned", - "toml_datetime", + "toml_datetime 0.7.5+spec-1.1.0", "toml_parser", "toml_writer", "winnow", @@ -4870,23 +4917,32 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_datetime" +version = "1.0.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +dependencies = [ + "serde_core", +] + [[package]] name = "toml_edit" -version = "0.23.10+spec-1.0.0" +version = "0.25.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" +checksum = "7193cbd0ce53dc966037f54351dbbcf0d5a642c7f0038c382ef9e677ce8c13f2" dependencies = [ "indexmap 2.13.0", - "toml_datetime", + "toml_datetime 1.0.0+spec-1.1.0", "toml_parser", "winnow", ] [[package]] name = "toml_parser" -version = "1.0.8+spec-1.1.0" +version = "1.0.9+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0742ff5ff03ea7e67c8ae6c93cac239e0d9784833362da3f9a9c1da8dfefcbdc" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" dependencies = [ "winnow", ] @@ -4970,7 +5026,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5087,9 +5143,9 @@ checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "537dd038a89878be9b64dd4bd1b260315c1bb94f4d784956b81e27a088d9a09e" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-width" @@ -5129,7 +5185,7 @@ checksum = "3b5bb2756c16fb66f80cfbf5fb0e0c09a7001e739f453c9ec241b9c8b1556fda" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -5168,11 +5224,11 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.21.0" +version = "1.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b672338555252d43fd2240c714dc444b8c6fb0a5c5335e65a07bba7742735ddb" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" dependencies = [ - "getrandom 0.4.1", + "getrandom 0.4.2", "js-sys", "wasm-bindgen", ] @@ -5197,7 +5253,7 @@ checksum = "8c44ce98e7227a04eeb4cf9c784109a5c9710e54849ceb4f09f8597247897f1e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "unzip-n", ] @@ -5311,7 +5367,7 @@ dependencies = [ "clap", "quinn", "rcgen", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tracing", "tracing-subscriber", @@ -5329,7 +5385,7 @@ dependencies = [ "futures", "quinn", "rcgen", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tracing", "tracing-subscriber", @@ -5396,7 +5452,7 @@ dependencies = [ "clap", "futures", "quinn", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tower", "tower-http", @@ -5435,9 +5491,9 @@ dependencies = [ [[package]] name = "wasi-preview1-component-adapter-provider" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9dd9d6d3211a4f0109862b49dc1de3b7148cc5cdc272cb1700684c9c65f8a0b" +checksum = "b6cd4b9bce6eb3f96748b3f2b4436f44a6c32628158434b27e05fc7e05149480" [[package]] name = "wasip2" @@ -5459,9 +5515,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" +checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" dependencies = [ "cfg-if", "once_cell", @@ -5472,9 +5528,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.58" +version = "0.4.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a6e77fd0ae8029c9ea0063f87c46fde723e7d887703d74ad2616d792e51e6f" +checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8" dependencies = [ "cfg-if", "futures-util", @@ -5486,9 +5542,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" +checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5496,22 +5552,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" +checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.108" +version = "0.2.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" +checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" dependencies = [ "unicode-ident", ] @@ -5711,9 +5767,9 @@ dependencies = [ [[package]] name = "wasmtime" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19f56cece843fa95dd929f5568ff8739c7e3873b530ceea9eda2aa02a0b4142" +checksum = "e2a83182bf04af87571b4c642300479501684f26bab5597f68f68cded5b098fd" dependencies = [ "addr2line", "anyhow", @@ -5737,7 +5793,7 @@ dependencies = [ "postcard", "pulley-interpreter", "rayon", - "rustix 1.1.3", + "rustix 1.1.4", "semver", "serde", "serde_derive", @@ -5765,9 +5821,9 @@ dependencies = [ [[package]] name = "wasmtime-cli-flags" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f0d01da6dc262995bfef315ac8ba903dce20080fe841de738426353f32bd84" +checksum = "d1dbf222d548262f720894bfac24583e5b25ab242a572e7e01aafa09ab30446e" dependencies = [ "anyhow", "clap", @@ -5780,9 +5836,9 @@ dependencies = [ [[package]] name = "wasmtime-environ" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bf9dff572c950258548cbbaf39033f68f8dcd0b43b22e80def9fe12d532d3e5" +checksum = "cb201c41aa23a3642365cfb2e4a183573d85127a3c9d528f56b9997c984541ab" dependencies = [ "anyhow", "cpp_demangle", @@ -5807,15 +5863,15 @@ dependencies = [ [[package]] name = "wasmtime-internal-cache" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f52a985f5b5dae53147fc596f3a313c334e2c24fd1ba708634e1382f6ecd727" +checksum = "fb5b3069d1a67ba5969d0eb1ccd7e141367d4e713f4649aa90356c98e8f19bea" dependencies = [ "base64 0.22.1", "directories-next", "log", "postcard", - "rustix 1.1.3", + "rustix 1.1.4", "serde", "serde_derive", "sha2", @@ -5827,14 +5883,14 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-macro" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7920dc7dcb608352f5fe93c52582e65075b7643efc5dac3fc717c1645a8d29a0" +checksum = "0c924400db7b6ca996fef1b23beb0f41d5c809836b1ec60fc25b4057e2d25d9b" dependencies = [ "anyhow", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wasmtime-internal-component-util", "wasmtime-internal-wit-bindgen", "wit-parser 0.243.0", @@ -5842,15 +5898,15 @@ dependencies = [ [[package]] name = "wasmtime-internal-component-util" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "066f5aed35aa60580a2ac0df145c0f0d4b04319862fee1d6036693e1cca43a12" +checksum = "7d3f65daf4bf3d74ca2fbbe20af0589c42e2b398a073486451425d94fd4afef4" [[package]] name = "wasmtime-internal-cranelift" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afb8002dc415b7773d7949ee360c05ee8f91627ec25a7a0b01ee03831bdfdda1" +checksum = "633e889cdae76829738db0114ab3b02fce51ea4a1cd9675a67a65fce92e8b418" dependencies = [ "cfg-if", "cranelift-codegen", @@ -5875,14 +5931,14 @@ dependencies = [ [[package]] name = "wasmtime-internal-fiber" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9c562c5a272bc9f615d8f0c085a4360bafa28eef9aa5947e63d204b1129b22" +checksum = "deb126adc5d0c72695cfb77260b357f1b81705a0f8fa30b3944e7c2219c17341" dependencies = [ "cc", "cfg-if", "libc", - "rustix 1.1.3", + "rustix 1.1.4", "wasmtime-environ", "wasmtime-internal-versioned-export-macros", "windows-sys 0.61.2", @@ -5890,21 +5946,21 @@ dependencies = [ [[package]] name = "wasmtime-internal-jit-debug" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db673148f26e1211db3913c12c75594be9e3858a71fa297561e9162b1a49cfb0" +checksum = "8e66ff7f90a8002187691ff6237ffd09f954a0ebb9de8b2ff7f5c62632134120" dependencies = [ "cc", "object", - "rustix 1.1.3", + "rustix 1.1.4", "wasmtime-internal-versioned-export-macros", ] [[package]] name = "wasmtime-internal-jit-icache-coherence" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bada5ca1cc47df7d14100e2254e187c2486b426df813cea2dd2553a7469f7674" +checksum = "4b96df23179ae16d54fb3a420f84ffe4383ec9dd06fad3e5bc782f85f66e8e08" dependencies = [ "anyhow", "cfg-if", @@ -5914,24 +5970,24 @@ dependencies = [ [[package]] name = "wasmtime-internal-math" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf6f615d528eda9adc6eefb062135f831b5215c348f4c3ec3e143690c730605b" +checksum = "86d1380926682b44c383e9a67f47e7a95e60c6d3fa8c072294dab2c7de6168a0" dependencies = [ "libm", ] [[package]] name = "wasmtime-internal-slab" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da169d4f789b586e1b2612ba8399c653ed5763edf3e678884ba785bb151d018f" +checksum = "9b63cbea1c0192c7feb7c0dfb35f47166988a3742f29f46b585ef57246c65764" [[package]] name = "wasmtime-internal-unwinder" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4888301f3393e4e8c75c938cce427293fade300fee3fc8fd466fdf3e54ae068e" +checksum = "f25c392c7e5fb891a7416e3c34cfbd148849271e8c58744fda875dde4bec4d6a" dependencies = [ "cfg-if", "cranelift-codegen", @@ -5942,20 +5998,20 @@ dependencies = [ [[package]] name = "wasmtime-internal-versioned-export-macros" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63ba3124cc2cbcd362672f9f077303ccc4cd61daa908f73447b7fdaece75ff9f" +checksum = "70f8b9796a3f0451a7b702508b303d654de640271ac80287176de222f187a237" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] name = "wasmtime-internal-winch" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90a4182515dabba776656de4ebd62efad03399e261cf937ecccb838ce8823534" +checksum = "c0063e61f1d0b2c20e9cfc58361a6513d074a23c80b417aac3033724f51648a0" dependencies = [ "cranelift-codegen", "gimli", @@ -5970,9 +6026,9 @@ dependencies = [ [[package]] name = "wasmtime-internal-wit-bindgen" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87acbd416227cdd279565ba49e57cf7f08d112657c3b3f39b70250acdfd094fe" +checksum = "587699ca7cae16b4a234ffcc834f37e75675933d533809919b52975f5609e2ef" dependencies = [ "anyhow", "bitflags 2.11.0", @@ -5983,9 +6039,9 @@ dependencies = [ [[package]] name = "wasmtime-wasi" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9a1bdb4948463ed22559a640e687fed0df50b66353144aa6a9496c041ecd927" +checksum = "fc2eb9dc95baed3cd86fdfebf9f9f333337eb308bf8bd973e0c7b06d9418c35f" dependencies = [ "anyhow", "async-trait", @@ -6000,7 +6056,7 @@ dependencies = [ "futures", "io-extras", "io-lifetimes", - "rustix 1.1.3", + "rustix 1.1.4", "system-interface", "thiserror 2.0.18", "tokio", @@ -6013,9 +6069,9 @@ dependencies = [ [[package]] name = "wasmtime-wasi-http" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2cbf108a4775209cd199416b5431fcca2d475e12a02e84aa4ca72edcb1a449c" +checksum = "18b7e0e450995808122674d5da29859c622f7d3de606542492338ba861e64f0f" dependencies = [ "anyhow", "async-trait", @@ -6037,9 +6093,9 @@ dependencies = [ [[package]] name = "wasmtime-wasi-io" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7873d8b990d3cf1105ef491abf2b3cf1e19ff6722d24d5ca662026ea082cdff" +checksum = "a0b8402f1e04385071fdd96aca97cba995d7376b572e42ce5841d5b6aaf6fa30" dependencies = [ "anyhow", "async-trait", @@ -6072,9 +6128,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.85" +version = "0.3.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "312e32e551d92129218ea9a2452120f4aabc03529ef03e4d0d82fb2780608598" +checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9" dependencies = [ "js-sys", "wasm-bindgen", @@ -6150,9 +6206,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winch-codegen" -version = "41.0.3" +version = "41.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4f31dcfdfaf9d6df9e1124d7c8ee6fc29af5b99b89d11ae731c138e0f5bd77b" +checksum = "c55de3ac5b8bd71e5f6c87a9e511dd3ceb194bdb58183c6a7bf21cd8c0e46fbc" dependencies = [ "anyhow", "cranelift-assembler-x64", @@ -6189,7 +6245,7 @@ checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6200,7 +6256,7 @@ checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -6526,9 +6582,9 @@ checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" dependencies = [ "memchr", ] @@ -6614,7 +6670,7 @@ dependencies = [ "heck", "indexmap 2.13.0", "prettyplease", - "syn 2.0.116", + "syn 2.0.117", "wasm-metadata 0.238.1", "wit-bindgen-core 0.45.1", "wit-component 0.238.1", @@ -6630,7 +6686,7 @@ dependencies = [ "heck", "indexmap 2.13.0", "prettyplease", - "syn 2.0.116", + "syn 2.0.117", "wasm-metadata 0.244.0", "wit-bindgen-core 0.51.0", "wit-component 0.244.0", @@ -6646,7 +6702,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wit-bindgen-core 0.45.1", "wit-bindgen-rust 0.45.1", ] @@ -6661,7 +6717,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wit-bindgen-core 0.51.0", "wit-bindgen-rust 0.51.0", ] @@ -6706,7 +6762,7 @@ dependencies = [ "prettyplease", "serde", "serde_json", - "syn 2.0.116", + "syn 2.0.117", "test-helpers", "tokio", "wit-bindgen-core 0.36.0", @@ -6723,7 +6779,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "wit-bindgen-core 0.36.0", "wit-bindgen-wrpc-rust", ] @@ -6972,7 +7028,7 @@ dependencies = [ "async-nats", "quinn", "rcgen", - "rustls 0.23.36", + "rustls 0.23.37", "tokio", "tracing", "wrpc-cli", @@ -7057,8 +7113,8 @@ dependencies = [ "futures", "hotpath", "nuid", + "postcard", "serde", - "serde_json", "tokio", "tokio-stream", "tokio-util", @@ -7161,7 +7217,7 @@ dependencies = [ "pem", "quinn", "rcgen", - "rustls 0.23.36", + "rustls 0.23.37", "rustls-native-certs 0.8.3", "rustls-pemfile", "rustls-pki-types", @@ -7233,7 +7289,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure", ] @@ -7449,7 +7505,7 @@ checksum = "b760a458cd906ac888b37fd1abdb21a0f58ecc64cc3882f83a976cb5ca8e0632" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "zenoh-keyexpr", ] @@ -7601,22 +7657,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.39" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d35d663eadb6c932438e763b262fe1a70987f9ae936e60158176d710cae4a" +checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.39" +version = "0.8.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4122cd3169e94605190e77839c9a40d40ed048d305bfdc146e7df40ab0f3e517" +checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] @@ -7636,7 +7692,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", "synstructure", ] @@ -7676,7 +7732,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.116", + "syn 2.0.117", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index cf6f57b00..3a1834907 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,9 +85,7 @@ wrpc-transport-nats = { workspace = true, optional = true } wrpc-transport-quic = { workspace = true, optional = true } wrpc-transport-web = { workspace = true, optional = true } wrpc-wasmtime-cli = { workspace = true, optional = true } -wrpc-transport-zenoh = { workspace = true, features = [ - "zenoh-1_5_0", -], optional = true } +wrpc-transport-zenoh = { workspace = true, optional = true } zenoh = { workspace = true, optional = true } [dev-dependencies] @@ -195,5 +193,6 @@ wrpc-wasi-keyvalue-mem = { version = "0.2", path = "./crates/wasi-keyvalue-mem", wrpc-wasi-keyvalue-redis = { version = "0.2", path = "./crates/wasi-keyvalue-redis", default-features = false } wrpc-wasmtime-cli = { version = "0.9", path = "./crates/wasmtime-cli", default-features = false } wtransport = { version = "0.6.1", default-features = false } -zenoh = {version = "1.5.0", default-features = false} -flume = {version = "0.11.0", default-features = false} +zenoh = {version = "1.7", default-features = false} +flume = {version = "0.11", default-features = false} +postcard = {version = "1.1"} diff --git a/benches/reactor/Cargo.toml b/benches/reactor/Cargo.toml index da8745740..279ec6c91 100644 --- a/benches/reactor/Cargo.toml +++ b/benches/reactor/Cargo.toml @@ -9,7 +9,7 @@ license.workspace = true repository.workspace = true [lib] -crate-type = ["rlib", "cdylib"] +crate-type = ["rlib"] [dependencies] wit-bindgen = { workspace = true, features = ["macros", "realloc"] } diff --git a/crates/cli/src/zenoh.rs b/crates/cli/src/zenoh.rs index a9c2c2784..9fc6a4dab 100644 --- a/crates/cli/src/zenoh.rs +++ b/crates/cli/src/zenoh.rs @@ -2,7 +2,10 @@ use zenoh::{Config, Session}; /// Open a regular Zenoh session with configs supplied by an environment variable. pub async fn connect() -> anyhow::Result { - let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + let cfg = match Config::from_env() { + Ok(cfg) => cfg, + Err(_) => Config::default(), + }; let session = zenoh::open(cfg) .await.unwrap(); diff --git a/crates/test/Cargo.toml b/crates/test/Cargo.toml index b505f4529..24054c88b 100644 --- a/crates/test/Cargo.toml +++ b/crates/test/Cargo.toml @@ -34,5 +34,5 @@ tokio = { workspace = true, features = ["net", "process", "rt-multi-thread"] } tracing = { workspace = true } wrpc-cli = { workspace = true } wtransport = { workspace = true, features = ["ring"], optional = true } -wrpc-transport-zenoh = { workspace = true, features = [ "zenoh-1_5_0",], optional = true } +wrpc-transport-zenoh = { workspace = true, optional = true } zenoh = { workspace = true, optional = true } diff --git a/crates/test/src/lib.rs b/crates/test/src/lib.rs index 3942087f9..ef1709b0d 100644 --- a/crates/test/src/lib.rs +++ b/crates/test/src/lib.rs @@ -136,7 +136,10 @@ pub async fn start_zenoh() -> anyhow::Result<( .context("failed to start zenohd server")?; // connect to zenoh - let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + let cfg = match Config::from_env() { + Ok(cfg) => cfg, + Err(_) => Config::default(), + }; let session = zenoh::open(cfg) .await diff --git a/crates/transport-zenoh/Cargo.toml b/crates/transport-zenoh/Cargo.toml index f7284f7e2..500aa3c05 100644 --- a/crates/transport-zenoh/Cargo.toml +++ b/crates/transport-zenoh/Cargo.toml @@ -10,7 +10,6 @@ license.workspace = true repository.workspace = true [features] -default = ["zenoh-1_5_0"] hotpath = ["hotpath/hotpath"] hotpath-alloc = ["hotpath/hotpath-alloc"] @@ -25,9 +24,9 @@ tokio-util = { workspace = true, features = ["codec", "io"] } tracing = { workspace = true, features = ["attributes"] } wasm-tokio = { workspace = true } wrpc-transport = { workspace = true } -zenoh-1_5_0 = { package = "zenoh", version = "1.5.0", default-features = false, optional = true } -serde_json = { workspace = true } +zenoh = { workspace = true } serde = { workspace = true } uuid = { workspace = true } flume = { workspace = true } -hotpath = "0.9" +postcard = {workspace = true, features = ["use-std"]} +hotpath = "0.13.0" diff --git a/crates/transport-zenoh/src/lib.rs b/crates/transport-zenoh/src/lib.rs index 8f2ad07fc..9e7735b1d 100644 --- a/crates/transport-zenoh/src/lib.rs +++ b/crates/transport-zenoh/src/lib.rs @@ -4,17 +4,13 @@ use anyhow::{anyhow, ensure, Context as _}; use wrpc_transport::Index; - -use zenoh_1_5_0::sample::Sample; -#[cfg(feature = "zenoh-1_5_0")] -use zenoh_1_5_0 as zenoh; +use zenoh::bytes::ZBytes; +use zenoh::sample::Sample; use core::ops::{Deref, DerefMut}; use std::iter::zip; use std::{io, mem}; -use zenoh::Session; -use zenoh::bytes::ZBytes; -use zenoh::Wait; +use zenoh::{Session, Wait}; use core::future::Future; use core::pin::{pin, Pin}; @@ -36,15 +32,9 @@ use tracing::{debug, error, instrument, trace, warn}; pub const PROTOCOL: &str = "wrpc.0.0.1"; -// wrpc_transport_zenoh.rs -// Minimal wRPC transport over Zenoh (no NATS extras) - -// ---------- Key helpers (slash-separated Zenoh style) ---------- -#[hotpath::measure] fn send_sync(session: &Session, key: &str, payload: &[u8]) -> io::Result<()> { - // Using the synchronous (blocking) API - // Note: session.put returns a builder; calling `.wait()` executes it synchronously. + // Using the synchronous (blocking) API due to some synchronization issue that nats handles session .put(key, payload) .wait() @@ -52,20 +42,7 @@ fn send_sync(session: &Session, key: &str, payload: &[u8]) -> io::Result<()> { Ok(()) } -#[hotpath::measure] -async fn publish_with_reply( - session: &zenoh::Session, - subject: String, - reply: String, - payload: Bytes, - ) -> Result<(), zenoh::Error> { - let zbytes = prepare_payload_zbytes(Some(reply), &payload, None, None); - session.put(subject, zbytes).await.unwrap(); - - Ok(()) - } -#[hotpath::measure] fn spawn_async(fut: impl Future + Send + 'static) { match tokio::runtime::Handle::try_current() { Ok(rt) => { @@ -80,21 +57,25 @@ fn spawn_async(fut: impl Future + Send + 'static) { } } +fn zbytes_as_bytes(zbytes: &ZBytes) -> Bytes { + // Get &ZBytes from the sample + let bytes = match zbytes.to_bytes() { + std::borrow::Cow::Borrowed(slice) => Bytes::copy_from_slice(slice), + std::borrow::Cow::Owned(vec) => Bytes::from(vec), + }; + + bytes +} + fn child_inbox(base: &str) -> String { - let base = if base.ends_with('/') { base } else { &format!("{base}/") }; + let base = if base.ends_with('/') { + base + } else { + &format!("{base}/") + }; format!("{base}{}", nuid::next()) } - -// fn new_inbox() -> String { -// let inbox = "_inbox/"; -// let id = nuid::next(); -// let mut s = String::with_capacity(inbox.len().saturating_add(id.len())); -// s.push_str(inbox); -// s.push_str(&id); -// s -// } - #[must_use] #[inline] pub fn param_subject(prefix: &str) -> String { @@ -166,10 +147,9 @@ fn corrupted_memory_error() -> std::io::Error { std::io::Error::other("corrupted memory state") } - /// Transport subscriber pub struct Subscriber { - rx: ReceiverStream, + rx: ReceiverStream, subject: String, commands: mpsc::Sender, tasks: Arc>, @@ -193,7 +173,7 @@ impl Drop for Subscriber { #[hotpath::measure_all] impl Deref for Subscriber { - type Target = ReceiverStream; + type Target = ReceiverStream; fn deref(&self) -> &Self::Target { &self.rx @@ -207,23 +187,12 @@ impl DerefMut for Subscriber { } } - enum Command { - Subscribe(String, mpsc::Sender), + Subscribe(String, mpsc::Sender), Unsubscribe(String), Batch(Box<[Command]>, oneshot::Sender<()>), } - -/// Subset of [`async_nats::Message`](async_nats::Message) used by this crate -pub struct Message { - subject: String, - reply: Option, - payload: Bytes, - status: Option, - description: Option, -} - #[derive(Clone, Debug)] pub struct Client { session: Arc, @@ -234,110 +203,6 @@ pub struct Client { tasks: Arc>, } -#[hotpath::measure] -fn parse_zbytes_message(sample: Sample) -> (String, Option, Bytes, Option, Option) { - let key = sample.key_expr().as_str().to_string(); - let zbytes = sample.payload(); - - let bytes = zbytes.to_bytes(); - let mut cursor = 0; - - // Decode reply - let reply = if cursor < bytes.len() && bytes[cursor] == 1 { - cursor += 1; - let len = u32::from_le_bytes([bytes[cursor], bytes[cursor+1], bytes[cursor+2], bytes[cursor+3]]) as usize; - cursor += 4; - let reply_str = String::from_utf8_lossy(&bytes[cursor..cursor+len]).into_owned(); - cursor += len; - Some(reply_str) - } else { - cursor += 1; - None - }; - - // Decode status - let status = if cursor < bytes.len() && bytes[cursor] == 1 { - cursor += 1; - let len = u32::from_le_bytes([bytes[cursor], bytes[cursor+1], bytes[cursor+2], bytes[cursor+3]]) as usize; - cursor += 4; - let status_str = String::from_utf8_lossy(&bytes[cursor..cursor+len]).into_owned(); - cursor += len; - Some(status_str) - } else { - cursor += 1; - None - }; - - // Decode description - let description = if cursor < bytes.len() && bytes[cursor] == 1 { - cursor += 1; - let len = u32::from_le_bytes([bytes[cursor], bytes[cursor+1], bytes[cursor+2], bytes[cursor+3]]) as usize; - cursor += 4; - let desc_str = String::from_utf8_lossy(&bytes[cursor..cursor+len]).into_owned(); - cursor += len; - Some(desc_str) - } else { - cursor += 1; - None - }; - - // Remaining bytes are payload - let payload = if cursor < bytes.len() { - Bytes::copy_from_slice(&bytes[cursor..]) - } else { - Bytes::new() - }; - - (key, reply, payload, status, description) -} - -#[hotpath::measure] -fn prepare_payload_zbytes( - reply: Option, - payload: &[u8], - status: Option, - description: Option -) -> ZBytes { - // use std::io::Write; - - let mut buf = Vec::new(); - - // Encode reply - if let Some(reply) = reply { - buf.push(1u8); // has_reply = true - let reply_bytes = reply.as_bytes(); - buf.extend_from_slice(&(reply_bytes.len() as u32).to_le_bytes()); - buf.extend_from_slice(reply_bytes); - } else { - buf.push(0u8); // has_reply = false - } - - // Encode status - if let Some(status) = status { - buf.push(1u8); - let status_bytes = status.as_bytes(); - buf.extend_from_slice(&(status_bytes.len() as u32).to_le_bytes()); - buf.extend_from_slice(status_bytes); - } else { - buf.push(0u8); - } - - // Encode description - if let Some(description) = description { - buf.push(1u8); - let desc_bytes = description.as_bytes(); - buf.extend_from_slice(&(desc_bytes.len() as u32).to_le_bytes()); - buf.extend_from_slice(desc_bytes); - } else { - buf.push(0u8); - } - - // Append payload - buf.extend_from_slice(payload); - - ZBytes::from(buf) -} - #[hotpath::measure_all] impl Client { pub async fn new( @@ -348,16 +213,17 @@ impl Client { let session: Arc = session.into(); let root = format!("_inbox/{}/", nuid::next()); let wildcard = format!("{root}**"); - let mut sub = session + let sub = session .declare_subscriber(wildcard) .with(flume::bounded(8192)) - .await.unwrap(); + .await + .unwrap(); let mut tasks = JoinSet::new(); let (cmd_tx, mut cmd_rx) = mpsc::channel(8192); tasks.spawn({ async move { - fn handle_command(subs: &mut HashMap>, cmd: Command) { + fn handle_command(subs: &mut HashMap>, cmd: Command) { //println!("Handle Command Called"); match cmd { Command::Subscribe(s, tx) => { @@ -379,13 +245,13 @@ impl Client { } async fn handle_message( - subs: &mut HashMap>, + subs: &mut HashMap>, sample: Sample, ) { //println!("Handle Command Called"); let key = sample.key_expr().clone().as_str().to_string(); // let msg = parse_message(sample); - + let Some(sub) = subs.get_mut(&key) else { debug!(?key, "drop message with no subscriber"); return; @@ -395,20 +261,8 @@ impl Client { subs.remove(&key); return; }; - - let (_key_parsed, - reply, - payload, - status, - description) = parse_zbytes_message(sample); - - sub.send(Message { - subject: key, - reply, - payload, - status, - description - }); + + sub.send(sample); } let mut subs = HashMap::new(); @@ -432,7 +286,6 @@ impl Client { } } - pub struct ByteSubscription(Subscriber); #[hotpath::measure_all] @@ -442,7 +295,7 @@ impl Stream for ByteSubscription { #[instrument(level = "trace", skip_all)] fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { match self.0.poll_next_unpin(cx) { - Poll::Ready(Some(Message { payload, .. })) => Poll::Ready(Some(Ok(payload))), + Poll::Ready(Some(sample)) => Poll::Ready(Some(Ok(zbytes_as_bytes(sample.payload())))), Poll::Ready(None) => Poll::Ready(None), Poll::Pending => Poll::Pending, } @@ -623,9 +476,6 @@ impl IndexTrie { } } - - - pub struct Reader { buffer: Bytes, incoming: Option, @@ -688,7 +538,8 @@ impl AsyncRead for Reader { }; trace!("polling for next message"); match incoming.poll_next_unpin(cx) { - Poll::Ready(Some(Message { mut payload, .. })) => { + Poll::Ready(Some(sample)) => { + let mut payload = zbytes_as_bytes(sample.payload()); trace!(?payload, "received message"); if payload.is_empty() { trace!("received stream shutdown message"); @@ -713,8 +564,6 @@ impl AsyncRead for Reader { } } - - #[derive(Clone, Debug)] pub struct SubjectWriter { session: Arc, @@ -752,22 +601,29 @@ impl wrpc_transport::Index for SubjectWriter { impl AsyncWrite for SubjectWriter { #[instrument(level = "trace", skip_all, ret, fields(subject = self.tx, buf = format!("{buf:02x?}")))] fn poll_write( - mut self: Pin<&mut Self>, - _cx: &mut Context<'_>, - buf: &[u8], + self: Pin<&mut Self>, + _cx: &mut Context<'_>, + buf: &[u8], ) -> Poll> { trace!("starting send"); - // let msg = prepare_payload_json(None, Bytes::copy_from_slice(buf), None, None); - let zbytes = prepare_payload_zbytes(None, buf, None, None); - let zbytes_bytes = zbytes.to_bytes(); + // let Ok(payload) = prepare_attachment_bytes(self.tx.clone(), None, buf, None, None) else { + // return Poll::Ready(Err(io::Error::new( + // io::ErrorKind::InvalidData, + // "Couldn't prepare payload as bytes", + // ))); + // }; let subject = &self.tx; let session = &self.session; - trace!("writing message synchronously: key={} size={}", subject, buf.len()); + trace!( + "writing message synchronously: key={} size={}", + subject, + buf.len() + ); - match send_sync(session, subject, &zbytes_bytes) { + match send_sync(session, subject, &buf) { Ok(()) => { trace!("put completed"); Poll::Ready(Ok(buf.len())) @@ -779,15 +635,14 @@ impl AsyncWrite for SubjectWriter { } } - #[instrument(level = "trace", skip_all, ret, fields(subject = self.tx))] - fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { trace!("flushing"); Poll::Ready(Ok(())) } #[instrument(level = "trace", skip_all, ret, fields(subject = self.tx))] - fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + fn poll_shutdown(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll> { trace!("writing stream shutdown message"); if !self.shutdown { let session = self.session.clone(); @@ -796,8 +651,7 @@ impl AsyncWrite for SubjectWriter { spawn_async(async move { trace!("writing stream shutdown message (explicit)"); - let zbytes = prepare_payload_zbytes(None, &[], None, None); - if let Err(err) = session.put(key, zbytes).await { + if let Err(err) = session.put(key, &[]).await { warn!(?err, "failed to publish stream shutdown message"); } }); @@ -815,8 +669,11 @@ impl Drop for SubjectWriter { let tasks = Arc::clone(&self.tasks); spawn_async(async move { trace!("writing stream shutdown message"); - let zbytes = prepare_payload_zbytes(None, &[],None, None); - if let Err(err) = session.put(key, zbytes).await { + // let Ok(payload) = prepare_attachment_bytes(key.clone(), None, &[], None, None) else { + // warn!("Couldn't prepare payload as bytes"); + // return (); + // }; + if let Err(err) = session.put(key, &[]).await { warn!(?err, "failed to publish stream shutdown message"); } drop(tasks); @@ -825,8 +682,6 @@ impl Drop for SubjectWriter { } } - - #[derive(Default)] pub enum RootParamWriter { #[default] @@ -867,9 +722,11 @@ fn map_status_to_error_kind(code: &str) -> Option { let c = code.trim(); match c { // Allow either symbolic names or common numeric equivalents - c if c.eq_ignore_ascii_case("NO_RESPONDERS") || c == "503" => Some(io::ErrorKind::NotConnected), - c if c.eq_ignore_ascii_case("TIMEOUT") || c == "408" => Some(io::ErrorKind::TimedOut), - c if c.eq_ignore_ascii_case("REQUEST_TERMINATED") => Some(io::ErrorKind::UnexpectedEof), + c if c.eq_ignore_ascii_case("NO_RESPONDERS") || c == "503" => { + Some(io::ErrorKind::NotConnected) + } + c if c.eq_ignore_ascii_case("TIMEOUT") || c == "408" => Some(io::ErrorKind::TimedOut), + c if c.eq_ignore_ascii_case("REQUEST_TERMINATED") => Some(io::ErrorKind::UnexpectedEof), _ => None, } } @@ -883,28 +740,26 @@ impl RootParamWriter { Self::Handshaking { sub, .. } => { trace!("polling for handshake response 1"); match sub.poll_next_unpin(cx) { - Poll::Ready(Some(Message { status: Some(code), description, .. })) => { - if let Some(kind) = map_status_to_error_kind(&code) { - return Poll::Ready(Err(kind.into())); - } - if !code.is_empty() { - let msg = match description { - Some(desc) if !desc.is_empty() => - format!("received a response with code `{code}` ({desc})"), - _ => - format!("received a response with code `{code}`"), - }; - return Poll::Ready(Err(io::Error::other(msg))); - } - // Empty status string: fall through to the generic error below - return Poll::Ready(Err(io::Error::new( - io::ErrorKind::InvalidInput, - "empty status string in handshake response", - ))); - } - Poll::Ready(Some(Message { - reply: Some(tx), .. - })) => { + // Poll::Ready(Some(sample) => { + // if let Some(kind) = map_status_to_error_kind(&code) { + // return Poll::Ready(Err(kind.into())); + // } + // if !code.is_empty() { + // let msg = match description { + // Some(desc) if !desc.is_empty() => { + // format!("received a response with code `{code}` ({desc})") + // } + // _ => format!("received a response with code `{code}`"), + // }; + // return Poll::Ready(Err(io::Error::other(msg))); + // } + // // Empty status string: fall through to the generic error below + // return Poll::Ready(Err(io::Error::new( + // io::ErrorKind::InvalidInput, + // "empty status string in handshake response", + // ))); + // } + Poll::Ready(Some(sample)) => { let Self::Handshaking { session, indexed, @@ -915,6 +770,17 @@ impl RootParamWriter { else { return Poll::Ready(Err(corrupted_memory_error())); }; + + let tx = match sample.attachment() { + Some(zbytes) => zbytes.try_to_string().unwrap().into_owned(), + None => { + return Poll::Ready(Err(std::io::Error::new( + std::io::ErrorKind::InvalidInput, + "peer did not specify a reply subject", + ))) + }, + }; + let tx = SubjectWriter::new(session, param_subject(&tx), tasks); let indexed = indexed .into_inner() @@ -934,10 +800,6 @@ impl RootParamWriter { self.poll_active(cx) } } - Poll::Ready(Some(..)) => Poll::Ready(Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "peer did not specify a reply subject", - ))), Poll::Ready(None) => { *self = Self::Corrupted; Poll::Ready(Err(std::io::Error::from(std::io::ErrorKind::BrokenPipe))) @@ -1054,7 +916,6 @@ pub enum IndexedParamWriter { Active(SubjectWriter), } - #[hotpath::measure_all] impl IndexedParamWriter { #[instrument(level = "trace", skip_all, ret)] @@ -1089,7 +950,6 @@ impl IndexedParamWriter { } } - #[hotpath::measure_all] impl wrpc_transport::Index for IndexedParamWriter { #[instrument(level = "trace", skip_all)] @@ -1113,7 +973,6 @@ impl wrpc_transport::Index for IndexedParamWriter { } } - #[hotpath::measure_all] impl AsyncWrite for IndexedParamWriter { #[instrument(level = "trace", skip_all, ret, fields(buf = format!("{buf:02x?}")))] @@ -1163,7 +1022,6 @@ impl AsyncWrite for IndexedParamWriter { } } - pub enum ParamWriter { Root(RootParamWriter), Nested(IndexedParamWriter), @@ -1223,7 +1081,7 @@ impl wrpc_transport::Invoke for Client { cx: Self::Context, instance: &str, func: &str, - mut params: Bytes, + params: Bytes, paths: impl AsRef<[P]> + Send, ) -> anyhow::Result<(Self::Outgoing, Self::Incoming)> { let paths = paths.as_ref(); @@ -1265,13 +1123,11 @@ impl wrpc_transport::Invoke for Client { let param_tx = invocation_subject(&self.prefix, instance, func); trace!("publishing handshake"); - publish_with_reply( - &self.session, - param_tx, - rx.clone(), - params) - .await.unwrap(); - + self.session.put(param_tx, params).attachment(rx.clone()).await.unwrap(); + // publish_with_reply(&self.session, param_tx, rx.clone(), params) + // .await + // .unwrap(); + // let session = Arc::clone(&self.session); // tokio::spawn(async move { // if let Err(err) = nats.flush().await { @@ -1310,15 +1166,14 @@ async fn handle_message( session: &zenoh::Session, rx: String, commands: mpsc::Sender, - Message { - reply: tx, - payload, - .. - }: Message, + sample: Sample, paths: &[Box<[Option]>], tasks: Arc>, ) -> anyhow::Result<((), SubjectWriter, Reader)> { - let tx = tx.clone(); + let tx = match sample.attachment() { + Some(zbytes) => zbytes.try_to_string().unwrap().into_owned(), + None => todo!(), + }; let mut cmds = Vec::with_capacity(paths.len().saturating_add(1)); @@ -1353,17 +1208,17 @@ async fn handle_message( ack_rx.await?; trace!("publishing handshake response"); - publish_with_reply(session, tx.clone().unwrap(), rx, Bytes::default()) - .await.unwrap(); + + session.put(tx.clone(), Bytes::default()).attachment(rx.clone()).await.unwrap(); Ok(( (), SubjectWriter::new( session.clone().into(), - result_subject(&tx.unwrap()), + result_subject(&tx), Arc::clone(&tasks), ), Reader { - buffer: payload, + buffer: zbytes_as_bytes(sample.payload()), incoming: Some(Subscriber { rx: ReceiverStream::new(param_rx), commands, @@ -1407,24 +1262,20 @@ impl wrpc_transport::Serve for Client { |(sub, session, paths, commands, tasks, inbox_root)| async move { match sub.recv_async().await { Ok(sample) => { - let (subject, - reply, - payload, - status, - description) = parse_zbytes_message(sample); - - let message = Message { - subject, - reply, - payload, - status, - description, - }; + // let Ok(message) = parse_bytes_message(sample) else { + // return None; + // }; - let rx = child_inbox(inbox_root.as_ref()); + let rx = child_inbox(inbox_root.as_ref()); let item = handle_message( - &session, rx, commands.clone(), message, &paths, Arc::clone(&tasks) - ).await; + &session, + rx, + commands.clone(), + sample, + &paths, + Arc::clone(&tasks), + ) + .await; // put `inboxroot` back into state for the next loop Some((item, (sub, session, paths, commands, tasks, inbox_root))) diff --git a/crates/wasmtime-cli/Cargo.toml b/crates/wasmtime-cli/Cargo.toml index d547b58c6..3e232547a 100644 --- a/crates/wasmtime-cli/Cargo.toml +++ b/crates/wasmtime-cli/Cargo.toml @@ -69,6 +69,6 @@ wit-component = { workspace = true } wrpc-cli = { workspace = true, features = ["nats"] } wrpc-transport-nats = { workspace = true } wrpc-transport = { workspace = true, features = ["net"] } -wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } +wrpc-transport-zenoh = { workspace = true } wrpc-runtime-wasmtime = { workspace = true } zenoh = { workspace = true } \ No newline at end of file diff --git a/examples/rust/hello-zenoh-client/Cargo.toml b/examples/rust/hello-zenoh-client/Cargo.toml index caf6d67ea..b70643a59 100644 --- a/examples/rust/hello-zenoh-client/Cargo.toml +++ b/examples/rust/hello-zenoh-client/Cargo.toml @@ -24,4 +24,5 @@ tokio = { workspace = true, features = ["rt-multi-thread"] } tracing-subscriber = { workspace = true, features = ["ansi", "fmt"] } url = { workspace = true } wit-bindgen-wrpc = { workspace = true } -wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } +wrpc-transport-zenoh = { workspace = true } +serde_json = {workspace = true} diff --git a/examples/rust/hello-zenoh-client/src/main.rs b/examples/rust/hello-zenoh-client/src/main.rs index 7abbe08c5..37c8f6a53 100644 --- a/examples/rust/hello-zenoh-client/src/main.rs +++ b/examples/rust/hello-zenoh-client/src/main.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use anyhow::Context as _; use zenoh::{Config}; use std::time::Instant; +use serde_json::json; mod bindings { wit_bindgen_wrpc::generate!({ @@ -16,7 +17,20 @@ mod bindings { async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt().init(); - let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + let cfg = match Config::from_env() { + Ok(cfg) => cfg, + Err(_) => { + let mut config = Config::default(); + // Set mode + config.insert_json5("mode", &json!("peer").to_string()).unwrap(); + config.insert_json5( + "connect/endpoints", + &json!(["tcp/0.0.0.0:7447"]).to_string(), + ).unwrap(); + + config + }, + }; let session = zenoh::open(cfg) .await diff --git a/examples/rust/hello-zenoh-server/Cargo.toml b/examples/rust/hello-zenoh-server/Cargo.toml index 02679ae94..fe2ada703 100644 --- a/examples/rust/hello-zenoh-server/Cargo.toml +++ b/examples/rust/hello-zenoh-server/Cargo.toml @@ -26,8 +26,9 @@ tracing = { workspace = true } tracing-subscriber = { workspace = true, features = ["ansi", "fmt"] } url = { workspace = true } wit-bindgen-wrpc = { workspace = true } -wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } -hotpath = "0.9" +wrpc-transport-zenoh = { workspace = true } +serde_json = {workspace = true} +hotpath = "0.13.0" [features] hotpath = ["hotpath/hotpath"] diff --git a/examples/rust/hello-zenoh-server/src/main.rs b/examples/rust/hello-zenoh-server/src/main.rs index 6a0bc8759..7d0d7e83d 100644 --- a/examples/rust/hello-zenoh-server/src/main.rs +++ b/examples/rust/hello-zenoh-server/src/main.rs @@ -4,6 +4,7 @@ use std::sync::Arc; use anyhow::Context as _; use futures::stream::select_all; use futures::StreamExt as _; +use serde_json::json; use tokio::task::JoinSet; use tokio::{select, signal}; use tracing::{debug, error, info, warn}; @@ -37,7 +38,20 @@ impl bindings::exports::wrpc_examples::hello::handler::Handler<()> async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt().init(); - let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + let cfg = match Config::from_env() { + Ok(cfg) => cfg, + Err(_) => { + let mut config = Config::default(); + // Set mode + config.insert_json5("mode", &json!("peer").to_string()).unwrap(); + config.insert_json5( + "connect/endpoints", + &json!(["tcp/0.0.0.0:7447"]).to_string(), + ).unwrap(); + + config + }, + }; let session = zenoh::open(cfg) .await diff --git a/examples/rust/streams-zenoh-client/Cargo.toml b/examples/rust/streams-zenoh-client/Cargo.toml index 698874803..21d6904c3 100644 --- a/examples/rust/streams-zenoh-client/Cargo.toml +++ b/examples/rust/streams-zenoh-client/Cargo.toml @@ -32,4 +32,5 @@ tracing-subscriber = { workspace = true, features = [ ] } url = { workspace = true } wit-bindgen-wrpc = { workspace = true } -wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } +wrpc-transport-zenoh = { workspace = true } +serde_json = {workspace = true} \ No newline at end of file diff --git a/examples/rust/streams-zenoh-server/Cargo.toml b/examples/rust/streams-zenoh-server/Cargo.toml index 3dbf317e1..89f7bd7ff 100644 --- a/examples/rust/streams-zenoh-server/Cargo.toml +++ b/examples/rust/streams-zenoh-server/Cargo.toml @@ -31,8 +31,9 @@ tracing-subscriber = { workspace = true, features = [ ] } url = { workspace = true } wit-bindgen-wrpc = { workspace = true } -wrpc-transport-zenoh = { workspace = true, features = ["zenoh-1_5_0"] } -hotpath = "0.9" +wrpc-transport-zenoh = { workspace = true } +serde_json = {workspace = true} +hotpath = "0.13.0" [features] hotpath = ["hotpath/hotpath"] diff --git a/tests/rust.rs b/tests/rust.rs index 3b25c5678..52d2cb513 100644 --- a/tests/rust.rs +++ b/tests/rust.rs @@ -7,6 +7,8 @@ use core::pin::pin; use core::str; use core::time::Duration; +use std::future::Future; +use std::pin::Pin; use std::sync::Arc; use std::thread; @@ -14,6 +16,7 @@ use anyhow::Context; use bytes::Bytes; use common::assert_async; use futures::{stream, FutureExt as _, Stream, StreamExt as _, TryStreamExt as _}; +use serial_test::serial; use tokio::sync::{oneshot, RwLock}; use tokio::time::sleep; use tokio::{join, select, spawn, try_join}; @@ -21,9 +24,6 @@ use tracing::{info, info_span, instrument, Instrument, Span}; use wrpc_transport::frame::{AcceptExt as _, Oneshot}; use wrpc_transport::{Accept, InvokeExt as _, ResourceBorrow, ResourceOwn, ServeExt as _}; -use zenoh::{Config}; -use serial_test::serial; - #[instrument(skip_all, ret)] async fn assert_bindgen_async(clt: Arc, srv: Arc) -> anyhow::Result<()> where @@ -1031,45 +1031,6 @@ where Ok(()) } -#[cfg(feature = "zenoh-transport")] -#[test_log::test(tokio::test(flavor = "multi_thread"))] -#[serial(zenoh_tests)] -#[instrument(ret)] -async fn rust_bindgen_zenoh_sync() -> anyhow::Result<()> { - wrpc_test::with_zenoh(|_, zenoh_client| async { - let clt = Arc::new(zenoh_client); - assert_bindgen_sync(Arc::clone(&clt), clt).await - }) - .await -} - -#[cfg(feature = "zenoh-transport")] -#[test_log::test(tokio::test(flavor = "multi_thread"))] -#[serial(zenoh_tests)] -#[instrument(ret)] -async fn rust_bindgen_zenoh_async() -> anyhow::Result<()> { - wrpc_test::with_zenoh(|_, zenoh_client| { - async { - let clt = Arc::new(zenoh_client); - assert_bindgen_async(Arc::clone(&clt), clt).await - } - .in_current_span() - }) - .await -} - -#[cfg(feature = "zenoh-transport")] -#[test_log::test(tokio::test(flavor = "multi_thread"))] -#[serial(zenoh_tests)] -#[instrument(ret)] -async fn rust_dynamic_zenoh() -> anyhow::Result<()> { - wrpc_test::with_zenoh(|_, zenoh_client| async { - let clt = Arc::new(zenoh_client); - assert_dynamic(Arc::clone(&clt), clt).await - }) - .await -} - #[cfg(feature = "nats")] #[test_log::test(tokio::test(flavor = "multi_thread"))] #[instrument(ret)] @@ -1309,6 +1270,45 @@ async fn rust_dynamic_web_transport() -> anyhow::Result<()> { .await } +#[cfg(feature = "zenoh-transport")] +#[test_log::test(tokio::test(flavor = "multi_thread"))] +#[serial(zenoh_tests)] +#[instrument(ret)] +async fn rust_bindgen_zenoh_sync() -> anyhow::Result<()> { + wrpc_test::with_zenoh(|_, zenoh_client| async { + let clt = Arc::new(zenoh_client); + assert_bindgen_sync(Arc::clone(&clt), clt).await + }) + .await +} + +#[cfg(feature = "zenoh-transport")] +#[test_log::test(tokio::test(flavor = "multi_thread"))] +#[serial(zenoh_tests)] +#[instrument(ret)] +async fn rust_bindgen_zenoh_async() -> anyhow::Result<()> { + wrpc_test::with_zenoh(|_, zenoh_client| { + async { + let clt = Arc::new(zenoh_client); + assert_bindgen_async(Arc::clone(&clt), clt).await + } + .in_current_span() + }) + .await +} + +#[cfg(feature = "zenoh-transport")] +#[test_log::test(tokio::test(flavor = "multi_thread"))] +#[serial(zenoh_tests)] +#[instrument(ret)] +async fn rust_dynamic_zenoh() -> anyhow::Result<()> { + wrpc_test::with_zenoh(|_, zenoh_client| async { + let clt = Arc::new(zenoh_client); + assert_dynamic(Arc::clone(&clt), clt).await + }) + .await +} + #[test_log::test(tokio::test(flavor = "multi_thread"))] #[instrument(ret)] async fn rust_bindgen_tcp_sync() -> anyhow::Result<()> { @@ -1530,4 +1530,4 @@ async fn rust_bindgen_uds_async() -> anyhow::Result<()> { } } } -} +} \ No newline at end of file diff --git a/zenoh_conf.json5 b/zenoh_conf.json5 deleted file mode 100644 index 6eaf1386b..000000000 --- a/zenoh_conf.json5 +++ /dev/null @@ -1,7 +0,0 @@ -{ - "mode": "client", - "connect": { - "endpoints": ["tcp/0.0.0.0:7447"] - } -} - \ No newline at end of file diff --git a/zenoh_conf.json5.template b/zenoh_conf.json5.template deleted file mode 100644 index c6ac22108..000000000 --- a/zenoh_conf.json5.template +++ /dev/null @@ -1,6 +0,0 @@ -{ - mode: "client", - listen: { - endpoints: ["tcp/172.21.8.176:7447"], - }, -} \ No newline at end of file From c2f7112015274ecf7f12002b992ce619b976913f Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 9 Mar 2026 12:56:49 +0100 Subject: [PATCH 3/7] fixed zenoh tests, zenohd now runs on dynamic ports --- Cargo.lock | 8 +- README.md | 123 ++++++++++++++++++ crates/cli/Cargo.toml | 1 + crates/cli/src/zenoh.rs | 22 +++- crates/test/Cargo.toml | 1 + crates/test/src/lib.rs | 96 ++++++++++---- crates/transport-zenoh/src/lib.rs | 92 ++++--------- crates/wasmtime-cli/src/zenoh.rs | 2 +- examples/rust/hello-zenoh-client/Cargo.toml | 1 + examples/rust/hello-zenoh-client/src/main.rs | 93 +++---------- .../wit/deps/hello/hello.wit | 30 ----- examples/rust/hello-zenoh-server/Cargo.toml | 6 +- examples/rust/hello-zenoh-server/src/main.rs | 41 ++---- .../wit/deps/hello/hello.wit | 30 ----- examples/rust/streams-zenoh-client/Cargo.toml | 3 +- .../rust/streams-zenoh-client/src/main.rs | 32 +++-- examples/rust/streams-zenoh-server/Cargo.toml | 6 +- .../rust/streams-zenoh-server/src/main.rs | 41 +++--- flake.nix | 3 + tests/rust.rs | 25 ++-- 20 files changed, 337 insertions(+), 319 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aee01cc85..1bc17789d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1914,6 +1914,7 @@ dependencies = [ "tracing-subscriber", "url", "wit-bindgen-wrpc", + "wrpc-cli", "wrpc-transport-zenoh", "zenoh", ] @@ -1925,13 +1926,13 @@ dependencies = [ "anyhow", "clap", "futures", - "hotpath", "serde_json", "tokio", "tracing", "tracing-subscriber", "url", "wit-bindgen-wrpc", + "wrpc-cli", "wrpc-transport-zenoh", "zenoh", ] @@ -4473,6 +4474,7 @@ dependencies = [ "tracing-subscriber", "url", "wit-bindgen-wrpc", + "wrpc-cli", "wrpc-transport-zenoh", "zenoh", ] @@ -4485,13 +4487,13 @@ dependencies = [ "bytes", "clap", "futures", - "hotpath", "serde_json", "tokio", "tracing", "tracing-subscriber", "url", "wit-bindgen-wrpc", + "wrpc-cli", "wrpc-transport-zenoh", "zenoh", ] @@ -6978,6 +6980,7 @@ version = "0.7.0" dependencies = [ "anyhow", "async-nats", + "serde_json", "tokio", "tracing-subscriber", "zenoh", @@ -7029,6 +7032,7 @@ dependencies = [ "quinn", "rcgen", "rustls 0.23.37", + "serde_json", "tokio", "tracing", "wrpc-cli", diff --git a/README.md b/README.md index d74e8b996..50dac8b33 100644 --- a/README.md +++ b/README.md @@ -230,6 +230,128 @@ We will use the following two Rust wRPC applications using [NATS.io] transport: wrpc-wasmtime nats run --import native ./target/wasm32-wasip2/release/hello-component-client.wasm ``` +#### Using [zenoh.io] transport + +We will use the following two Rust wRPC applications using [zenoh.io] transport: +- [examples/rust/hello-zenoh-client](examples/rust/hello-zenoh-client) +- [examples/rust/hello-zenoh-server](examples/rust/hello-zenoh-server) + +1. Run [zenoh.io] (more thorough documentation available [here](https://docs.nats.io/running-a-nats-service/introduction/running)): + + - using standalone binary: + ```sh + zenohd + ``` + + - using nix flake develop environment: + ```sh + nix develop + zenohd + ``` + +2. Serve Wasm `hello` server via [zenoh.io] + + ```sh + wrpc-wasmtime zenoh serve --export rust ./target/wasm32-wasip2/release/hello_component_server.wasm + ``` + + - Sample output: + > INFO async_nats: event: connected + > + > INFO wrpc_wasmtime_cli: serving instance function name="hello" + +3. Call Wasm `hello` server using a Wasm `hello` client via [zenoh.io]: + + ```sh + wrpc-wasmtime zenoh run --import rust ./target/wasm32-wasip2/release/hello-component-client.wasm + ``` + + - Sample output in the client: + > INFO async_nats: event: connected + > + >hello from Rust + + - Sample output in the server: + > INFO wrpc_wasmtime_cli: serving instance function invocation + > + > INFO wrpc_wasmtime_cli: successfully served instance function invocation + +4. Call the Wasm `hello` server using a native wRPC `hello` client via [zenoh.io]: + + ```sh + cargo run -p hello-zenoh-client rust + ``` + +5. Serve native wRPC `hello` server via [zenoh.io]: + + ```sh + cargo run -p hello-zenoh-server native + ``` + +6. Call both the native wRPC `hello` server and Wasm `hello` server using native wRPC `hello` client via [zenoh.io]: + + ```sh + cargo run -p hello-zenoh-client rust native + ``` + +7. Call native wRPC `hello` server using Wasm `hello` client via [zenoh.io]: + + ```sh + wrpc-wasmtime zenoh run --import native ./target/wasm32-wasip2/release/hello-component-client.wasm + ``` + + +To test the transport-zenoh package run: + + ```sh + cargo test zenoh -- --nocapture + ``` + + - Sample output: + > test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 13 filtered out; finished in 6.17s + +### Zenoh Configuration +By default we set Zenoh to run in **client mode**. In this mode it behaves +similarly to a typical NATS client: the application connects to a local +Zenoh router (`zenohd`) that acts as the message broker. + +The client attempts to connect to a `zenohd` instance running on the +**default Zenoh port (`7447`) on the same machine**. + +Zenohd has been +added to the flake nix file and is available after running nix develop in the +command lnine. + +This behavior can be altered by providing a **custom Zenoh configuration +file** and setting the `ZENOH_CONFIG` environment variable to its path. + +Example: + +``` bash +export ZENOH_CONFIG="/path/to/config/zenoh_conf.json5" +``` + + +When this environment variable is set, Zenoh will load the configuration +from the specified file instead of using the default settings. + +Example configuration: + +``` json +{ + "mode": "client", + "listen": { + "endpoints": ["tcp/0.0.0.0:7447"] + } +} +``` + + +More information about available configuration options and how to confige zenoh in peer mode can be found in +the official Zenoh configuration manual: + +https://zenoh.io/docs/manual/configuration/ + ## Repository structure This repository contains (for all supported languages): @@ -256,3 +378,4 @@ Whether you're a seasoned developer or just getting started, your contributions [Docker]: https://www.docker.com/ [NATS.io]: https://nats.io/ +[zenoh.io]: https://zenoh.io/ diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml index a87497830..ba7a3ff87 100644 --- a/crates/cli/Cargo.toml +++ b/crates/cli/Cargo.toml @@ -27,3 +27,4 @@ tracing-subscriber = { workspace = true, features = [ "tracing-log", ] } zenoh = { workspace = true, optional = true, features = ["transport_tcp"] } +serde_json = { workspace = true, default-features = false } \ No newline at end of file diff --git a/crates/cli/src/zenoh.rs b/crates/cli/src/zenoh.rs index 9fc6a4dab..22c6e1360 100644 --- a/crates/cli/src/zenoh.rs +++ b/crates/cli/src/zenoh.rs @@ -1,13 +1,27 @@ +use serde_json::json; use zenoh::{Config, Session}; /// Open a regular Zenoh session with configs supplied by an environment variable. pub async fn connect() -> anyhow::Result { let cfg = match Config::from_env() { Ok(cfg) => cfg, - Err(_) => Config::default(), + Err(_) => { + let mut config = Config::default(); + // Set mode + config + .insert_json5("mode", &json!("client").to_string()) + .unwrap(); + config + .insert_json5( + "connect/endpoints", + &json!(["tcp/0.0.0.0:7447"]).to_string(), + ) + .unwrap(); + + config + } }; - let session = zenoh::open(cfg) - .await.unwrap(); + let session = zenoh::open(cfg).await.unwrap(); Ok(session) -} \ No newline at end of file +} diff --git a/crates/test/Cargo.toml b/crates/test/Cargo.toml index 24054c88b..c73654106 100644 --- a/crates/test/Cargo.toml +++ b/crates/test/Cargo.toml @@ -36,3 +36,4 @@ wrpc-cli = { workspace = true } wtransport = { workspace = true, features = ["ring"], optional = true } wrpc-transport-zenoh = { workspace = true, optional = true } zenoh = { workspace = true, optional = true } +serde_json = { workspace = true } \ No newline at end of file diff --git a/crates/test/src/lib.rs b/crates/test/src/lib.rs index ef1709b0d..19b447902 100644 --- a/crates/test/src/lib.rs +++ b/crates/test/src/lib.rs @@ -2,18 +2,19 @@ use core::net::Ipv6Addr; use std::process::ExitStatus; -use std::sync::Arc; use anyhow::Context; use rcgen::{generate_simple_self_signed, CertifiedKey}; use rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer}; use rustls::version::TLS13; use rustls::{ClientConfig, RootCertStore, ServerConfig}; -use tokio::net::TcpListener; +use std::sync::Arc; +use tokio::net::{TcpListener, TcpStream}; use tokio::process::Command; use tokio::sync::oneshot; use tokio::task::JoinHandle; use tokio::{select, spawn}; -use zenoh::{Config}; +use std::time::Duration; +use tokio::time::sleep; pub async fn free_port() -> anyhow::Result { TcpListener::bind((Ipv6Addr::LOCALHOST, 0)) @@ -125,46 +126,95 @@ pub async fn start_nats() -> anyhow::Result<( #[cfg(feature = "zenoh-transport")] pub async fn start_zenoh() -> anyhow::Result<( u16, - wrpc_transport_zenoh::Client, + Arc, JoinHandle>, oneshot::Sender<()>, )> { + // Check if nats-server is available + + use zenoh::Config; + let nats_server_check = Command::new("zenohd").arg("--version").output().await; + if let Err(e) = nats_server_check { + let error_msg = if e.kind() == std::io::ErrorKind::NotFound { + "zenohd is not installed or not in PATH" + } else if e.kind() == std::io::ErrorKind::PermissionDenied { + "zenohd is not executable or permission denied" + } else { + "failed to execute zenohd" + }; + anyhow::bail!( + "{}. Please install zenohd \ + See https://zenoh.io/docs/getting-started/installation/ for installation instructions. \ + Original error: {}", + error_msg, + e + ); + } + let port = free_port().await?; // not used in setup -- just return - let (server, stop_tx) = - spawn_server(Command::new("zenohd").args(&[] as &[&str])) - .await - .context("failed to start zenohd server")?; - // connect to zenoh + let listen = format!("tcp/0.0.0.0:{port}"); + + let (server, stop_tx) = spawn_server(Command::new("zenohd").args(["-l", &listen])) + .await + .context("failed to start zenohd server")?; + + let mut ready = false; + + // Check that zenohd is ready + for _ in 0..50 { + if TcpStream::connect(("127.0.0.1", port)).await.is_ok() { + ready = true; + break; + } + sleep(Duration::from_millis(100)).await; + } + + if !ready { + anyhow::bail!("zenohd did not open port {port}"); + } + let cfg = match Config::from_env() { Ok(cfg) => cfg, - Err(_) => Config::default(), - }; + Err(_) => { + use serde_json::json; - let session = zenoh::open(cfg) - .await - .expect("Failed to open a Zenoh session"); + let mut config = Config::default(); - let arc_session = Arc::new(session); + // Set mode + config + .insert_json5("mode", &json!("client").to_string()) + .unwrap(); + config + .insert_json5( + "connect/endpoints", + &json!([format!("tcp/127.0.0.1:{port}")]).to_string(), + ) + .unwrap(); - let prefix = Arc::::from(""); + config + } + }; - let client = wrpc_transport_zenoh::Client::new(arc_session, prefix) - .await - .context("failed to construct transport client")?; + let session = zenoh::open(cfg).await.unwrap(); - Ok((port, client, server, stop_tx)) + + let arc_session = Arc::new(session); + + Ok((port, arc_session, server, stop_tx)) } #[cfg(feature = "zenoh-transport")] -pub async fn with_zenoh(f: impl FnOnce(u16, wrpc_transport_zenoh::Client) -> Fut) -> anyhow::Result +pub async fn with_zenoh( + f: impl FnOnce(u16, Arc) -> Fut, +) -> anyhow::Result where Fut: core::future::Future>, { - let (port, zenoh_client, zenoh_server, stop_tx) = start_zenoh() + let (port, zenoh_session, zenoh_server, stop_tx) = start_zenoh() .await .context("failed to start Zenoh server")?; - let res = f(port, zenoh_client).await.context("closure failed")?; + let res = f(port, zenoh_session).await.context("closure failed")?; stop_tx.send(()).expect("failed to stop Zenoh server"); zenoh_server diff --git a/crates/transport-zenoh/src/lib.rs b/crates/transport-zenoh/src/lib.rs index 9e7735b1d..27ef50bbd 100644 --- a/crates/transport-zenoh/src/lib.rs +++ b/crates/transport-zenoh/src/lib.rs @@ -14,11 +14,11 @@ use zenoh::{Session, Wait}; use core::future::Future; use core::pin::{pin, Pin}; +use core::str; use core::task::{Context, Poll}; -use core::{str}; -use std::collections::{HashMap}; -use std::sync::{Arc}; +use std::collections::HashMap; +use std::sync::Arc; use bytes::{Buf as _, Bytes}; use futures::{Stream, StreamExt}; @@ -32,17 +32,15 @@ use tracing::{debug, error, instrument, trace, warn}; pub const PROTOCOL: &str = "wrpc.0.0.1"; - fn send_sync(session: &Session, key: &str, payload: &[u8]) -> io::Result<()> { - // Using the synchronous (blocking) API due to some synchronization issue that nats handles + // Using the synchronous (blocking) API due to some synchronization issue that nats handles session .put(key, payload) .wait() - .map_err(|e| io::Error::new(io::ErrorKind::Other, e))?; + .map_err(io::Error::other)?; Ok(()) } - fn spawn_async(fut: impl Future + Send + 'static) { match tokio::runtime::Handle::try_current() { Ok(rt) => { @@ -60,8 +58,8 @@ fn spawn_async(fut: impl Future + Send + 'static) { fn zbytes_as_bytes(zbytes: &ZBytes) -> Bytes { // Get &ZBytes from the sample let bytes = match zbytes.to_bytes() { - std::borrow::Cow::Borrowed(slice) => Bytes::copy_from_slice(slice), - std::borrow::Cow::Owned(vec) => Bytes::from(vec), + std::borrow::Cow::Borrowed(slice) => Bytes::copy_from_slice(slice), + std::borrow::Cow::Owned(vec) => Bytes::from(vec), }; bytes @@ -155,7 +153,6 @@ pub struct Subscriber { tasks: Arc>, } -#[hotpath::measure_all] impl Drop for Subscriber { fn drop(&mut self) { let commands = self.commands.clone(); @@ -171,7 +168,6 @@ impl Drop for Subscriber { } } -#[hotpath::measure_all] impl Deref for Subscriber { type Target = ReceiverStream; @@ -180,7 +176,6 @@ impl Deref for Subscriber { } } -#[hotpath::measure_all] impl DerefMut for Subscriber { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.rx @@ -203,7 +198,6 @@ pub struct Client { tasks: Arc>, } -#[hotpath::measure_all] impl Client { pub async fn new( session: impl Into>, @@ -224,18 +218,14 @@ impl Client { tasks.spawn({ async move { fn handle_command(subs: &mut HashMap>, cmd: Command) { - //println!("Handle Command Called"); match cmd { Command::Subscribe(s, tx) => { - //println!("Handle Command Subcribe: {}", s); subs.insert(s, tx); } Command::Unsubscribe(s) => { - //println!("Handle Command Unsubscribe: {}", s); subs.remove(&s); } Command::Batch(cmds, ack) => { - //println!("Handle Command Batch"); for cmd in cmds { handle_command(subs, cmd); } @@ -248,9 +238,7 @@ impl Client { subs: &mut HashMap>, sample: Sample, ) { - //println!("Handle Command Called"); let key = sample.key_expr().clone().as_str().to_string(); - // let msg = parse_message(sample); let Some(sub) = subs.get_mut(&key) else { debug!(?key, "drop message with no subscriber"); @@ -267,7 +255,6 @@ impl Client { let mut subs = HashMap::new(); loop { - //println!("Loop Called"); select! { Ok(msg) = sub.recv_async() => handle_message(&mut subs, msg).await, Some(cmd) = cmd_rx.recv() => handle_command(&mut subs, cmd), @@ -288,7 +275,6 @@ impl Client { pub struct ByteSubscription(Subscriber); -#[hotpath::measure_all] impl Stream for ByteSubscription { type Item = std::io::Result; @@ -317,7 +303,6 @@ enum IndexTrie { }, } -#[hotpath::measure_all] impl<'a> From<(&'a [Option], Subscriber)> for IndexTrie { fn from((path, sub): (&'a [Option], Subscriber)) -> Self { match path { @@ -352,7 +337,6 @@ impl]>> FromIterator<(P, Subscriber)> for IndexTrie { } } -#[hotpath::measure_all] impl IndexTrie { #[inline] fn is_empty(&self) -> bool { @@ -483,7 +467,6 @@ pub struct Reader { path: Box<[usize]>, } -#[hotpath::measure_all] impl wrpc_transport::Index for Reader { #[instrument(level = "trace", skip(self))] fn index(&self, path: &[usize]) -> anyhow::Result { @@ -506,7 +489,6 @@ impl wrpc_transport::Index for Reader { } } -#[hotpath::measure_all] impl AsyncRead for Reader { #[instrument(level = "trace", skip_all, ret)] fn poll_read( @@ -583,7 +565,6 @@ impl SubjectWriter { } } -#[hotpath::measure_all] impl wrpc_transport::Index for SubjectWriter { #[instrument(level = "trace", skip(self))] fn index(&self, path: &[usize]) -> anyhow::Result { @@ -623,7 +604,7 @@ impl AsyncWrite for SubjectWriter { buf.len() ); - match send_sync(session, subject, &buf) { + match send_sync(session, subject, buf) { Ok(()) => { trace!("put completed"); Poll::Ready(Ok(buf.len())) @@ -660,7 +641,6 @@ impl AsyncWrite for SubjectWriter { } } -#[hotpath::measure_all] impl Drop for SubjectWriter { fn drop(&mut self) { if !self.shutdown { @@ -717,21 +697,6 @@ impl RootParamWriter { } } -#[hotpath::measure] -fn map_status_to_error_kind(code: &str) -> Option { - let c = code.trim(); - match c { - // Allow either symbolic names or common numeric equivalents - c if c.eq_ignore_ascii_case("NO_RESPONDERS") || c == "503" => { - Some(io::ErrorKind::NotConnected) - } - c if c.eq_ignore_ascii_case("TIMEOUT") || c == "408" => Some(io::ErrorKind::TimedOut), - c if c.eq_ignore_ascii_case("REQUEST_TERMINATED") => Some(io::ErrorKind::UnexpectedEof), - _ => None, - } -} - -#[hotpath::measure_all] impl RootParamWriter { #[instrument(level = "trace", skip_all, ret)] fn poll_active(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { @@ -775,10 +740,10 @@ impl RootParamWriter { Some(zbytes) => zbytes.try_to_string().unwrap().into_owned(), None => { return Poll::Ready(Err(std::io::Error::new( - std::io::ErrorKind::InvalidInput, - "peer did not specify a reply subject", - ))) - }, + std::io::ErrorKind::InvalidInput, + "peer did not specify a reply subject", + ))) + } }; let tx = SubjectWriter::new(session, param_subject(&tx), tasks); @@ -831,7 +796,6 @@ impl RootParamWriter { } } -#[hotpath::measure_all] impl wrpc_transport::Index for RootParamWriter { #[instrument(level = "trace", skip(self))] fn index(&self, path: &[usize]) -> anyhow::Result { @@ -856,7 +820,6 @@ impl wrpc_transport::Index for RootParamWriter { } } -#[hotpath::measure_all] impl AsyncWrite for RootParamWriter { #[instrument(level = "trace", skip_all, ret, fields(buf = format!("{buf:02x?}")))] fn poll_write( @@ -916,7 +879,6 @@ pub enum IndexedParamWriter { Active(SubjectWriter), } -#[hotpath::measure_all] impl IndexedParamWriter { #[instrument(level = "trace", skip_all, ret)] fn poll_active(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { @@ -950,7 +912,6 @@ impl IndexedParamWriter { } } -#[hotpath::measure_all] impl wrpc_transport::Index for IndexedParamWriter { #[instrument(level = "trace", skip_all)] fn index(&self, path: &[usize]) -> anyhow::Result { @@ -973,7 +934,6 @@ impl wrpc_transport::Index for IndexedParamWriter { } } -#[hotpath::measure_all] impl AsyncWrite for IndexedParamWriter { #[instrument(level = "trace", skip_all, ret, fields(buf = format!("{buf:02x?}")))] fn poll_write( @@ -1027,7 +987,6 @@ pub enum ParamWriter { Nested(IndexedParamWriter), } -#[hotpath::measure_all] impl wrpc_transport::Index for ParamWriter { fn index(&self, path: &[usize]) -> anyhow::Result { ensure!(!path.is_empty()); @@ -1039,7 +998,6 @@ impl wrpc_transport::Index for ParamWriter { } } -#[hotpath::measure_all] impl AsyncWrite for ParamWriter { #[instrument(level = "trace", skip_all, ret, fields(buf = format!("{buf:02x?}")))] fn poll_write( @@ -1123,17 +1081,11 @@ impl wrpc_transport::Invoke for Client { let param_tx = invocation_subject(&self.prefix, instance, func); trace!("publishing handshake"); - self.session.put(param_tx, params).attachment(rx.clone()).await.unwrap(); - // publish_with_reply(&self.session, param_tx, rx.clone(), params) - // .await - // .unwrap(); - - // let session = Arc::clone(&self.session); - // tokio::spawn(async move { - // if let Err(err) = nats.flush().await { - // error!(?err, "failed to flush"); - // } - // }); + self.session + .put(param_tx, params) + .attachment(rx.clone()) + .await + .unwrap(); Ok(( ParamWriter::Root(RootParamWriter::new( (*self.session).clone().into(), @@ -1161,7 +1113,6 @@ impl wrpc_transport::Invoke for Client { } } -#[hotpath::measure] async fn handle_message( session: &zenoh::Session, rx: String, @@ -1209,7 +1160,11 @@ async fn handle_message( trace!("publishing handshake response"); - session.put(tx.clone(), Bytes::default()).attachment(rx.clone()).await.unwrap(); + session + .put(tx.clone(), Bytes::default()) + .attachment(rx.clone()) + .await + .unwrap(); Ok(( (), SubjectWriter::new( @@ -1231,7 +1186,6 @@ async fn handle_message( )) } -#[hotpath::measure_all] impl wrpc_transport::Serve for Client { type Context = (); type Outgoing = SubjectWriter; @@ -1248,8 +1202,6 @@ impl wrpc_transport::Serve for Client { > { let subject = invocation_subject(&self.prefix, instance, func); - //println!("Client serve subscribe to: {}", subject); - let sub = self.session.declare_subscriber(subject).await.unwrap(); let session = Arc::clone(&self.session); let paths = paths.into(); diff --git a/crates/wasmtime-cli/src/zenoh.rs b/crates/wasmtime-cli/src/zenoh.rs index 87a7bb4a4..e6ef400c7 100644 --- a/crates/wasmtime-cli/src/zenoh.rs +++ b/crates/wasmtime-cli/src/zenoh.rs @@ -83,7 +83,7 @@ pub async fn handle_serve( let imports = wrpc_transport_zenoh::Client::new(zenoh.clone(), import) .await .context("failed to construct zenoh transport import client")?; - //println!("foooooo serve"); + //println!("foooooo serve"); // future::pending::<()>().await; // res crate::handle_serve(exports, imports, (), *timeout, workload).await diff --git a/examples/rust/hello-zenoh-client/Cargo.toml b/examples/rust/hello-zenoh-client/Cargo.toml index b70643a59..49421b22e 100644 --- a/examples/rust/hello-zenoh-client/Cargo.toml +++ b/examples/rust/hello-zenoh-client/Cargo.toml @@ -26,3 +26,4 @@ url = { workspace = true } wit-bindgen-wrpc = { workspace = true } wrpc-transport-zenoh = { workspace = true } serde_json = {workspace = true} +wrpc-cli = { workspace = true, features = ["zenoh-transport"] } \ No newline at end of file diff --git a/examples/rust/hello-zenoh-client/src/main.rs b/examples/rust/hello-zenoh-client/src/main.rs index 37c8f6a53..c87ee2e41 100644 --- a/examples/rust/hello-zenoh-client/src/main.rs +++ b/examples/rust/hello-zenoh-client/src/main.rs @@ -1,8 +1,6 @@ -use std::sync::Arc; use anyhow::Context as _; -use zenoh::{Config}; -use std::time::Instant; -use serde_json::json; +use clap::Parser; +use std::sync::Arc; mod bindings { wit_bindgen_wrpc::generate!({ @@ -12,84 +10,35 @@ mod bindings { }); } +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Prefixes to invoke `wrpc-examples:hello/handler.hello` on + #[arg(default_value = "rust")] + prefixes: Vec, +} #[tokio::main] async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt().init(); - let cfg = match Config::from_env() { - Ok(cfg) => cfg, - Err(_) => { - let mut config = Config::default(); - // Set mode - config.insert_json5("mode", &json!("peer").to_string()).unwrap(); - config.insert_json5( - "connect/endpoints", - &json!(["tcp/0.0.0.0:7447"]).to_string(), - ).unwrap(); - - config - }, - }; + let Args { prefixes } = Args::parse(); - let session = zenoh::open(cfg) - .await - .expect("Failed to open a Zenoh session"); + let session = wrpc_cli::zenoh::connect() + .await + .context("failed to connect to zenoh")?; let arc_session = Arc::new(session); - let prefix = Arc::::from(""); - - let wrpc = wrpc_transport_zenoh::Client::new(arc_session, prefix) - .await - .context("failed to construct transport client")?; - - // From hello-nats-client - // let hello = bindings::wrpc_examples::hello::handler::hello(&wrpc, ()) - // .await - // .context("failed to invoke `wrpc-examples.hello/handler.hello`")?; - - // eprintln!("NOT_USED_var:prefix: {hello}"); - - // actually useful stuff - let ipv4_address = bindings::wrpc_examples::hello::handler::Ipv4Address{octets: (0,0,0,0)}; - let timespec = bindings::wrpc_examples::hello::handler::Timespec{tv_sec:-111, tv_nsec:111}; - let tr = bindings::wrpc_examples::hello::handler::Tracking { - ref_id: 32, - ip_addr: ipv4_address, - stratum: 16, - leap_status: 16, - ref_time: timespec, - current_correction: 64.0, - last_offset: 64.0, - rms_offset: 64.0, - freq_ppm: 64.0, - resid_freq_ppm: 64.0, - skew_ppm: 64.0, - root_delay: 64.0, - root_dispersion: 64.0, - last_update_interval: 64.0, - }; - - let start = Instant::now(); - let limit = 100001; - for i in 1..limit { - let t1 = bindings::wrpc_examples::hello::handler::get_tracking(&wrpc, (), &tr) - .await - .context("failed to invoke `wrpc-examples.hello/handler.hello`")?; - - // tiny sleep to allow buffers to clear - // tokio::time::sleep(tokio::time::Duration::from_micros(33)).await; - - // println!("Call {i} {:?}", t1.ref_id); + for prefix in prefixes { + let wrpc = wrpc_transport_zenoh::Client::new(arc_session.clone(), prefix.clone()) + .await + .context("failed to construct transport client")?; + let hello = bindings::wrpc_examples::hello::handler::hello(&wrpc, ()) + .await + .context("failed to invoke `wrpc-examples.hello/handler.hello`")?; + eprintln!("{prefix}: {hello}"); } - // Record the time after the loop finishes and calculate the duration - let duration = start.elapsed(); - - // Print the elapsed time - // The {:?} formatter uses the Debug implementation for Duration - println!("Time elapsed in the loop is for {limit} calls. Time Elapsed: {duration:?}"); - Ok(()) } diff --git a/examples/rust/hello-zenoh-client/wit/deps/hello/hello.wit b/examples/rust/hello-zenoh-client/wit/deps/hello/hello.wit index 29ea9780f..6c84d66cc 100644 --- a/examples/rust/hello-zenoh-client/wit/deps/hello/hello.wit +++ b/examples/rust/hello-zenoh-client/wit/deps/hello/hello.wit @@ -1,37 +1,7 @@ package wrpc-examples:hello; interface handler { - record timespec { - tv-sec: s64, - tv-nsec: u32 - } - - record tracking { - ref-id: u32, - ip-addr: ipv4-address, - stratum: u16, - leap-status: u16, - ref-time: timespec, - current-correction: f64, - last-offset: f64, - rms-offset: f64, - freq-ppm: f64, - resid-freq-ppm: f64, - skew-ppm: f64, - root-delay: f64, - root-dispersion: f64, - last-update-interval: f64, - } - - record ipv4-address { - // It seems that a list with a fixed size is supported in the WIT standard. However I have no clue if wasmtime implements it... - // octets: list, // https: //github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#types - - octets: tuple // Backup solution: closest to a static u8 array with 4 elements - } - hello: func() -> string; - get-tracking: func(t: tracking) -> tracking; } world client { diff --git a/examples/rust/hello-zenoh-server/Cargo.toml b/examples/rust/hello-zenoh-server/Cargo.toml index fe2ada703..b0dbedfaf 100644 --- a/examples/rust/hello-zenoh-server/Cargo.toml +++ b/examples/rust/hello-zenoh-server/Cargo.toml @@ -28,8 +28,4 @@ url = { workspace = true } wit-bindgen-wrpc = { workspace = true } wrpc-transport-zenoh = { workspace = true } serde_json = {workspace = true} -hotpath = "0.13.0" - -[features] -hotpath = ["hotpath/hotpath"] -hotpath-alloc = ["hotpath/hotpath-alloc"] +wrpc-cli = { workspace = true, features = ["zenoh-transport"] } diff --git a/examples/rust/hello-zenoh-server/src/main.rs b/examples/rust/hello-zenoh-server/src/main.rs index 7d0d7e83d..45db6bbba 100644 --- a/examples/rust/hello-zenoh-server/src/main.rs +++ b/examples/rust/hello-zenoh-server/src/main.rs @@ -2,13 +2,12 @@ use core::pin::pin; use std::sync::Arc; use anyhow::Context as _; +use clap::Parser; use futures::stream::select_all; use futures::StreamExt as _; -use serde_json::json; use tokio::task::JoinSet; use tokio::{select, signal}; use tracing::{debug, error, info, warn}; -use zenoh::{Config}; mod bindings { wit_bindgen_wrpc::generate!({ @@ -21,46 +20,32 @@ mod bindings { #[derive(Clone, Copy)] struct Server; -impl bindings::exports::wrpc_examples::hello::handler::Handler<()> - for Server -{ +impl bindings::exports::wrpc_examples::hello::handler::Handler<()> for Server { async fn hello(&self, _: ()) -> anyhow::Result { Ok("hello from Rust".to_string()) } +} - async fn get_tracking(&self, _cx: (), t:bindings::exports::wrpc_examples::hello::handler::Tracking) -> Result { - Ok(t) - } +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Prefix to serve `wrpc-examples:hello/handler.hello` on + #[arg(default_value = "rust")] + prefix: String, } #[tokio::main] -#[hotpath::main(percentiles = [99])] async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt().init(); - let cfg = match Config::from_env() { - Ok(cfg) => cfg, - Err(_) => { - let mut config = Config::default(); - // Set mode - config.insert_json5("mode", &json!("peer").to_string()).unwrap(); - config.insert_json5( - "connect/endpoints", - &json!(["tcp/0.0.0.0:7447"]).to_string(), - ).unwrap(); - - config - }, - }; + let Args { prefix } = Args::parse(); - let session = zenoh::open(cfg) - .await - .expect("Failed to open a Zenoh session"); + let session = wrpc_cli::zenoh::connect() + .await + .context("failed to connect to zenoh")?; let arc_session = Arc::new(session); - let prefix = Arc::::from(""); - let wrpc = wrpc_transport_zenoh::Client::new(arc_session, prefix) .await .context("failed to construct transport client")?; diff --git a/examples/rust/hello-zenoh-server/wit/deps/hello/hello.wit b/examples/rust/hello-zenoh-server/wit/deps/hello/hello.wit index 29ea9780f..6c84d66cc 100644 --- a/examples/rust/hello-zenoh-server/wit/deps/hello/hello.wit +++ b/examples/rust/hello-zenoh-server/wit/deps/hello/hello.wit @@ -1,37 +1,7 @@ package wrpc-examples:hello; interface handler { - record timespec { - tv-sec: s64, - tv-nsec: u32 - } - - record tracking { - ref-id: u32, - ip-addr: ipv4-address, - stratum: u16, - leap-status: u16, - ref-time: timespec, - current-correction: f64, - last-offset: f64, - rms-offset: f64, - freq-ppm: f64, - resid-freq-ppm: f64, - skew-ppm: f64, - root-delay: f64, - root-dispersion: f64, - last-update-interval: f64, - } - - record ipv4-address { - // It seems that a list with a fixed size is supported in the WIT standard. However I have no clue if wasmtime implements it... - // octets: list, // https: //github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#types - - octets: tuple // Backup solution: closest to a static u8 array with 4 elements - } - hello: func() -> string; - get-tracking: func(t: tracking) -> tracking; } world client { diff --git a/examples/rust/streams-zenoh-client/Cargo.toml b/examples/rust/streams-zenoh-client/Cargo.toml index 21d6904c3..f0f792a7c 100644 --- a/examples/rust/streams-zenoh-client/Cargo.toml +++ b/examples/rust/streams-zenoh-client/Cargo.toml @@ -33,4 +33,5 @@ tracing-subscriber = { workspace = true, features = [ url = { workspace = true } wit-bindgen-wrpc = { workspace = true } wrpc-transport-zenoh = { workspace = true } -serde_json = {workspace = true} \ No newline at end of file +serde_json = {workspace = true} +wrpc-cli = { workspace = true, features = ["zenoh-transport"] } \ No newline at end of file diff --git a/examples/rust/streams-zenoh-client/src/main.rs b/examples/rust/streams-zenoh-client/src/main.rs index 93bf87bd8..fc835315f 100644 --- a/examples/rust/streams-zenoh-client/src/main.rs +++ b/examples/rust/streams-zenoh-client/src/main.rs @@ -1,13 +1,12 @@ -use core::time::Duration; -use std::sync::Arc; - use anyhow::Context as _; use bytes::Bytes; +use clap::Parser; +use core::time::Duration; use futures::{stream, StreamExt as _}; +use std::sync::Arc; use tokio::{time, try_join}; use tokio_stream::wrappers::IntervalStream; use tracing::debug; -use zenoh::{Config}; mod bindings { wit_bindgen_wrpc::generate!({ @@ -19,22 +18,27 @@ mod bindings { use bindings::wrpc_examples::streams::handler::{echo, Req}; +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Prefixes to invoke `wrpc-examples:streams/handler.echo` on + #[arg(default_value = "rust")] + prefixes: Vec, +} + #[tokio::main] async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt().init(); - let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + let Args { prefixes } = Args::parse(); - let session = zenoh::open(cfg) - .await - .expect("Failed to open a Zenoh session"); + let session = wrpc_cli::zenoh::connect() + .await + .context("failed to connect to zenoh")?; let arc_session = Arc::new(session); - - let prefix = Arc::::from("rust"); - //let prefixes = vec!["Hello", "Zenoh", "streams!"]; // Expected was a string vec ... ! - //for prefix in prefixes { + for prefix in prefixes { let numbers = Box::pin( stream::iter(1..) .take(10) @@ -53,7 +57,7 @@ async fn main() -> anyhow::Result<()> { ); // Client creation moved here from top - let wrpc = wrpc_transport_zenoh::Client::new(arc_session, prefix) + let wrpc = wrpc_transport_zenoh::Client::new(arc_session.clone(), prefix) .await .context("failed to construct transport client")?; @@ -82,6 +86,6 @@ async fn main() -> anyhow::Result<()> { Ok(()) } )?; - //} + } Ok(()) } diff --git a/examples/rust/streams-zenoh-server/Cargo.toml b/examples/rust/streams-zenoh-server/Cargo.toml index 89f7bd7ff..e3583d171 100644 --- a/examples/rust/streams-zenoh-server/Cargo.toml +++ b/examples/rust/streams-zenoh-server/Cargo.toml @@ -33,8 +33,4 @@ url = { workspace = true } wit-bindgen-wrpc = { workspace = true } wrpc-transport-zenoh = { workspace = true } serde_json = {workspace = true} -hotpath = "0.13.0" - -[features] -hotpath = ["hotpath/hotpath"] -hotpath-alloc = ["hotpath/hotpath-alloc"] \ No newline at end of file +wrpc-cli = { workspace = true, features = ["zenoh-transport"] } diff --git a/examples/rust/streams-zenoh-server/src/main.rs b/examples/rust/streams-zenoh-server/src/main.rs index 3c0c7f2e8..a20c7e542 100644 --- a/examples/rust/streams-zenoh-server/src/main.rs +++ b/examples/rust/streams-zenoh-server/src/main.rs @@ -1,14 +1,13 @@ -use core::pin::{pin, Pin}; -use std::sync::Arc; - use anyhow::Context as _; use bytes::Bytes; +use clap::Parser; +use core::pin::{pin, Pin}; use futures::stream::select_all; use futures::{Stream, StreamExt as _}; +use std::sync::Arc; use tokio::task::JoinSet; use tokio::{select, signal}; use tracing::{debug, error, info, warn}; -use zenoh::{Config}; mod bindings { wit_bindgen_wrpc::generate!({ @@ -20,23 +19,18 @@ mod bindings { use bindings::exports::wrpc_examples::streams::handler::Req; -// #[derive(Parser, Debug)] -// #[command(author, version, about, long_about = None)] -// struct Args { -// /// NATS.io URL to connect to -// #[arg(short, long, default_value = "nats://127.0.0.1:4222")] -// nats: Url, - -// /// Prefix to serve `wrpc-examples:streams/handler.echo` on -// #[arg(default_value = "rust")] -// prefix: String, -// } +#[derive(Parser, Debug)] +#[command(author, version, about, long_about = None)] +struct Args { + /// Prefix to serve `wrpc-examples:streams/handler.echo` on + #[arg(default_value = "rust")] + prefix: String, +} #[derive(Clone, Copy)] struct Server; -impl bindings::exports::wrpc_examples::streams::handler::Handler<()> for Server -{ +impl bindings::exports::wrpc_examples::streams::handler::Handler<()> for Server { async fn echo( &self, _cx: (), @@ -50,19 +44,16 @@ impl bindings::exports::wrpc_examples::streams::handler::Handler<()> for Server } #[tokio::main] -#[hotpath::main(percentiles = [99])] async fn main() -> anyhow::Result<()> { tracing_subscriber::fmt().init(); - let cfg = Config::from_env().expect("Missing environment variable 'ZENOH_CONFIG'"); + let Args { prefix } = Args::parse(); - let session = zenoh::open(cfg) - .await - .expect("Failed to open a Zenoh session"); + let session = wrpc_cli::zenoh::connect() + .await + .context("failed to connect to zenoh")?; let arc_session = Arc::new(session); - - let prefix = Arc::::from("rust"); let wrpc = wrpc_transport_zenoh::Client::new(arc_session, prefix) .await @@ -70,7 +61,7 @@ async fn main() -> anyhow::Result<()> { let invocations = bindings::serve(&wrpc, Server) .await .context("failed to serve `wrpc-examples:streams/handler.echo`")?; - + // NOTE: This will conflate all invocation streams into a single stream via `futures::stream::SelectAll`, // to customize this, iterate over the returned `invocations` and set up custom handling per export let mut invocations = select_all( diff --git a/flake.nix b/flake.nix index cbdabaf4f..1c7b6e48d 100644 --- a/flake.nix +++ b/flake.nix @@ -122,6 +122,8 @@ pkgs.nats-server pkgs.pkgsUnstable.go + + pkgs.zenoh ]; }; @@ -210,6 +212,7 @@ pkgs.cargo-audit pkgs.cargo-nextest pkgs.wit-deps + pkgs.zenoh pkgs.pkgsUnstable.go pkgs.pkgsUnstable.nats-server diff --git a/tests/rust.rs b/tests/rust.rs index 52d2cb513..da9d594ca 100644 --- a/tests/rust.rs +++ b/tests/rust.rs @@ -16,7 +16,6 @@ use anyhow::Context; use bytes::Bytes; use common::assert_async; use futures::{stream, FutureExt as _, Stream, StreamExt as _, TryStreamExt as _}; -use serial_test::serial; use tokio::sync::{oneshot, RwLock}; use tokio::time::sleep; use tokio::{join, select, spawn, try_join}; @@ -1272,24 +1271,32 @@ async fn rust_dynamic_web_transport() -> anyhow::Result<()> { #[cfg(feature = "zenoh-transport")] #[test_log::test(tokio::test(flavor = "multi_thread"))] -#[serial(zenoh_tests)] #[instrument(ret)] async fn rust_bindgen_zenoh_sync() -> anyhow::Result<()> { wrpc_test::with_zenoh(|_, zenoh_client| async { - let clt = Arc::new(zenoh_client); + let clt = wrpc_transport_zenoh::Client::new( + zenoh_client, + "rust-bindgen-sync" + ).await + .context("failed to construct client")?; + let clt = Arc::new(clt); assert_bindgen_sync(Arc::clone(&clt), clt).await }) .await } -#[cfg(feature = "zenoh-transport")] +#[cfg(feature = "nats")] #[test_log::test(tokio::test(flavor = "multi_thread"))] -#[serial(zenoh_tests)] #[instrument(ret)] async fn rust_bindgen_zenoh_async() -> anyhow::Result<()> { wrpc_test::with_zenoh(|_, zenoh_client| { async { - let clt = Arc::new(zenoh_client); + let clt = wrpc_transport_zenoh::Client::new( + zenoh_client, + "rust-bindgen-sync" + ).await + .context("failed to construct client")?; + let clt = Arc::new(clt); assert_bindgen_async(Arc::clone(&clt), clt).await } .in_current_span() @@ -1299,11 +1306,11 @@ async fn rust_bindgen_zenoh_async() -> anyhow::Result<()> { #[cfg(feature = "zenoh-transport")] #[test_log::test(tokio::test(flavor = "multi_thread"))] -#[serial(zenoh_tests)] #[instrument(ret)] async fn rust_dynamic_zenoh() -> anyhow::Result<()> { wrpc_test::with_zenoh(|_, zenoh_client| async { - let clt = Arc::new(zenoh_client); + let clt = wrpc_transport_zenoh::Client::new(zenoh_client, "rust-bindgen-dynamic").await.unwrap(); + let clt = Arc::new(clt); assert_dynamic(Arc::clone(&clt), clt).await }) .await @@ -1530,4 +1537,4 @@ async fn rust_bindgen_uds_async() -> anyhow::Result<()> { } } } -} \ No newline at end of file +} From 7685c3203e367b1c12d8c6c1948fdf6f23e77739 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 9 Mar 2026 12:58:39 +0100 Subject: [PATCH 4/7] fixed wrong feature flag on zenoh test --- tests/rust.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/rust.rs b/tests/rust.rs index da9d594ca..2aba8c83b 100644 --- a/tests/rust.rs +++ b/tests/rust.rs @@ -1285,7 +1285,7 @@ async fn rust_bindgen_zenoh_sync() -> anyhow::Result<()> { .await } -#[cfg(feature = "nats")] +#[cfg(feature = "zenoh-transport")] #[test_log::test(tokio::test(flavor = "multi_thread"))] #[instrument(ret)] async fn rust_bindgen_zenoh_async() -> anyhow::Result<()> { From 2a88dde0a573c2de0261ce7350aeebedcb48c51e Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 9 Mar 2026 13:07:19 +0100 Subject: [PATCH 5/7] remove seperate zenoh.md and fix some test dependencies --- ZENOH.md | 157 ------------------------------ crates/test/src/lib.rs | 11 +-- crates/transport-zenoh/src/lib.rs | 5 +- tests/rust.rs | 20 ++-- 4 files changed, 15 insertions(+), 178 deletions(-) delete mode 100644 ZENOH.md diff --git a/ZENOH.md b/ZENOH.md deleted file mode 100644 index 4360b3d7d..000000000 --- a/ZENOH.md +++ /dev/null @@ -1,157 +0,0 @@ -### Requirements ******************* - -#### Setup zenohd on NixOS - -1. Add zenoh to your configuration.nix file in the environment.systemPackages - ``` - # List packages installed in system profile. To search, run: - # $ nix search wget - environment.systemPackages = with pkgs; [ - ... - zenoh - ]; - ``` - -2. Rebuild NixOS - ``` - sudo nixos-rebuild switch - ``` - -3. Test zenohd - ``` - zenohd - ``` - - - Sample output: - 2025-12-08T12:27:11.419376Z INFO main ThreadId(01) zenohd: zenohd v1.6.1 built with rustc 1.85.0 (4d91de4e4 2025-02-17) - 2025-12-08T12:27:11.423016Z INFO main ThreadId(01) zenohd: Initial conf: {"access_control":{"def ........ ,"qos":{"enabled":true}}}} - 2025-12-08T12:27:11.428864Z INFO main ThreadId(01) zenoh::net::runtime: Using ZID: ba0e4a24bdf641c79bfe9ee37eb9bc4 - 2025-12-08T12:27:11.438761Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::215:5dff:fe00:b079]:7447 - 2025-12-08T12:27:11.439328Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::3842:4ff:fe75:baf1]:7447 - 2025-12-08T12:27:11.439331Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/[fe80::209d:11ff:fe06:8e06]:7447 - 2025-12-08T12:27:11.439333Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/10.255.255.254:7447 - 2025-12-08T12:27:11.439334Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/172.21.8.176:7447 - 2025-12-08T12:27:11.439336Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: Zenoh can be reached at: tcp/172.18.0.1:7447 - 2025-12-08T12:27:11.439428Z INFO main ThreadId(01) zenoh::net::runtime::orchestrator: zenohd listening scout messages on 224.0.0.224:7446 - -#### Using [zenoh] transport - -We will use the following two Rust wRPC applications using [zenoh] transport: -- [examples/rust/hello-zenoh-client](examples/rust/hello-zenoh-client) -- [examples/rust/hello-zenoh-server](examples/rust/hello-zenoh-server) - -1. Run [zenoh]: - - - Build the repo, so that zenoh transport is compiled for wrpc-wasmtime (runtime) using - ```sh - cargo build --release - ``` - - - Create a zenoh config file at /path/to/config/zenoh_conf.json5 - ```sh - { - mode: "client", - listen: { - endpoints: ["tcp/0.0.0.0:7447"], - }, - } - ``` - This is a minimal example config. - - - Set the config environment variable for zenoh: - > export ZENOH_CONFIG="/path/to/config/zenoh_conf.json5" - - - Running as a daemon with the config above in order to run zenoh as a transport (in Client mode): - ```sh - zenohd - ``` - -2. Serve Wasm `hello` server via [zenoh] - - ```sh - ./target/release/wrpc-wasmtime zenoh serve ./target/wasm32-wasip2/debug/hello_component_server.wasm - ``` - - - Sample output: - > INFO zenoh::net::runtime: Using ZID: 638a012883d98f769cf4367f8457bc66 - > INFO zenoh::net::runtime::orchestrator: Scouting... - > INFO zenoh::net::runtime::orchestrator: Found HelloProto { version: 9, whatami: Router, zid: f3ae70a723144e6675f4c72d30196797, locators: [tcp/[fe80::215:5dff:fe83:cd20]:7447, tcp/[fe80::8d2:a4ff:fed2:f33d]:7447, tcp/[fe80::c431:38ff:fe58:9310]:7447, tcp/10.255.255.254:7447, tcp/172.21.8.176:7447, tcp/172.18.0.1:7447] } - > INFO zenoh::net::runtime::orchestrator: Found HelloProto { version: 9, whatami: Router, zid: f3ae70a723144e6675f4c72d30196797, locators: [tcp/[fe80::215:5dff:fe83:cd20]:7447, tcp/[fe80::8d2:a4ff:fed2:f33d]:7447, tcp/[fe80::c431:38ff:fe58:9310]:7447, tcp/10.255.255.254:7447, tcp/172.21.8.176:7447, tcp/172.18.0.1:7447] } - > INFO wrpc_wasmtime_cli: serving instance function name="hello" - -3. Call Wasm `hello` server using a Wasm `hello` client via [zenoh]: - - ```sh - ./target/release/wrpc-wasmtime zenoh run ./target/wasm32-wasip2/debug/hello-component-client.wasm - ``` - - - Sample output: - > INFO zenoh::net::runtime: Using ZID: e4b5dcb134469e2e5773dd88dfb7a8a - > INFO zenoh::net::runtime::orchestrator: Scouting... - > INFO zenoh::net::runtime::orchestrator: Found HelloProto { version: 9, whatami: Router, zid: f3ae70a723144e6675f4c72d30196797, locators: [tcp/[fe80::215:5dff:fe83:cd20]:7447, tcp/[fe80::8d2:a4ff:fed2:f33d]:7447, tcp/[fe80::c431:38ff:fe58:9310]:7447, tcp/10.255.255.254:7447, tcp/172.21.8.176:7447, tcp/172.18.0.1:7447] } - > INFO zenoh::net::runtime::orchestrator: Found HelloProto { version: 9, whatami: Router, zid: f3ae70a723144e6675f4c72d30196797, locators: [tcp/[fe80::215:5dff:fe83:cd20]:7447, tcp/[fe80::8d2:a4ff:fed2:f33d]:7447, tcp/[fe80::c431:38ff:fe58:9310]:7447, tcp/10.255.255.254:7447, tcp/172.21.8.176:7447, tcp/172.18.0.1:7447] } - hello from Rust - > INFO zenoh::api::session: close session zid=e4b5dcb134469e2e5773dd88dfb7a8a - -4. Call the Wasm `hello` server using a native wRPC `hello` client via [zenoh]: - - ```sh - cargo run -p hello-zenoh-client - ``` - -5. Serve native wRPC `hello` server via [zenoh]: - - ```sh - cargo run -p hello-zenoh-server - ``` - - -#### Testing - -To test the transport-zenoh package run: - - ```sh - cargo test zenoh -- --nocapture - ``` - - - Sample output: - > test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 13 filtered out; finished in 6.17s - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -6. Call both the native wRPC `hello` server and Wasm `hello` server using native wRPC `hello` client via [zenoh]: - - ```sh - cargo run -p hello-zenoh-client rust native - ``` - -7. Call native wRPC `hello` server using Wasm `hello` client via [zenoh]: - - ```sh - wrpc-wasmtime zenoh run --import native ./target/wasm32-wasip2/release/hello-component-client.wasm \ No newline at end of file diff --git a/crates/test/src/lib.rs b/crates/test/src/lib.rs index 19b447902..56642d0df 100644 --- a/crates/test/src/lib.rs +++ b/crates/test/src/lib.rs @@ -8,13 +8,13 @@ use rustls::pki_types::{CertificateDer, PrivatePkcs8KeyDer}; use rustls::version::TLS13; use rustls::{ClientConfig, RootCertStore, ServerConfig}; use std::sync::Arc; +use std::time::Duration; use tokio::net::{TcpListener, TcpStream}; use tokio::process::Command; use tokio::sync::oneshot; use tokio::task::JoinHandle; -use tokio::{select, spawn}; -use std::time::Duration; use tokio::time::sleep; +use tokio::{select, spawn}; pub async fn free_port() -> anyhow::Result { TcpListener::bind((Ipv6Addr::LOCALHOST, 0)) @@ -130,9 +130,9 @@ pub async fn start_zenoh() -> anyhow::Result<( JoinHandle>, oneshot::Sender<()>, )> { - // Check if nats-server is available + // Check if nats-server is available - use zenoh::Config; + use zenoh::Config; let nats_server_check = Command::new("zenohd").arg("--version").output().await; if let Err(e) = nats_server_check { let error_msg = if e.kind() == std::io::ErrorKind::NotFound { @@ -162,7 +162,7 @@ pub async fn start_zenoh() -> anyhow::Result<( let mut ready = false; // Check that zenohd is ready - for _ in 0..50 { + for _ in 0..50 { if TcpStream::connect(("127.0.0.1", port)).await.is_ok() { ready = true; break; @@ -198,7 +198,6 @@ pub async fn start_zenoh() -> anyhow::Result<( let session = zenoh::open(cfg).await.unwrap(); - let arc_session = Arc::new(session); Ok((port, arc_session, server, stop_tx)) diff --git a/crates/transport-zenoh/src/lib.rs b/crates/transport-zenoh/src/lib.rs index 27ef50bbd..86c7763a0 100644 --- a/crates/transport-zenoh/src/lib.rs +++ b/crates/transport-zenoh/src/lib.rs @@ -34,10 +34,7 @@ pub const PROTOCOL: &str = "wrpc.0.0.1"; fn send_sync(session: &Session, key: &str, payload: &[u8]) -> io::Result<()> { // Using the synchronous (blocking) API due to some synchronization issue that nats handles - session - .put(key, payload) - .wait() - .map_err(io::Error::other)?; + session.put(key, payload).wait().map_err(io::Error::other)?; Ok(()) } diff --git a/tests/rust.rs b/tests/rust.rs index 2aba8c83b..ab4bdb42b 100644 --- a/tests/rust.rs +++ b/tests/rust.rs @@ -1274,11 +1274,9 @@ async fn rust_dynamic_web_transport() -> anyhow::Result<()> { #[instrument(ret)] async fn rust_bindgen_zenoh_sync() -> anyhow::Result<()> { wrpc_test::with_zenoh(|_, zenoh_client| async { - let clt = wrpc_transport_zenoh::Client::new( - zenoh_client, - "rust-bindgen-sync" - ).await - .context("failed to construct client")?; + let clt = wrpc_transport_zenoh::Client::new(zenoh_client, "rust-bindgen-sync") + .await + .context("failed to construct client")?; let clt = Arc::new(clt); assert_bindgen_sync(Arc::clone(&clt), clt).await }) @@ -1291,11 +1289,9 @@ async fn rust_bindgen_zenoh_sync() -> anyhow::Result<()> { async fn rust_bindgen_zenoh_async() -> anyhow::Result<()> { wrpc_test::with_zenoh(|_, zenoh_client| { async { - let clt = wrpc_transport_zenoh::Client::new( - zenoh_client, - "rust-bindgen-sync" - ).await - .context("failed to construct client")?; + let clt = wrpc_transport_zenoh::Client::new(zenoh_client, "rust-bindgen-sync") + .await + .context("failed to construct client")?; let clt = Arc::new(clt); assert_bindgen_async(Arc::clone(&clt), clt).await } @@ -1309,7 +1305,9 @@ async fn rust_bindgen_zenoh_async() -> anyhow::Result<()> { #[instrument(ret)] async fn rust_dynamic_zenoh() -> anyhow::Result<()> { wrpc_test::with_zenoh(|_, zenoh_client| async { - let clt = wrpc_transport_zenoh::Client::new(zenoh_client, "rust-bindgen-dynamic").await.unwrap(); + let clt = wrpc_transport_zenoh::Client::new(zenoh_client, "rust-bindgen-dynamic") + .await + .unwrap(); let clt = Arc::new(clt); assert_dynamic(Arc::clone(&clt), clt).await }) From 4e83c6639856cb75b35021c2cfa8a251dc435af7 Mon Sep 17 00:00:00 2001 From: Christoph Schulze Date: Mon, 9 Mar 2026 14:21:41 +0100 Subject: [PATCH 6/7] fixes from cargo clippy --fix --allow-dirty --allow-staged --all-targets --workspace -- -Wclippy::pedantic --- crates/cli/src/zenoh.rs | 29 +++++------ crates/test/src/lib.rs | 49 ++++++++----------- examples/rust/hello-zenoh-server/src/main.rs | 6 +-- .../rust/streams-zenoh-server/src/main.rs | 4 +- 4 files changed, 39 insertions(+), 49 deletions(-) diff --git a/crates/cli/src/zenoh.rs b/crates/cli/src/zenoh.rs index 22c6e1360..9c8b9efe7 100644 --- a/crates/cli/src/zenoh.rs +++ b/crates/cli/src/zenoh.rs @@ -3,23 +3,20 @@ use zenoh::{Config, Session}; /// Open a regular Zenoh session with configs supplied by an environment variable. pub async fn connect() -> anyhow::Result { - let cfg = match Config::from_env() { - Ok(cfg) => cfg, - Err(_) => { - let mut config = Config::default(); - // Set mode - config - .insert_json5("mode", &json!("client").to_string()) - .unwrap(); - config - .insert_json5( - "connect/endpoints", - &json!(["tcp/0.0.0.0:7447"]).to_string(), - ) - .unwrap(); + let cfg = if let Ok(cfg) = Config::from_env() { cfg } else { + let mut config = Config::default(); + // Set mode + config + .insert_json5("mode", &json!("client").to_string()) + .unwrap(); + config + .insert_json5( + "connect/endpoints", + &json!(["tcp/0.0.0.0:7447"]).to_string(), + ) + .unwrap(); - config - } + config }; let session = zenoh::open(cfg).await.unwrap(); diff --git a/crates/test/src/lib.rs b/crates/test/src/lib.rs index 56642d0df..a005ca701 100644 --- a/crates/test/src/lib.rs +++ b/crates/test/src/lib.rs @@ -103,11 +103,9 @@ pub async fn start_nats() -> anyhow::Result<( "failed to execute nats-server" }; anyhow::bail!( - "{}. Please install nats-server >= 2.10.20. \ + "{error_msg}. Please install nats-server >= 2.10.20. \ See https://docs.nats.io/running-a-nats-service/introduction/installation for installation instructions. \ - Original error: {}", - error_msg, - e + Original error: {e}" ); } @@ -143,11 +141,9 @@ pub async fn start_zenoh() -> anyhow::Result<( "failed to execute zenohd" }; anyhow::bail!( - "{}. Please install zenohd \ + "{error_msg}. Please install zenohd \ See https://zenoh.io/docs/getting-started/installation/ for installation instructions. \ - Original error: {}", - error_msg, - e + Original error: {e}" ); } @@ -174,26 +170,23 @@ pub async fn start_zenoh() -> anyhow::Result<( anyhow::bail!("zenohd did not open port {port}"); } - let cfg = match Config::from_env() { - Ok(cfg) => cfg, - Err(_) => { - use serde_json::json; - - let mut config = Config::default(); - - // Set mode - config - .insert_json5("mode", &json!("client").to_string()) - .unwrap(); - config - .insert_json5( - "connect/endpoints", - &json!([format!("tcp/127.0.0.1:{port}")]).to_string(), - ) - .unwrap(); - - config - } + let cfg = if let Ok(cfg) = Config::from_env() { cfg } else { + use serde_json::json; + + let mut config = Config::default(); + + // Set mode + config + .insert_json5("mode", &json!("client").to_string()) + .unwrap(); + config + .insert_json5( + "connect/endpoints", + &json!([format!("tcp/127.0.0.1:{port}")]).to_string(), + ) + .unwrap(); + + config }; let session = zenoh::open(cfg).await.unwrap(); diff --git a/examples/rust/hello-zenoh-server/src/main.rs b/examples/rust/hello-zenoh-server/src/main.rs index 45db6bbba..8deba2d41 100644 --- a/examples/rust/hello-zenoh-server/src/main.rs +++ b/examples/rust/hello-zenoh-server/src/main.rs @@ -21,7 +21,7 @@ mod bindings { struct Server; impl bindings::exports::wrpc_examples::hello::handler::Handler<()> for Server { - async fn hello(&self, _: ()) -> anyhow::Result { + async fn hello(&self, (): ()) -> anyhow::Result { Ok("hello from Rust".to_string()) } } @@ -83,14 +83,14 @@ async fn main() -> anyhow::Result<()> { } Some(res) = tasks.join_next() => { if let Err(err) = res { - error!(?err, "failed to join task") + error!(?err, "failed to join task"); } } res = &mut shutdown => { // wait for all invocations to complete while let Some(res) = tasks.join_next().await { if let Err(err) = res { - error!(?err, "failed to join task") + error!(?err, "failed to join task"); } } return res.context("failed to listen for ^C") diff --git a/examples/rust/streams-zenoh-server/src/main.rs b/examples/rust/streams-zenoh-server/src/main.rs index a20c7e542..af05d96ee 100644 --- a/examples/rust/streams-zenoh-server/src/main.rs +++ b/examples/rust/streams-zenoh-server/src/main.rs @@ -93,14 +93,14 @@ async fn main() -> anyhow::Result<()> { } Some(res) = tasks.join_next() => { if let Err(err) = res { - error!(?err, "failed to join task") + error!(?err, "failed to join task"); } } res = &mut shutdown => { // wait for all invocations to complete while let Some(res) = tasks.join_next().await { if let Err(err) = res { - error!(?err, "failed to join task") + error!(?err, "failed to join task"); } } return res.context("failed to listen for ^C") From 93661b9e4df558ed46dba7486d6a0af6697df92a Mon Sep 17 00:00:00 2001 From: Patrick Siegl <3261314+psiegl@users.noreply.github.com> Date: Wed, 11 Mar 2026 19:14:30 +0100 Subject: [PATCH 7/7] Update Cargo.lock --- Cargo.lock | 58 +++++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bcd6fb596..36d357f2e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -270,11 +270,10 @@ checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" [[package]] name = "axum" -version = "0.7.9" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" dependencies = [ - "async-trait", "axum-core", "bytes", "futures-util", @@ -289,8 +288,7 @@ dependencies = [ "mime", "percent-encoding", "pin-project-lite", - "rustversion", - "serde", + "serde_core", "sync_wrapper 1.0.2", "tokio", "tower", @@ -300,19 +298,17 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ - "async-trait", "bytes", - "futures-util", + "futures-core", "http 1.4.0", "http-body 1.0.1", "http-body-util", "mime", "pin-project-lite", - "rustversion", "sync_wrapper 1.0.2", "tower-layer", "tower-service", @@ -2525,9 +2521,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.182" +version = "0.2.183" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" [[package]] name = "libloading" @@ -2661,9 +2657,9 @@ dependencies = [ [[package]] name = "matchit" -version = "0.7.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "maybe-owned" @@ -3304,7 +3300,7 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls 0.23.37", - "socket2 0.6.2", + "socket2 0.6.3", "thiserror 2.0.18", "tokio", "tracing", @@ -3313,9 +3309,9 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ "bytes", "getrandom 0.3.4", @@ -3342,7 +3338,7 @@ dependencies = [ "cfg_aliases", "libc", "once_cell", - "socket2 0.6.2", + "socket2 0.6.3", "tracing", "windows-sys 0.60.2", ] @@ -3903,9 +3899,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] @@ -4309,12 +4305,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -4600,9 +4596,9 @@ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "tempfile" -version = "3.26.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a72c767771b47409d2345987fda8628641887d5466101319899796367354a0" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "once_cell", @@ -4810,7 +4806,7 @@ dependencies = [ "mio", "pin-project-lite", "signal-hook-registry", - "socket2 0.6.2", + "socket2 0.6.3", "tokio-macros", "windows-sys 0.61.2", ] @@ -7661,18 +7657,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.40" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a789c6e490b576db9f7e6b6d661bcc9799f7c0ac8352f56ea20193b2681532e5" +checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.40" +version = "0.8.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" +checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f" dependencies = [ "proc-macro2", "quote", @@ -7771,4 +7767,4 @@ checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" dependencies = [ "cc", "pkg-config", -] \ No newline at end of file +]