diff --git a/.gitignore b/.gitignore index d7a6cf967..49b20fcc2 100644 --- a/.gitignore +++ b/.gitignore @@ -70,4 +70,8 @@ dkms.conf .cache # Platform dependent generated files -include/zenoh_configure.h \ No newline at end of file +include/zenoh_configure.h + +# Build resources +.build_resources* +src/opaque_types/mod.rs \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index ac02d01d7..e1b9b2a26 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -30,11 +30,12 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.7" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -42,18 +43,18 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.5" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c378d78423fdad8089616f827526ee33c19f2fddbd5de1629152c9593ba4783" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-tzdata" @@ -70,59 +71,11 @@ dependencies = [ "libc", ] -[[package]] -name = "anstream" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b09b5178381e0874812a9b157f7fe84982617e48f71f4e3235482775e5b540" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" - -[[package]] -name = "anstyle-parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" -dependencies = [ - "windows-sys 0.48.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" [[package]] name = "array-init" @@ -141,32 +94,44 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-channel" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" +dependencies = [ + "concurrent-queue", + "event-listener 5.3.0", + "event-listener-strategy 0.5.1", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-executor" -version = "1.5.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +checksum = "b10202063978b3351199d68f8b22c4e47e4b1b822f8d43fd862d5ea8c006b29a" dependencies = [ - "async-lock", "async-task", "concurrent-queue", - "fastrand 1.9.0", - "futures-lite", + "fastrand 2.0.2", + "futures-lite 2.3.0", "slab", ] [[package]] name = "async-global-executor" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1b6f5d7df27bd294849f8eec66ecfc63d11814df7a4f5d74168a2394467b776" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" dependencies = [ - "async-channel", + "async-channel 2.2.1", "async-executor", - "async-io", - "async-lock", + "async-io 2.3.2", + "async-lock 3.3.0", "blocking", - "futures-lite", + "futures-lite 2.3.0", "once_cell", "tokio", ] @@ -177,20 +142,39 @@ version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" dependencies = [ - "async-lock", + "async-lock 2.8.0", "autocfg", "cfg-if", "concurrent-queue", - "futures-lite", + "futures-lite 1.13.0", "log", "parking", - "polling", - "rustix 0.37.25", + "polling 2.8.0", + "rustix 0.37.27", "slab", - "socket2 0.4.9", + "socket2 0.4.10", "waker-fn", ] +[[package]] +name = "async-io" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +dependencies = [ + "async-lock 3.3.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.7.0", + "rustix 0.38.34", + "slab", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "async-lock" version = "2.8.0" @@ -200,40 +184,68 @@ dependencies = [ "event-listener 2.5.3", ] +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", + "pin-project-lite", +] + [[package]] name = "async-process" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a9d28b1d97e08915212e2e45310d47854eafa69600756fc735fb788f75199c9" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" dependencies = [ - "async-io", - "async-lock", - "autocfg", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", "blocking", "cfg-if", - "event-listener 2.5.3", - "futures-lite", - "rustix 0.37.25", - "signal-hook", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.34", "windows-sys 0.48.0", ] +[[package]] +name = "async-signal" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afe66191c335039c7bb78f99dc7520b0cbb166b3a1cb33a03f53d8a1c6f2afda" +dependencies = [ + "async-io 2.3.2", + "async-lock 3.3.0", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.34", + "signal-hook-registry", + "slab", + "windows-sys 0.52.0", +] + [[package]] name = "async-std" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" dependencies = [ - "async-channel", + "async-channel 1.9.0", "async-global-executor", - "async-io", - "async-lock", + "async-io 1.13.0", + "async-lock 2.8.0", "async-process", "crossbeam-utils", "futures-channel", "futures-core", "futures-io", - "futures-lite", + "futures-lite 1.13.0", "gloo-timers", "kv-log-macro", "log", @@ -247,26 +259,26 @@ dependencies = [ [[package]] name = "async-task" -version = "4.4.0" +version = "4.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" [[package]] name = "async-trait" -version = "0.1.73" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", ] [[package]] name = "atomic-waker" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1181e1e0d1fce796a03db1ae795d67167da795f9cf4a39c37589e85ef57f26d3" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atty" @@ -281,15 +293,15 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -302,9 +314,15 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.4" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" [[package]] name = "base64ct" @@ -329,9 +347,12 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] [[package]] name = "block-buffer" @@ -344,36 +365,37 @@ dependencies = [ [[package]] name = "blocking" -version = "1.3.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77231a1c8f801696fc0123ec6150ce92cffb8e164a02afb9c8ddee0e9b65ad65" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel", - "async-lock", + "async-channel 2.2.1", + "async-lock 3.3.0", "async-task", - "atomic-waker", - "fastrand 1.9.0", - "futures-lite", - "log", + "fastrand 2.0.2", + "futures-io", + "futures-lite 2.3.0", + "piper", + "tracing", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "cache-padded" @@ -383,9 +405,9 @@ checksum = "981520c98f422fcc584dc1a95c334e6953900b9106bc47a9839b81790009eb21" [[package]] name = "cbindgen" -version = "0.24.5" +version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b922faaf31122819ec80c4047cc684c6979a087366c069611e33649bf98e18d" +checksum = "da6bc11b07529f16944307272d5bd9b22530bc7d05751717c9d416586cedab49" dependencies = [ "clap", "heck", @@ -402,12 +424,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "d32a725bc159af97c3e629873bb9f88fb8cf8a4867175f76dc987815ea07c83b" [[package]] name = "cfg-if" @@ -417,16 +436,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.37" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -463,41 +482,35 @@ dependencies = [ "os_str_bytes", ] -[[package]] -name = "colorchoice" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" - [[package]] name = "concurrent-queue" -version = "2.2.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] [[package]] name = "const-oid" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f" +checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const_format" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c990efc7a285731f9a4378d81aff2f0e85a2c8781a05ef0f8baa8dac54d0ff48" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" dependencies = [ "const_format_proc_macros", ] [[package]] name = "const_format_proc_macros" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e026b6ce194a874cb9cf32cd5772d1ef9767cc8fcb5765948d74f37a9d8b2bf6" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" dependencies = [ "proc-macro2", "quote", @@ -506,9 +519,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -516,28 +529,40 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] [[package]] -name = "crossbeam-utils" -version = "0.8.16" +name = "crc" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ - "cfg-if", + "crc-catalog", ] +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + [[package]] name = "crypto-common" version = "0.1.6" @@ -550,15 +575,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308" +checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -600,19 +625,9 @@ dependencies = [ [[package]] name = "dyn-clone" -version = "1.0.13" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfc4744c1b8f2a09adc0e55242f60b1af195d88596bd8700be74418c056c555" - -[[package]] -name = "env_filter" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" -dependencies = [ - "log", - "regex", -] +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "env_logger" @@ -627,19 +642,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "env_logger" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c012a26a7f605efc424dd53697843a72be7dc86ad2d01f7814337794a12231d" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "humantime", - "log", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -664,15 +666,57 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "4.0.0" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770d968249b5d99410d61f5bf89057f3199a077a04d087092f58e7d10692baae" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" dependencies = [ "concurrent-queue", "parking", "pin-project-lite", ] +[[package]] +name = "event-listener" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d9944b8ca13534cdfb2800775f8dd4902ff3fc75a50101466decadfdf322a24" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "332f51cb23d20b0de8458b86580878211da09bcd4503cb579c225b3d124cabb3" +dependencies = [ + "event-listener 5.3.0", + "pin-project-lite", +] + [[package]] name = "fastrand" version = "1.9.0" @@ -714,9 +758,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -739,9 +783,9 @@ checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -754,9 +798,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -764,15 +808,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -781,9 +825,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-lite" @@ -800,34 +844,47 @@ dependencies = [ "waker-fn", ] +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.0.2", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -853,9 +910,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "js-sys", @@ -866,30 +923,28 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "git-version" -version = "0.3.5" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6b0decc02f4636b9ccad390dcbe77b722a77efedfa393caf8379a51d5c61899" +checksum = "1ad568aa3db0fcbc81f2f116137f263d7304f512a1209b35b85150d3ef88ad19" dependencies = [ "git-version-macro", - "proc-macro-hack", ] [[package]] name = "git-version-macro" -version = "0.3.5" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe69f1cbdb6e28af2bac214e943b99ce8a0a06b447d15d3e61161b0423139f3f" +checksum = "53010ccb100b96a67bc32c0175f0ed1426b31b655d562898e57325f81c023ac0" dependencies = [ - "proc-macro-hack", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.60", ] [[package]] @@ -904,6 +959,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + [[package]] name = "hashbrown" version = "0.12.3" @@ -921,9 +982,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.0" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash", "allocator-api2", @@ -946,9 +1007,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hmac" @@ -961,18 +1022,18 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "http" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -993,16 +1054,16 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.57" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad5b825842d2b38bd206f3e81d6957625fd7f0a361e345c30e01a0ae2dd613" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows 0.48.0", + "windows-core", ] [[package]] @@ -1016,9 +1077,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -1036,12 +1097,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.0.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5477fe2230a79769d8dc68e0eabf5437907c0457a5614a9e8dddb67f65eb65d" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.0", + "hashbrown 0.14.3", ] [[package]] @@ -1068,7 +1129,7 @@ version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.9", "libc", "windows-sys 0.48.0", ] @@ -1084,26 +1145,32 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" dependencies = [ - "hermit-abi 0.3.2", - "rustix 0.38.32", - "windows-sys 0.48.0", + "hermit-abi 0.3.9", + "libc", + "windows-sys 0.52.0", ] +[[package]] +name = "iter-read" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c397ca3ea05ad509c4ec451fea28b4771236a376ca1c69fd5143aae0cf8f93c4" + [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1121,9 +1188,9 @@ dependencies = [ [[package]] name = "keccak" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f6d5ed8676d904364de097082f4e7d240b571b67989ced0240f08b7f966f940" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" dependencies = [ "cpufeatures", ] @@ -1163,19 +1230,29 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.52.5", ] [[package]] name = "libm" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + +[[package]] +name = "libredox" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" +dependencies = [ + "bitflags 2.5.0", + "libc", +] [[package]] name = "linux-raw-sys" @@ -1191,37 +1268,55 @@ checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" -version = "0.4.10" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", ] +[[package]] +name = "lockfree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74ee94b5ad113c7cb98c5a040f783d0952ee4fe100993881d1673c2cb002dd23" +dependencies = [ + "owned-alloc", +] + [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ "value-bag", ] [[package]] name = "lz4_flex" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ea9b256699eda7b0387ffbc776dd625e28bde3918446381781245b7a50349d8" +checksum = "75761162ae2b0e580d7e7c390558127e5f01b4194debd6221fd8c207fc80e3f5" dependencies = [ "twox-hash", ] +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + [[package]] name = "memchr" -version = "2.6.3" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "memoffset" @@ -1234,9 +1329,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -1280,7 +1375,7 @@ version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.5.0", "cfg-if", "libc", ] @@ -1291,6 +1386,27 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-bigint-dig" version = "0.8.4" @@ -1310,19 +1426,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -1331,9 +1446,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", @@ -1345,24 +1460,24 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.2", + "hermit-abi 0.3.9", "libc", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl-probe" @@ -1378,9 +1493,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "ordered-float" -version = "4.1.1" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "536900a8093134cf9ccf00a27deb3532421099e958d9dd431135d0c7543ca1e8" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" dependencies = [ "num-traits", ] @@ -1391,11 +1506,23 @@ version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owned-alloc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30fceb411f9a12ff9222c5f824026be368ff15dc2f13468d850c7d3f502205d6" + [[package]] name = "parking" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" [[package]] name = "paste" @@ -1414,15 +1541,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.3" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33" +checksum = "311fb059dee1a7b802f036316d790138c613a4e8b180c822e3925a662e9f0c95" dependencies = [ "memchr", "thiserror", @@ -1431,9 +1558,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.3" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bee7be22ce7918f641a33f08e3f43388c7656772244e2bbb2477f44cc9021a" +checksum = "f73541b156d32197eecda1a4014d7f868fd2bcb3c550d5386087cfba442bf69c" dependencies = [ "pest", "pest_generator", @@ -1441,22 +1568,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.3" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1511785c5e98d79a05e8a6bc34b4ac2168a0e3e92161862030ad84daa223141" +checksum = "c35eeed0a3fab112f75165fdc026b3913f4183133f19b49be773ac9ea966e8bd" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", ] [[package]] name = "pest_meta" -version = "2.7.3" +version = "2.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f" +checksum = "2adbf29bb9776f28caece835398781ab24435585fe0d4dc1374a61db5accedca" dependencies = [ "once_cell", "pest", @@ -1470,14 +1597,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 2.0.0", + "indexmap 2.2.6", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.60", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1485,6 +1654,17 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.2", + "futures-io", +] + [[package]] name = "pkcs1" version = "0.7.5" @@ -1554,6 +1734,21 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "polling" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645493cf344456ef24219d02a768cf1fb92ddf8c92161679ae3d91b91a637be3" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.3.9", + "pin-project-lite", + "rustix 0.38.34", + "tracing", + "windows-sys 0.52.0", +] + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1561,16 +1756,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] -name = "proc-macro-hack" -version = "0.5.20+deprecated" +name = "proc-macro-crate" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -1586,7 +1784,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.21.7", + "rustls 0.21.12", "thiserror", "tokio", "tracing", @@ -1594,15 +1792,15 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.10.4" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13f81c9a9d574310b8351f8666f5a93ac3b0069c45c28ad52c10291389a7cf9" +checksum = "141bf7dfde2fbc246bfd3fe12f2455aa24b0fbd9af535d8c86c7bd1381ff2b1a" dependencies = [ "bytes", "rand", "ring 0.16.20", "rustc-hash", - "rustls 0.21.7", + "rustls 0.21.12", "rustls-native-certs 0.6.3", "slab", "thiserror", @@ -1625,9 +1823,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1662,54 +1860,60 @@ dependencies = [ "getrandom", ] -[[package]] -name = "redox_syscall" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", - "redox_syscall", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.5" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata", - "regex-syntax", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", ] [[package]] name = "regex-automata" -version = "0.3.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax", + "regex-syntax 0.8.3", ] [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "ring" @@ -1728,16 +1932,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.6" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684d5e6e18f669ccebf64a92236bb7db9a34f07be010e3627368182027180866" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted 0.9.0", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1750,18 +1955,28 @@ dependencies = [ "cache-padded", ] +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64 0.21.7", + "bitflags 2.5.0", + "serde", + "serde_derive", +] + [[package]] name = "rsa" -version = "0.9.2" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" dependencies = [ - "byteorder", "const-oid", "digest", "num-bigint-dig", "num-integer", - "num-iter", "num-traits", "pkcs1", "pkcs8", @@ -1795,9 +2010,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.25" +version = "0.37.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4eb579851244c2c03e7c24f501c3432bed80b8f720af1d6e5b0e0f01555a035" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" dependencies = [ "bitflags 1.3.2", "errno", @@ -1809,11 +2024,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys 0.4.13", @@ -1822,26 +2037,26 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.7" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d6c9f025a446bc4d18ad9632e69aec8f287aa84499ee335599fabd20c3fd8" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", - "ring 0.16.20", - "rustls-webpki 0.101.5", + "ring 0.17.8", + "rustls-webpki 0.101.7", "sct", ] [[package]] name = "rustls" -version = "0.22.2" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ "log", - "ring 0.17.6", + "ring 0.17.8", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki 0.102.3", "subtle", "zeroize", ] @@ -1853,7 +2068,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" dependencies = [ "openssl-probe", - "rustls-pemfile 1.0.3", + "rustls-pemfile 1.0.4", "schannel", "security-framework", ] @@ -1865,7 +2080,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792" dependencies = [ "openssl-probe", - "rustls-pemfile 2.0.0", + "rustls-pemfile 2.1.2", "rustls-pki-types", "schannel", "security-framework", @@ -1873,70 +2088,76 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.7", ] [[package]] name = "rustls-pemfile" -version = "2.0.0" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35e4980fa29e4c4b212ffb3db068a564cbf560e51d3944b7c88bd8bf5bec64f4" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64", + "base64 0.22.0", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8" +checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" [[package]] name = "rustls-webpki" -version = "0.101.5" +version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a27e3b59326c16e23d30aeb7a36a24cc0d29e71d68ff611cdfb4a01d013bed" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] name = "rustls-webpki" -version = "0.102.2" +version = "0.102.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +checksum = "f3bce581c0dd41bce533ce695a1437fa16a7ab5ac3ccfa99fe1a620a7885eabf" dependencies = [ - "ring 0.17.6", + "ring 0.17.8", "rustls-pki-types", "untrusted 0.9.0", ] [[package]] -name = "ryu" +name = "rustversion" version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "schemars" -version = "0.8.13" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763f8cd0d4c71ed8389c90cb8100cba87e763bd01a8e614d4f0af97bcd50a161" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "dyn-clone", "schemars_derive", @@ -1946,9 +2167,9 @@ dependencies = [ [[package]] name = "schemars_derive" -version = "0.8.13" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0f696e21e10fa546b7ffb1c9672c6de8fbc7a81acf59524386d8639bf12737" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" dependencies = [ "proc-macro2", "quote", @@ -1964,12 +2185,12 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring 0.17.8", + "untrusted 0.9.0", ] [[package]] @@ -1984,9 +2205,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -1997,9 +2218,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" dependencies = [ "core-foundation-sys", "libc", @@ -2007,28 +2228,51 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.18" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a" dependencies = [ "serde_derive", ] +[[package]] +name = "serde-pickle" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762ad136a26407c6a80825813600ceeab5e613660d93d79a41f0ec877171e71" +dependencies = [ + "byteorder", + "iter-read", + "num-bigint", + "num-traits", + "serde", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.199" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", ] [[package]] @@ -2044,9 +2288,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" dependencies = [ "itoa", "ryu", @@ -2055,11 +2299,11 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.25" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a49e178e4452f45cb61d0cd8cebc1b0fafd3e41929e996cef79aa3aca91f574" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.0.0", + "indexmap 2.2.6", "itoa", "ryu", "serde", @@ -2068,9 +2312,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -2079,15 +2323,21 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.7" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if", "cpufeatures", "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" @@ -2098,6 +2348,15 @@ dependencies = [ "keccak", ] +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + [[package]] name = "shared_memory" version = "0.12.4" @@ -2120,35 +2379,31 @@ dependencies = [ "dirs", ] -[[package]] -name = "signal-hook" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" -dependencies = [ - "libc", - "signal-hook-registry", -] - [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] [[package]] name = "signature" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500" +checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ "digest", "rand_core", ] +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + [[package]] name = "slab" version = "0.4.9" @@ -2160,15 +2415,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -2201,14 +2456,50 @@ dependencies = [ [[package]] name = "spki" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a" +checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" dependencies = [ "base64ct", "der", ] +[[package]] +name = "stabby" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ec04c5825384722310b6a1fd83023bee0bfdc838f7aa3069f0a59e10203836b" +dependencies = [ + "lazy_static", + "rustversion", + "stabby-abi", +] + +[[package]] +name = "stabby-abi" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976322da1deb6cc64a8406fd24378b840b1962acaac1978a993131c3838d81b3" +dependencies = [ + "libc", + "rustversion", + "sha2-const-stable", + "stabby-macros", +] + +[[package]] +name = "stabby-macros" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736712a13ab37b1fa6e073831efca751bbcb31033af4d7308bd5d9d605939183" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "rand", + "syn 1.0.109", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -2221,7 +2512,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af91f480ee899ab2d9f8435bfdfc14d08a5754bd9d3fef1f1a1c23336aad6c8b" dependencies = [ - "async-channel", + "async-channel 1.9.0", "cfg-if", "futures-core", "pin-project-lite", @@ -2252,9 +2543,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.33" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9caece70c63bfba29ec2fed841a09851b14a235c60010fa4de58089b6c025668" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -2269,7 +2560,7 @@ checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand 2.0.2", - "rustix 0.38.32", + "rustix 0.38.34", "windows-sys 0.52.0", ] @@ -2290,22 +2581,46 @@ checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.48" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.48" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" dependencies = [ "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", +] + +[[package]] +name = "thread-priority" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72cb4958060ee2d9540cef68bb3871fd1e547037772c7fe7650d5d1cbec53b3" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "log", + "rustversion", + "winapi", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", ] [[package]] @@ -2334,9 +2649,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.36.0" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" dependencies = [ "backtrace", "bytes", @@ -2357,7 +2672,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", ] [[package]] @@ -2366,7 +2681,7 @@ version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "rustls 0.21.7", + "rustls 0.21.12", "tokio", ] @@ -2376,7 +2691,7 @@ version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ - "rustls 0.22.2", + "rustls 0.22.4", "rustls-pki-types", "tokio", ] @@ -2403,7 +2718,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "hashbrown 0.14.0", + "hashbrown 0.14.3", "pin-project-lite", "tokio", ] @@ -2417,13 +2732,29 @@ dependencies = [ "serde", ] +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "log", "pin-project-lite", "tracing-attributes", @@ -2432,22 +2763,65 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ + "matchers", + "nu-ansi-term", "once_cell", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", ] [[package]] @@ -2481,9 +2855,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" @@ -2507,9 +2881,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -2519,9 +2893,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -2534,9 +2908,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "untrusted" @@ -2550,6 +2924,12 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "unwrap-infallible" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151ac09978d3c2862c4e39b557f4eceee2cc72150bc4cb4f16abf061b6e381fb" + [[package]] name = "unzip-n" version = "0.1.2" @@ -2563,9 +2943,9 @@ dependencies = [ [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -2578,17 +2958,11 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf8parse" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" - [[package]] name = "uuid" -version = "1.4.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" dependencies = [ "getrandom", ] @@ -2617,11 +2991,17 @@ dependencies = [ "unzip-n", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "value-bag" -version = "1.4.1" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92ccd67fb88503048c01b59152a04effd0782d035a83a6d256ce6085f08f4a3" +checksum = "74797339c3b98616c009c7c3eb53a0ce41e85c8ec66bd3db96ed132d20cfdee8" [[package]] name = "vec_map" @@ -2637,9 +3017,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "waker-fn" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" [[package]] name = "wasi" @@ -2649,9 +3029,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2659,24 +3039,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -2686,9 +3066,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2696,28 +3076,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -2725,9 +3105,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de2cfda980f21be5a7ed2eadb3e6fe074d56022bea2cdeb1a62eb220fc04188" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" dependencies = [ "rustls-pki-types", ] @@ -2738,7 +3118,7 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b7b128a98c1cfa201b09eb49ba285887deb3cbe7466a98850eb1adabb452be5" dependencies = [ - "windows 0.34.0", + "windows", ] [[package]] @@ -2759,11 +3139,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -2786,12 +3166,12 @@ dependencies = [ ] [[package]] -name = "windows" -version = "0.48.0" +name = "windows-core" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -2809,7 +3189,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -2829,17 +3209,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -2850,9 +3231,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -2868,9 +3249,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -2886,9 +3267,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -2904,9 +3291,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -2922,9 +3309,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -2934,9 +3321,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -2952,39 +3339,53 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] [[package]] name = "zenoh" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ + "ahash", "async-trait", - "base64", + "base64 0.21.7", "const_format", - "env_logger 0.11.2", - "event-listener 4.0.0", + "event-listener 4.0.3", "flume", "form_urlencoded", "futures", "git-version", "lazy_static", - "log", "ordered-float", "paste", "petgraph", + "phf", "rand", "regex", "rustc_version", "serde", + "serde-pickle", + "serde_cbor", "serde_json", + "serde_yaml", "socket2 0.5.6", "stop-token", "tokio", "tokio-util", + "tracing", "uhlc", + "unwrap-infallible", "uuid", "vec_map", "zenoh-buffers", @@ -3010,7 +3411,7 @@ dependencies = [ [[package]] name = "zenoh-buffers" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "zenoh-collections", ] @@ -3023,7 +3424,8 @@ dependencies = [ "async-trait", "cbindgen", "chrono", - "env_logger 0.10.2", + "const_format", + "env_logger", "fs2", "fs_extra", "futures", @@ -3032,8 +3434,10 @@ dependencies = [ "libc", "log", "rand", + "regex", "serde_yaml", "spin 0.9.8", + "unwrap-infallible", "zenoh", "zenoh-ext", "zenoh-protocol", @@ -3043,10 +3447,10 @@ dependencies = [ [[package]] name = "zenoh-codec" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ - "log", "serde", + "tracing", "uhlc", "zenoh-buffers", "zenoh-protocol", @@ -3056,21 +3460,21 @@ dependencies = [ [[package]] name = "zenoh-collections" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" [[package]] name = "zenoh-config" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "flume", "json5", - "log", "num_cpus", "secrecy", "serde", "serde_json", "serde_yaml", + "tracing", "validated_struct", "zenoh-core", "zenoh-protocol", @@ -3081,7 +3485,7 @@ dependencies = [ [[package]] name = "zenoh-core" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-global-executor", "lazy_static", @@ -3093,7 +3497,7 @@ dependencies = [ [[package]] name = "zenoh-crypto" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "aes", "hmac", @@ -3106,15 +3510,17 @@ dependencies = [ [[package]] name = "zenoh-ext" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "bincode", - "env_logger 0.11.2", "flume", "futures", - "log", + "phf", "serde", + "serde_cbor", + "serde_json", "tokio", + "tracing", "zenoh", "zenoh-core", "zenoh-macros", @@ -3128,9 +3534,9 @@ dependencies = [ [[package]] name = "zenoh-keyexpr" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ - "hashbrown 0.14.0", + "hashbrown 0.14.3", "keyed-set", "rand", "schemars", @@ -3142,7 +3548,7 @@ dependencies = [ [[package]] name = "zenoh-link" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-trait", "zenoh-config", @@ -3160,17 +3566,17 @@ dependencies = [ [[package]] name = "zenoh-link-commons" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-trait", "flume", "futures", - "log", - "rustls 0.22.2", - "rustls-webpki 0.102.2", + "rustls 0.22.4", + "rustls-webpki 0.102.3", "serde", "tokio", "tokio-util", + "tracing", "zenoh-buffers", "zenoh-codec", "zenoh-core", @@ -3183,21 +3589,22 @@ dependencies = [ [[package]] name = "zenoh-link-quic" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-trait", - "base64", + "base64 0.21.7", "futures", - "log", "quinn", - "rustls 0.21.7", + "rustls 0.21.12", "rustls-native-certs 0.7.0", - "rustls-pemfile 2.0.0", - "rustls-webpki 0.102.2", + "rustls-pemfile 2.1.2", + "rustls-webpki 0.102.3", "secrecy", "tokio", "tokio-rustls 0.24.1", "tokio-util", + "tracing", + "zenoh-collections", "zenoh-config", "zenoh-core", "zenoh-link-commons", @@ -3211,12 +3618,12 @@ dependencies = [ [[package]] name = "zenoh-link-tcp" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-trait", - "log", "tokio", "tokio-util", + "tracing", "zenoh-core", "zenoh-link-commons", "zenoh-protocol", @@ -3229,21 +3636,22 @@ dependencies = [ [[package]] name = "zenoh-link-tls" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-trait", - "base64", + "base64 0.21.7", "futures", - "log", - "rustls 0.22.2", - "rustls-pemfile 2.0.0", + "rustls 0.22.4", + "rustls-pemfile 2.1.2", "rustls-pki-types", - "rustls-webpki 0.102.2", + "rustls-webpki 0.102.3", "secrecy", "tokio", "tokio-rustls 0.25.0", "tokio-util", + "tracing", "webpki-roots", + "zenoh-collections", "zenoh-config", "zenoh-core", "zenoh-link-commons", @@ -3257,13 +3665,13 @@ dependencies = [ [[package]] name = "zenoh-link-udp" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-trait", - "log", "socket2 0.5.6", "tokio", "tokio-util", + "tracing", "zenoh-buffers", "zenoh-collections", "zenoh-core", @@ -3278,14 +3686,14 @@ dependencies = [ [[package]] name = "zenoh-link-unixsock_stream" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-trait", "futures", - "log", "nix 0.27.1", "tokio", "tokio-util", + "tracing", "uuid", "zenoh-core", "zenoh-link-commons", @@ -3298,14 +3706,14 @@ dependencies = [ [[package]] name = "zenoh-link-ws" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-trait", "futures-util", - "log", "tokio", "tokio-tungstenite", "tokio-util", + "tracing", "url", "zenoh-core", "zenoh-link-commons", @@ -3319,24 +3727,24 @@ dependencies = [ [[package]] name = "zenoh-macros" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", "zenoh-keyexpr", ] [[package]] name = "zenoh-plugin-trait" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "const_format", "libloading", - "log", "serde", "serde_json", + "tracing", "zenoh-keyexpr", "zenoh-macros", "zenoh-result", @@ -3346,13 +3754,14 @@ dependencies = [ [[package]] name = "zenoh-protocol" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "const_format", "rand", "serde", "uhlc", "zenoh-buffers", + "zenoh-collections", "zenoh-keyexpr", "zenoh-result", ] @@ -3360,7 +3769,7 @@ dependencies = [ [[package]] name = "zenoh-result" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "anyhow", ] @@ -3368,33 +3777,49 @@ dependencies = [ [[package]] name = "zenoh-runtime" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "futures", "lazy_static", + "libc", + "ron", + "serde", "tokio", "zenoh-collections", + "zenoh-macros", "zenoh-result", ] [[package]] name = "zenoh-shm" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ - "log", + "async-trait", + "bincode", + "crc", + "lazy_static", + "lockfree", + "num-traits", + "rand", "serde", "shared_memory", + "stabby", + "thread-priority", + "tokio", + "tracing", "zenoh-buffers", + "zenoh-core", + "zenoh-macros", "zenoh-result", ] [[package]] name = "zenoh-sync" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ - "event-listener 4.0.0", + "event-listener 4.0.3", "futures", "tokio", "zenoh-buffers", @@ -3406,12 +3831,12 @@ dependencies = [ [[package]] name = "zenoh-task" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "futures", - "log", "tokio", "tokio-util", + "tracing", "zenoh-core", "zenoh-runtime", ] @@ -3419,11 +3844,10 @@ dependencies = [ [[package]] name = "zenoh-transport" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-trait", "flume", - "log", "lz4_flex", "paste", "rand", @@ -3433,6 +3857,7 @@ dependencies = [ "sha3", "tokio", "tokio-util", + "tracing", "zenoh-buffers", "zenoh-codec", "zenoh-collections", @@ -3452,7 +3877,7 @@ dependencies = [ [[package]] name = "zenoh-util" version = "0.11.0-dev" -source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=main#d594afbc358be0e8379a25ed985a1fcc1e36f2d8" +source = "git+https://github.com/ZettaScaleLabs/zenoh.git?branch=shm_watchdog_poc#0694040c57a5475bf09858e83bb7ebfd8aec541f" dependencies = [ "async-std", "async-trait", @@ -3462,10 +3887,11 @@ dependencies = [ "lazy_static", "libc", "libloading", - "log", "pnet_datalink", "shellexpand", "tokio", + "tracing", + "tracing-subscriber", "winapi", "zenoh-core", "zenoh-result", @@ -3488,11 +3914,11 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.33", + "syn 2.0.60", ] [[package]] name = "zeroize" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/Cargo.toml b/Cargo.toml index a654da5db..f7a9c7b0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ build = "build.rs" [features] logger-autoinit = [] shared-memory = ["zenoh/shared-memory"] +unstable = ["zenoh/unstable"] default = ["zenoh/default"] [badges] @@ -41,7 +42,7 @@ maintenance = { status = "actively-developed" } [dependencies] async-std = "=1.12.0" async-trait = "0.1.66" -chrono = "0.4.34" +chrono = "0.4.37" env_logger = "0.10.0" futures = "0.3.26" json5 = "0.4.1" @@ -50,21 +51,24 @@ libc = "0.2.139" log = "0.4.17" rand = "0.8.5" spin = "0.9.5" +unwrap-infallible = "0.1.5" +const_format = "0.2.32" # shared-memory enabled for zenoh even if zenoh-c "shared-memory" feature is disabled. This is to make "std::mem::transmute" work for `ZSLice` -zenoh = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["shared-memory", "unstable"], default-features = false } -zenoh-protocol = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["shared-memory"] } -zenoh-util = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main" } -zenoh-ext = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["unstable"] } +zenoh = { version = "0.11.0-dev", git = "https://github.com/ZettaScaleLabs/zenoh.git", branch = "shm_refine", features = ["shared-memory", "unstable"], default-features = false } +zenoh-protocol = { version = "0.11.0-dev", git = "https://github.com/ZettaScaleLabs/zenoh.git", branch = "shm_refine", features = ["shared-memory"] } +zenoh-util = { version = "0.11.0-dev", git = "https://github.com/ZettaScaleLabs/zenoh.git", branch = "shm_refine" } +zenoh-ext = { version = "0.11.0-dev", git = "https://github.com/ZettaScaleLabs/zenoh.git", branch = "shm_refine", features = ["unstable"] } [build-dependencies] -cbindgen = "0.24.3" +cbindgen = "0.26.0" fs2 = "0.4.3" +regex = "1.7.1" serde_yaml = "0.9.19" fs_extra = "1.3.0" [lib] path="src/lib.rs" -name = "zenohc" +name = "zenohcd" crate-type = ["cdylib", "staticlib"] doctest = false diff --git a/Cargo.toml.in b/Cargo.toml.in index be9b3f1b7..60889e77b 100644 --- a/Cargo.toml.in +++ b/Cargo.toml.in @@ -33,6 +33,7 @@ build = "@CARGO_PROJECT_DIR@build.rs" [features] logger-autoinit = [] shared-memory = ["zenoh/shared-memory"] +unstable = ["zenoh/unstable"] default = ["zenoh/default"] [badges] @@ -41,7 +42,7 @@ maintenance = { status = "actively-developed" } [dependencies] async-std = "=1.12.0" async-trait = "0.1.66" -chrono = "0.4.34" +chrono = "0.4.37" env_logger = "0.10.0" futures = "0.3.26" json5 = "0.4.1" @@ -50,15 +51,18 @@ libc = "0.2.139" log = "0.4.17" rand = "0.8.5" spin = "0.9.5" +unwrap-infallible = "0.1.5" +const_format = "0.2.32" # shared-memory enabled for zenoh even if zenoh-c "shared-memory" feature is disabled. This is to make "std::mem::transmute" work for `ZSLice` -zenoh = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["shared-memory", "unstable"], default-features = false } -zenoh-protocol = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["shared-memory"] } -zenoh-util = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main" } -zenoh-ext = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "main", features = ["unstable"] } +zenoh = { version = "0.11.0-dev", git = "https://github.com/ZettaScaleLabs/zenoh.git", branch = "shm_refine", features = ["shared-memory", "unstable"], default-features = false } +zenoh-protocol = { version = "0.11.0-dev", git = "https://github.com/ZettaScaleLabs/zenoh.git", branch = "shm_refine", features = ["shared-memory"] } +zenoh-util = { version = "0.11.0-dev", git = "https://github.com/ZettaScaleLabs/zenoh.git", branch = "shm_refine" } +zenoh-ext = { version = "0.11.0-dev", git = "https://github.com/ZettaScaleLabs/zenoh.git", branch = "shm_refine", features = ["unstable"] } [build-dependencies] -cbindgen = "0.24.3" +cbindgen = "0.26.0" fs2 = "0.4.3" +regex = "1.7.1" serde_yaml = "0.9.19" fs_extra = "1.3.0" diff --git a/build-resources/opaque-types/Cargo.lock b/build-resources/opaque-types/Cargo.lock new file mode 100644 index 000000000..ec5cafe8e --- /dev/null +++ b/build-resources/opaque-types/Cargo.lock @@ -0,0 +1,2998 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[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.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "anyhow" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" + +[[package]] +name = "array-init" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d62b7694a562cdf5a74227903507c56ab2cc8bdd1f781ed5cb4cf9c9f810bfc" + +[[package]] +name = "async-channel" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" +dependencies = [ + "concurrent-queue", + "event-listener 2.5.3", + "futures-core", +] + +[[package]] +name = "async-channel" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +dependencies = [ + "concurrent-queue", + "event-listener 5.2.0", + "event-listener-strategy 0.5.0", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-executor" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17ae5ebefcc48e7452b4987947920dac9450be1110cadf34d1b8c116bdbaf97c" +dependencies = [ + "async-lock 3.3.0", + "async-task", + "concurrent-queue", + "fastrand 2.0.2", + "futures-lite 2.3.0", + "slab", +] + +[[package]] +name = "async-global-executor" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b1b633a2115cd122d73b955eadd9916c18c8f510ec9cd1686404c60ad1c29c" +dependencies = [ + "async-channel 2.2.0", + "async-executor", + "async-io 2.3.2", + "async-lock 3.3.0", + "blocking", + "futures-lite 2.3.0", + "once_cell", + "tokio", +] + +[[package]] +name = "async-io" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fc5b45d93ef0529756f812ca52e44c221b35341892d3dcc34132ac02f3dd2af" +dependencies = [ + "async-lock 2.8.0", + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-lite 1.13.0", + "log", + "parking", + "polling 2.8.0", + "rustix 0.37.27", + "slab", + "socket2 0.4.10", + "waker-fn", +] + +[[package]] +name = "async-io" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcccb0f599cfa2f8ace422d3555572f47424da5648a4382a9dd0310ff8210884" +dependencies = [ + "async-lock 3.3.0", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite 2.3.0", + "parking", + "polling 3.6.0", + "rustix 0.38.32", + "slab", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "async-lock" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "287272293e9d8c41773cec55e365490fe034813a2f172f502d6ddcf75b2f582b" +dependencies = [ + "event-listener 2.5.3", +] + +[[package]] +name = "async-lock" +version = "3.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d034b430882f8381900d3fe6f0aaa3ad94f2cb4ac519b429692a1bc2dda4ae7b" +dependencies = [ + "event-listener 4.0.3", + "event-listener-strategy 0.4.0", + "pin-project-lite", +] + +[[package]] +name = "async-process" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6438ba0a08d81529c69b36700fa2f95837bfe3e776ab39cde9c14d9149da88" +dependencies = [ + "async-io 1.13.0", + "async-lock 2.8.0", + "async-signal", + "blocking", + "cfg-if", + "event-listener 3.1.0", + "futures-lite 1.13.0", + "rustix 0.38.32", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-signal" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" +dependencies = [ + "async-io 2.3.2", + "async-lock 2.8.0", + "atomic-waker", + "cfg-if", + "futures-core", + "futures-io", + "rustix 0.38.32", + "signal-hook-registry", + "slab", + "windows-sys 0.48.0", +] + +[[package]] +name = "async-std" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62565bb4402e926b29953c785397c6dc0391b7b446e45008b0049eb43cec6f5d" +dependencies = [ + "async-channel 1.9.0", + "async-global-executor", + "async-io 1.13.0", + "async-lock 2.8.0", + "async-process", + "crossbeam-utils", + "futures-channel", + "futures-core", + "futures-io", + "futures-lite 1.13.0", + "gloo-timers", + "kv-log-macro", + "log", + "memchr", + "once_cell", + "pin-project-lite", + "pin-utils", + "slab", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-task" +version = "4.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb36e985947064623dbd357f727af08ffd077f93d696782f3c56365fa2e2799" + +[[package]] +name = "async-trait" +version = "0.1.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.21.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "bincode" +version = "1.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +dependencies = [ + "serde", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +dependencies = [ + "serde", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "blocking" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" +dependencies = [ + "async-channel 2.2.0", + "async-lock 3.3.0", + "async-task", + "fastrand 2.0.2", + "futures-io", + "futures-lite 2.3.0", + "piper", + "tracing", +] + +[[package]] +name = "bumpalo" +version = "3.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" + +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cache-padded" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "981520c98f422fcc584dc1a95c334e6953900b9106bc47a9839b81790009eb21" + +[[package]] +name = "cc" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[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 = "concurrent-queue" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "const_format" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a214c7af3d04997541b18d432afaff4c455e79e2029079647e72fc2bd27673" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7f6ff08fd20f4f299298a28e2dfa8a8ba1036e6cd2460ac1de7b425d76f2500" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "cpufeatures" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +dependencies = [ + "libc", +] + +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + +[[package]] +name = "crossbeam-utils" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + +[[package]] +name = "dyn-clone" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "event-listener" +version = "2.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" + +[[package]] +name = "event-listener" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d93877bcde0eb80ca09131a08d23f0a5c18a620b01db137dba666d18cd9b30c2" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener" +version = "5.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b5fb89194fa3cad959b833185b3063ba881dbfc7030680b314250779fb4cc91" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +dependencies = [ + "event-listener 4.0.3", + "pin-project-lite", +] + +[[package]] +name = "event-listener-strategy" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feedafcaa9b749175d5ac357452a9d41ea2911da598fde46ce1fe02c37751291" +dependencies = [ + "event-listener 5.2.0", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + +[[package]] +name = "fastrand" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" + +[[package]] +name = "fixedbitset" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" + +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "nanorand", + "spin", +] + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand 1.9.0", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand 2.0.2", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[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.55", +] + +[[package]] +name = "gloo-timers" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "half" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" +dependencies = [ + "ahash", +] + +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[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.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "indexmap" +version = "2.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", +] + +[[package]] +name = "inout" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" +dependencies = [ + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "io-lifetimes" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2" +dependencies = [ + "hermit-abi", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "ipnetwork" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" +dependencies = [ + "serde", +] + +[[package]] +name = "iter-read" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c397ca3ea05ad509c4ec451fea28b4771236a376ca1c69fd5143aae0cf8f93c4" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "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.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc2af9a1119c51f12a14607e783cb977bde58bc069ff0c3da1095e635d70654" +dependencies = [ + "cpufeatures", +] + +[[package]] +name = "keyed-set" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b79e110283e09081809ca488cf3a9709270c6d4d4c4a32674c39cc438366615a" +dependencies = [ + "hashbrown 0.13.2", +] + +[[package]] +name = "kv-log-macro" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de8b303297635ad57c9f5059fd9cee7a47f8e8daa09df0fcd07dd39fb22977f" +dependencies = [ + "log", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.153" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libloading" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +dependencies = [ + "cfg-if", + "windows-targets 0.52.4", +] + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.5.0", + "libc", + "redox_syscall", +] + +[[package]] +name = "linux-raw-sys" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "lock_api" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "lockfree" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74ee94b5ad113c7cb98c5a040f783d0952ee4fe100993881d1673c2cb002dd23" +dependencies = [ + "owned-alloc", +] + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +dependencies = [ + "value-bag", +] + +[[package]] +name = "lz4_flex" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "912b45c753ff5f7f5208307e8ace7d2a2e30d024e26d3509f3dce546c044ce15" +dependencies = [ + "twox-hash", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "nanorand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +dependencies = [ + "getrandom", +] + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags 1.3.2", + "cc", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-bigint" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +dependencies = [ + "autocfg", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "opaque-types" +version = "0.1.0" +dependencies = [ + "const_format", + "zenoh", + "zenoh-ext", +] + +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + +[[package]] +name = "ordered-float" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +dependencies = [ + "num-traits", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "owned-alloc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30fceb411f9a12ff9222c5f824026be368ff15dc2f13468d850c7d3f502205d6" + +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + +[[package]] +name = "paste" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pest" +version = "2.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +dependencies = [ + "memchr", + "thiserror", + "ucd-trie", +] + +[[package]] +name = "pest_derive" +version = "2.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" +dependencies = [ + "pest", + "pest_generator", +] + +[[package]] +name = "pest_generator" +version = "2.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" +dependencies = [ + "pest", + "pest_meta", + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "pest_meta" +version = "2.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" +dependencies = [ + "once_cell", + "pest", + "sha2", +] + +[[package]] +name = "petgraph" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" +dependencies = [ + "fixedbitset", + "indexmap", +] + +[[package]] +name = "phf" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +dependencies = [ + "phf_macros", + "phf_shared", +] + +[[package]] +name = "phf_generator" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +dependencies = [ + "phf_shared", + "rand", +] + +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator", + "phf_shared", + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "phf_shared" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "piper" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +dependencies = [ + "atomic-waker", + "fastrand 2.0.2", + "futures-io", +] + +[[package]] +name = "pnet_base" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c" +dependencies = [ + "no-std-net", +] + +[[package]] +name = "pnet_datalink" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad5854abf0067ebbd3967f7d45ebc8976ff577ff0c7bd101c4973ae3c70f98fe" +dependencies = [ + "ipnetwork", + "libc", + "pnet_base", + "pnet_sys", + "winapi", +] + +[[package]] +name = "pnet_sys" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "417c0becd1b573f6d544f73671070b039051e5ad819cc64aa96377b536128d00" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "polling" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b2d323e8ca7996b3e23126511a523f7e62924d93ecd5ae73b333815b0eb3dce" +dependencies = [ + "autocfg", + "bitflags 1.3.2", + "cfg-if", + "concurrent-queue", + "libc", + "log", + "pin-project-lite", + "windows-sys 0.48.0", +] + +[[package]] +name = "polling" +version = "3.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c976a60b2d7e99d6f229e414670a9b85d13ac305cc6d1e9c134de58c5aaaf6" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix 0.38.32", + "tracing", + "windows-sys 0.52.0", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "redox_syscall" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +dependencies = [ + "bitflags 1.3.2", +] + +[[package]] +name = "redox_users" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.6", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.3", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" + +[[package]] +name = "ring" +version = "0.17.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" +dependencies = [ + "cc", + "cfg-if", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "ringbuffer-spsc" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fd1938faa63a2362ee1747afb2d10567d0fb1413b9cbd6198a8541485c4f773" +dependencies = [ + "array-init", + "cache-padded", +] + +[[package]] +name = "ron" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +dependencies = [ + "base64", + "bitflags 2.5.0", + "serde", + "serde_derive", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustc_version" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +dependencies = [ + "semver", +] + +[[package]] +name = "rustix" +version = "0.37.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea8ca367a3a01fe35e6943c400addf443c0f57670e6ec51196f71a4b8762dd2" +dependencies = [ + "bitflags 1.3.2", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys 0.3.8", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustix" +version = "0.38.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys 0.4.13", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" +dependencies = [ + "log", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd36cc4259e3e4514335c4a138c6b43171a8d61d8f5c9348f9fc7529416f247" + +[[package]] +name = "rustls-webpki" +version = "0.102.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80af6f9131f277a45a3fba6ce8e2258037bb0477a67e610d3c1fe046ab31de47" + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schemars" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" +dependencies = [ + "dyn-clone", + "schemars_derive", + "serde", + "serde_json", +] + +[[package]] +name = "schemars_derive" +version = "0.8.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c767fd6fa65d9ccf9cf026122c1b555f2ef9a4f0cea69da4d7dbc3e258d30967" +dependencies = [ + "proc-macro2", + "quote", + "serde_derive_internals", + "syn 1.0.109", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "serde", + "zeroize", +] + +[[package]] +name = "semver" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" + +[[package]] +name = "serde" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-pickle" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c762ad136a26407c6a80825813600ceeab5e613660d93d79a41f0ec877171e71" +dependencies = [ + "byteorder", + "iter-read", + "num-bigint", + "num-traits", + "serde", +] + +[[package]] +name = "serde_cbor" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" +dependencies = [ + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.197" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "serde_derive_internals" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85bf8229e7920a9f636479437026331ce11aa132b4dde37d121944a44d6e5f3c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "serde_json" +version = "1.0.115" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shared_memory" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba8593196da75d9dc4f69349682bd4c2099f8cde114257d1ef7ef1b33d1aba54" +dependencies = [ + "cfg-if", + "libc", + "nix", + "rand", + "win-sys", +] + +[[package]] +name = "shellexpand" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +dependencies = [ + "dirs", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +dependencies = [ + "libc", +] + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] + +[[package]] +name = "stabby" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ec04c5825384722310b6a1fd83023bee0bfdc838f7aa3069f0a59e10203836b" +dependencies = [ + "lazy_static", + "rustversion", + "stabby-abi", +] + +[[package]] +name = "stabby-abi" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976322da1deb6cc64a8406fd24378b840b1962acaac1978a993131c3838d81b3" +dependencies = [ + "libc", + "rustversion", + "sha2-const-stable", + "stabby-macros", +] + +[[package]] +name = "stabby-macros" +version = "4.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "736712a13ab37b1fa6e073831efca751bbcb31033af4d7308bd5d9d605939183" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "rand", + "syn 1.0.109", +] + +[[package]] +name = "static_assertions" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" + +[[package]] +name = "stop-token" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af91f480ee899ab2d9f8435bfdfc14d08a5754bd9d3fef1f1a1c23336aad6c8b" +dependencies = [ + "async-channel 1.9.0", + "cfg-if", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "subtle" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "thread-priority" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b72cb4958060ee2d9540cef68bb3871fd1e547037772c7fe7650d5d1cbec53b3" +dependencies = [ + "bitflags 1.3.2", + "cfg-if", + "libc", + "log", + "rustversion", + "winapi", +] + +[[package]] +name = "thread_local" +version = "1.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +dependencies = [ + "cfg-if", + "once_cell", +] + +[[package]] +name = "token-cell" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a2b964fdb303b08a4eab04d7c1bad2bca33f8eee334ccd28802f1041c6eb87" +dependencies = [ + "paste", +] + +[[package]] +name = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2 0.5.6", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "futures-util", + "hashbrown 0.14.3", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml_datetime" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" + +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-serde" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc6b213177105856957181934e4920de57730fc69bf42c37ee5bb664d406d9e1" +dependencies = [ + "serde", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "serde", + "serde_json", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", + "tracing-serde", +] + +[[package]] +name = "twox-hash" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" +dependencies = [ + "cfg-if", + "static_assertions", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "ucd-trie" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" + +[[package]] +name = "uhlc" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99b6df3f3e948b40e20c38a6d1fd6d8f91b3573922fc164e068ad3331560487e" +dependencies = [ + "humantime", + "lazy_static", + "log", + "rand", + "serde", + "spin", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-xid" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" + +[[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 = "unwrap-infallible" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "151ac09978d3c2862c4e39b557f4eceee2cc72150bc4cb4f16abf061b6e381fb" + +[[package]] +name = "unzip-n" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2e7e85a0596447f0f2ac090e16bc4c516c6fe91771fb0c0ccf7fa3dae896b9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "uuid" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +dependencies = [ + "getrandom", +] + +[[package]] +name = "validated_struct" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "feef04c049b4beae3037a2a31b8da40d8cebec0b97456f24c7de0ede4ed9efed" +dependencies = [ + "json5", + "serde", + "serde_json", + "validated_struct_macros", +] + +[[package]] +name = "validated_struct_macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d4444a980afa9ef0d29c2a3f4d952ec0495a7a996a9c78b52698b71bc21edb4" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", + "unzip-n", +] + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "value-bag" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74797339c3b98616c009c7c3eb53a0ce41e85c8ec66bd3db96ed132d20cfdee8" + +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "waker-fn" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c4517f54858c779bbcbf228f4fca63d121bf85fbecb2dc578cdf4a39395690" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.55", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "win-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b7b128a98c1cfa201b09eb49ba285887deb3cbe7466a98850eb1adabb452be5" +dependencies = [ + "windows", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45296b64204227616fdbf2614cefa4c236b98ee64dfaaaa435207ed99fe7829f" +dependencies = [ + "windows_aarch64_msvc 0.34.0", + "windows_i686_gnu 0.34.0", + "windows_i686_msvc 0.34.0", + "windows_x86_64_gnu 0.34.0", + "windows_x86_64_msvc 0.34.0", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17cffbe740121affb56fad0fc0e421804adf0ae00891205213b5cecd30db881d" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" + +[[package]] +name = "windows_i686_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2564fde759adb79129d9b4f54be42b32c89970c18ebf93124ca8870a498688ed" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" + +[[package]] +name = "windows_i686_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cd9d32ba70453522332c14d38814bceeb747d80b3958676007acadd7e166956" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfce6deae227ee8d356d19effc141a509cc503dfd1f850622ec4b0f84428e1f4" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d19538ccc21819d01deaf88d6a17eae6596a12e9aafdbb97916fb49896d89de9" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "zenoh" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "ahash", + "async-trait", + "base64", + "const_format", + "event-listener 4.0.3", + "flume", + "form_urlencoded", + "futures", + "git-version", + "lazy_static", + "ordered-float", + "paste", + "petgraph", + "phf", + "rand", + "regex", + "rustc_version", + "serde", + "serde-pickle", + "serde_cbor", + "serde_json", + "serde_yaml", + "socket2 0.5.6", + "stop-token", + "tokio", + "tokio-util", + "tracing", + "uhlc", + "unwrap-infallible", + "uuid", + "vec_map", + "zenoh-buffers", + "zenoh-codec", + "zenoh-collections", + "zenoh-config", + "zenoh-core", + "zenoh-crypto", + "zenoh-keyexpr", + "zenoh-link", + "zenoh-macros", + "zenoh-plugin-trait", + "zenoh-protocol", + "zenoh-result", + "zenoh-runtime", + "zenoh-shm", + "zenoh-sync", + "zenoh-task", + "zenoh-transport", + "zenoh-util", +] + +[[package]] +name = "zenoh-buffers" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "zenoh-collections", +] + +[[package]] +name = "zenoh-codec" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "serde", + "tracing", + "uhlc", + "zenoh-buffers", + "zenoh-protocol", + "zenoh-shm", +] + +[[package]] +name = "zenoh-collections" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" + +[[package]] +name = "zenoh-config" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "flume", + "json5", + "num_cpus", + "secrecy", + "serde", + "serde_json", + "serde_yaml", + "tracing", + "validated_struct", + "zenoh-core", + "zenoh-protocol", + "zenoh-result", + "zenoh-util", +] + +[[package]] +name = "zenoh-core" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "async-global-executor", + "lazy_static", + "tokio", + "zenoh-result", + "zenoh-runtime", +] + +[[package]] +name = "zenoh-crypto" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "aes", + "hmac", + "rand", + "rand_chacha", + "sha3", + "zenoh-result", +] + +[[package]] +name = "zenoh-ext" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "bincode", + "flume", + "futures", + "phf", + "serde", + "serde_cbor", + "serde_json", + "tokio", + "tracing", + "zenoh", + "zenoh-macros", + "zenoh-util", +] + +[[package]] +name = "zenoh-keyexpr" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "hashbrown 0.14.3", + "keyed-set", + "rand", + "schemars", + "serde", + "token-cell", + "zenoh-result", +] + +[[package]] +name = "zenoh-link" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "async-trait", + "zenoh-config", + "zenoh-link-commons", + "zenoh-protocol", + "zenoh-result", +] + +[[package]] +name = "zenoh-link-commons" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "async-trait", + "flume", + "futures", + "rustls", + "rustls-webpki", + "serde", + "tokio", + "tokio-util", + "tracing", + "zenoh-buffers", + "zenoh-codec", + "zenoh-core", + "zenoh-protocol", + "zenoh-result", + "zenoh-runtime", + "zenoh-util", +] + +[[package]] +name = "zenoh-macros" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", + "zenoh-keyexpr", +] + +[[package]] +name = "zenoh-plugin-trait" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "const_format", + "libloading", + "serde", + "serde_json", + "tracing", + "zenoh-keyexpr", + "zenoh-macros", + "zenoh-result", + "zenoh-util", +] + +[[package]] +name = "zenoh-protocol" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "const_format", + "rand", + "serde", + "uhlc", + "zenoh-buffers", + "zenoh-collections", + "zenoh-keyexpr", + "zenoh-result", +] + +[[package]] +name = "zenoh-result" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "anyhow", +] + +[[package]] +name = "zenoh-runtime" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "futures", + "lazy_static", + "libc", + "ron", + "serde", + "tokio", + "zenoh-collections", + "zenoh-macros", + "zenoh-protocol", + "zenoh-result", +] + +[[package]] +name = "zenoh-shm" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "async-trait", + "bincode", + "crc", + "lazy_static", + "lockfree", + "num-traits", + "rand", + "serde", + "shared_memory", + "stabby", + "thread-priority", + "tokio", + "tracing", + "zenoh-buffers", + "zenoh-core", + "zenoh-macros", + "zenoh-result", +] + +[[package]] +name = "zenoh-sync" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "event-listener 4.0.3", + "futures", + "tokio", + "zenoh-buffers", + "zenoh-collections", + "zenoh-core", + "zenoh-runtime", +] + +[[package]] +name = "zenoh-task" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "futures", + "tokio", + "tokio-util", + "tracing", + "zenoh-core", + "zenoh-runtime", +] + +[[package]] +name = "zenoh-transport" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "async-trait", + "flume", + "lz4_flex", + "paste", + "rand", + "ringbuffer-spsc", + "serde", + "sha3", + "tokio", + "tokio-util", + "tracing", + "zenoh-buffers", + "zenoh-codec", + "zenoh-collections", + "zenoh-config", + "zenoh-core", + "zenoh-crypto", + "zenoh-link", + "zenoh-protocol", + "zenoh-result", + "zenoh-runtime", + "zenoh-shm", + "zenoh-sync", + "zenoh-task", + "zenoh-util", +] + +[[package]] +name = "zenoh-util" +version = "0.11.0-dev" +source = "git+https://github.com/eclipse-zenoh/zenoh.git?branch=explicit_api2#d10308568c7fb0444ea3412259bf344cafd0f8dc" +dependencies = [ + "async-std", + "async-trait", + "flume", + "home", + "humantime", + "lazy_static", + "libc", + "libloading", + "pnet_datalink", + "shellexpand", + "tokio", + "tracing", + "tracing-subscriber", + "winapi", + "zenoh-core", + "zenoh-result", +] + +[[package]] +name = "zerocopy" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "zeroize" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" diff --git a/build-resources/opaque-types/Cargo.toml b/build-resources/opaque-types/Cargo.toml new file mode 100644 index 000000000..4d976ea98 --- /dev/null +++ b/build-resources/opaque-types/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "opaque-types" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +# shared-memory enabled for zenoh even if zenoh-c "shared-memory" feature is disabled. This is to make "std::mem::transmute" work for `ZSLice` +zenoh = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "explicit_api2", features = ["shared-memory", "unstable"], default-features = false } +zenoh-ext = { version = "0.11.0-dev", git = "https://github.com/eclipse-zenoh/zenoh.git", branch = "explicit_api2", features = ["unstable"] } +const_format = "0.2.32" diff --git a/build-resources/opaque-types/src/lib.rs b/build-resources/opaque-types/src/lib.rs new file mode 100644 index 000000000..0d870a510 --- /dev/null +++ b/build-resources/opaque-types/src/lib.rs @@ -0,0 +1,275 @@ +use std::borrow::Cow; +use std::collections::HashMap; +use std::sync::Arc; +use std::sync::Condvar; +use std::sync::Mutex; +use std::sync::MutexGuard; +use std::thread::JoinHandle; +use zenoh::config::Config; +use zenoh::config::ZenohId; +use zenoh::encoding::Encoding; +use zenoh::handlers::DefaultHandler; +use zenoh::key_expr::KeyExpr; +use zenoh::bytes::{ZBytes, ZBytesReader}; +use zenoh::liveliness::LivelinessToken; +use zenoh::publication::MatchingListener; +use zenoh::publication::Publisher; +use zenoh::query::Reply; +use zenoh::queryable::Query; +use zenoh::queryable::Queryable; +use zenoh::sample::Sample; +use zenoh::session::Session; +use zenoh::subscriber::Subscriber; +use zenoh::time::Timestamp; +use zenoh::value::Value; + +#[macro_export] +macro_rules! get_opaque_type_data { + ($src_type:ty, $name:ident) => { + const _: () = { + use const_format::concatcp; + const DST_NAME: &str = stringify!($name); + const ALIGN: usize = std::mem::align_of::<$src_type>(); + const SIZE: usize = std::mem::size_of::<$src_type>(); + const INFO_MESSAGE: &str = concatcp!( + "type: ", DST_NAME, ", align: ", ALIGN, ", size: ", SIZE + ); + panic!("{}", INFO_MESSAGE); + }; + } +} + +/// A split buffer that owns all of its data. +/// +/// To minimize copies and reallocations, Zenoh may provide you data in split buffers. +get_opaque_type_data!(Option, z_owned_bytes_t); +/// A loaned payload. +get_opaque_type_data!(ZBytes, z_loaned_bytes_t); + +/// A contiguous view of bytes owned by some other entity. +/// +/// `start` being `null` is considered a gravestone value, +/// and empty slices are represented using a possibly dangling pointer for `start`. +get_opaque_type_data!(Option>, z_owned_slice_t); +get_opaque_type_data!(Option<&'static [u8]>, z_view_slice_t); +get_opaque_type_data!(&'static [u8], z_loaned_slice_t); + +/// The wrapper type for null-terminated string values allocated by zenoh. The instances of `z_owned_str_t` +/// should be released with `z_drop` macro or with `z_str_drop` function and checked to validity with +/// `z_check` and `z_str_check` correspondently +get_opaque_type_data!(Option>, z_owned_str_t); +get_opaque_type_data!(Option<&'static [u8]>, z_view_str_t); +get_opaque_type_data!(&'static [u8], z_loaned_str_t); + +/// A map of maybe-owned vector of bytes to maybe-owned vector of bytes. +/// +/// In Zenoh C, this map is backed by Rust's standard HashMap, with a DoS-resistant hasher +get_opaque_type_data!(Option, Cow<'static, [u8]>>>, z_owned_slice_map_t); +get_opaque_type_data!(HashMap, Cow<'static, [u8]>>, z_loaned_slice_map_t); + +/// An owned sample. +/// +/// This is a read only type that can only be constructed by cloning a `z_loaned_sample_t`. +/// Like all owned types, its memory must be freed by passing a mutable reference to it to `z_sample_drop`. +get_opaque_type_data!(Option, z_owned_sample_t); +get_opaque_type_data!(Sample, z_loaned_sample_t); + +/// A reader for payload data. +get_opaque_type_data!(Option>, z_owned_bytes_reader_t); +get_opaque_type_data!(ZBytesReader<'static>, z_loaned_bytes_reader_t); + +/// The encoding of a payload, in a MIME-like format. +/// +/// For wire and matching efficiency, common MIME types are represented using an integer as `prefix`, and a `suffix` may be used to either provide more detail, or in combination with the `Empty` prefix to write arbitrary MIME types. +get_opaque_type_data!(Encoding, z_loaned_encoding_t); +get_opaque_type_data!(Encoding, z_owned_encoding_t); + +/// An owned reply to a :c:func:`z_get`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. +get_opaque_type_data!(Option, z_owned_reply_t); +get_opaque_type_data!(Reply, z_loaned_reply_t); + +/// A zenoh value. +get_opaque_type_data!(Value, z_owned_value_t); +get_opaque_type_data!(Value, z_loaned_value_t); + +// Loaned variant of a Query received by a Queryable. +/// +/// Queries are atomically reference-counted, letting you extract them from the callback that handed them to you by cloning. +/// `z_loaned_query_t`'s are valid as long as at least one corresponding `z_owned_query_t` exists, including the one owned by Zenoh until the callback returns. +get_opaque_type_data!(Option, z_owned_query_t); +get_opaque_type_data!(Query, z_loaned_query_t); + +/// An owned zenoh queryable. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +get_opaque_type_data!(Option>, z_owned_queryable_t); +get_opaque_type_data!(Queryable<'static, ()>, z_loaned_queryable_t); + +/// An owned zenoh querying subscriber. Destroying the subscriber cancels the subscription. +/// +/// Like most `ze_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `ze_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +get_opaque_type_data!(Option<(zenoh_ext::FetchingSubscriber<'static, ()>, &'static Session)>, ze_owned_querying_subscriber_t); +get_opaque_type_data!((zenoh_ext::FetchingSubscriber<'static, ()>, &'static Session), ze_loaned_querying_subscriber_t); + +/// A zenoh-allocated key expression. +/// +/// Key expressions can identify a single key or a set of keys. +/// +/// Examples : +/// - ``"key/expression"``. +/// - ``"key/ex*"``. +/// +/// Key expressions can be mapped to numerical ids through :c:func:`z_declare_expr` +/// for wire and computation efficiency. +/// +/// A `key expression `_ can be either: +/// - A plain string expression. +/// - A pure numerical id. +/// - The combination of a numerical prefix and a string suffix. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +get_opaque_type_data!(Option>, z_owned_keyexpr_t); +get_opaque_type_data!(Option>, z_view_keyexpr_t); + +/// A loaned key expression. +/// +/// Key expressions can identify a single key or a set of keys. +/// +/// Examples : +/// - ``"key/expression"``. +/// - ``"key/ex*"``. +/// +/// Using :c:func:`z_declare_keyexpr` allows zenoh to optimize a key expression, +/// both for local processing and network-wise. +get_opaque_type_data!(KeyExpr<'_>, z_loaned_keyexpr_t); + +/// An owned zenoh session. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +get_opaque_type_data!(Option>, z_owned_session_t); +get_opaque_type_data!(Session, z_loaned_session_t); + +/// An owned zenoh configuration. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +get_opaque_type_data!(Option, z_owned_config_t); +/// A loaned zenoh configuration. +get_opaque_type_data!(Config, z_loaned_config_t); + +/// Represents a Zenoh ID. +/// +/// In general, valid Zenoh IDs are LSB-first 128bit unsigned and non-zero integers. +get_opaque_type_data!(ZenohId, z_id_t); + +get_opaque_type_data!(Timestamp, z_timestamp_t); + +/// An owned zenoh publisher. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +get_opaque_type_data!(Option>, z_owned_publisher_t); +get_opaque_type_data!(Publisher<'static>, z_loaned_publisher_t); + +/// An owned zenoh matching listener. Destroying the matching listener cancels the subscription. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +get_opaque_type_data!(Option>, zcu_owned_matching_listener_t); + + +/// An owned zenoh subscriber. Destroying the subscriber cancels the subscription. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +get_opaque_type_data!(Option>, z_owned_subscriber_t); +get_opaque_type_data!(Subscriber<'static, ()>, z_loaned_subscriber_t); + +/// A liveliness token that can be used to provide the network with information about connectivity to its +/// declarer: when constructed, a PUT sample will be received by liveliness subscribers on intersecting key +/// expressions. +/// +/// A DELETE on the token's key expression will be received by subscribers if the token is destroyed, or if connectivity between the subscriber and the token's creator is lost. +get_opaque_type_data!(Option>, zc_owned_liveliness_token_t); +get_opaque_type_data!(LivelinessToken<'static>, zc_loaned_liveliness_token_t); + + +/// An owned zenoh publication_cache. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +get_opaque_type_data!(Option>, ze_owned_publication_cache_t); +get_opaque_type_data!(zenoh_ext::PublicationCache<'static>, ze_loaned_publication_cache_t); + + +get_opaque_type_data!(Option<(Mutex<()>, Option>)>, z_owned_mutex_t); +get_opaque_type_data!((Mutex<()>, Option>), z_loaned_mutex_t); + +get_opaque_type_data!(Option, z_owned_condvar_t); +get_opaque_type_data!(Condvar, z_loaned_condvar_t); + +get_opaque_type_data!(Option>, z_owned_task_t); \ No newline at end of file diff --git a/build.rs b/build.rs index 66267e883..2a1c263bf 100644 --- a/build.rs +++ b/build.rs @@ -1,6 +1,8 @@ use fs2::FileExt; +use regex::Regex; use std::env; use std::io::{Read, Write}; +use std::process::{Command, Stdio}; use std::{ borrow::Cow, collections::HashMap, @@ -30,10 +32,12 @@ const HEADER: &str = r"// "; fn main() { + generate_opaque_types(); cbindgen::generate(std::env::var("CARGO_MANIFEST_DIR").unwrap()) .expect("Unable to generate bindings") .write_to_file(GENERATION_PATH); + create_generics_header(GENERATION_PATH, "include/zenoh_macros.h"); configure(); let split_guide = SplitGuide::from_yaml(SPLITGUIDE_PATH); split_bindings(&split_guide).unwrap(); @@ -50,9 +54,96 @@ fn main() { println!("cargo:rerun-if-changed=src"); println!("cargo:rerun-if-changed=splitguide.yaml"); println!("cargo:rerun-if-changed=cbindgen.toml"); + println!("cargo:rerun-if-changed=build-resources"); println!("cargo:rerun-if-changed=include"); } +fn get_build_rs_path() -> PathBuf { + let file_path = file!(); + let mut path_buf = PathBuf::new(); + path_buf.push(file_path); + path_buf.parent().unwrap().to_path_buf() +} + +fn produce_opaque_types_data() -> PathBuf { + let target = env::var("TARGET").unwrap(); + let current_folder = get_build_rs_path(); + let manifest_path = current_folder.join("./build-resources/opaque-types/Cargo.toml"); + let output_file_path = current_folder.join("./.build_resources_opaque_types.txt"); + let out_file = std::fs::File::create(output_file_path.clone()).unwrap(); + let stdio = Stdio::from(out_file); + let _ = Command::new("cargo") + .arg("build") + .arg("--target") + .arg(target) + .arg("--manifest-path") + .arg(manifest_path) + .stderr(stdio) + .output() + .unwrap(); + + output_file_path +} + +fn generate_opaque_types() { + let type_to_inner_field_name = HashMap::from([("z_id_t", "id")]); + let current_folder = get_build_rs_path(); + let path_in = produce_opaque_types_data(); + let path_out = current_folder.join("./src/opaque_types/mod.rs"); + + let data_in = std::fs::read_to_string(path_in).unwrap(); + let mut data_out = String::new(); + data_out += "#[rustfmt::skip] +#[allow(clippy::all)] +"; + let mut docs = get_opaque_type_docs(); + + let re = Regex::new(r"type: (\w+), align: (\d+), size: (\d+)").unwrap(); + for (_, [type_name, align, size]) in re.captures_iter(&data_in).map(|c| c.extract()) { + let inner_field_name = type_to_inner_field_name.get(type_name).unwrap_or(&"_0"); + let s = format!( + "#[derive(Copy, Clone)] +#[repr(C, align({align}))] +pub struct {type_name} {{ + {inner_field_name}: [u8; {size}], +}} +" + ); + let doc = docs + .remove(type_name) + .unwrap_or_else(|| panic!("Failed to extract docs for opaque type: {type_name}")); + for d in doc { + data_out += &d; + data_out += "\r\n"; + } + data_out += &s; + } + for d in docs.keys() { + panic!("Failed to find type information for opaque type: {d}"); + } + std::fs::write(path_out, data_out).unwrap(); +} + +fn get_opaque_type_docs() -> HashMap> { + let current_folder = get_build_rs_path(); + let path_in = current_folder.join("./build-resources/opaque-types/src/lib.rs"); + let re = Regex::new(r"(?m)^\s*get_opaque_type_data!\(\s*(.*)\s*,\s*(\w+)\)").unwrap(); + let mut comments = std::vec::Vec::::new(); + let mut res = HashMap::>::new(); + + for line in std::fs::read_to_string(path_in).unwrap().lines() { + if line.starts_with("///") { + comments.push(line.to_string()); + continue; + } + if let Some(c) = re.captures(line) { + res.insert(c[2].to_string(), comments.clone()); + } + comments.clear(); + } + res +} + // See: https://github.com/rust-lang/cargo/issues/9661 // See: https://github.com/rust-lang/cargo/issues/545 fn cargo_target_dir() -> PathBuf { @@ -642,3 +733,465 @@ impl<'a> Iterator for Tokenizer<'a> { } } } + +#[derive(Clone, Debug)] +pub struct FuncArg { + typename: String, + cv: String, + name: String, +} + +impl FuncArg { + pub fn new(typename: &str, cv: &str, name: &str) -> Self { + FuncArg { + typename: typename.to_owned(), + cv: cv.to_owned(), + name: name.to_owned(), + } + } +} +#[derive(Clone, Debug)] +pub struct FunctionSignature { + return_type: String, + func_name: String, + arg_type_and_name: Vec, +} + +pub fn create_generics_header(path_in: &str, path_out: &str) { + let mut file_out = std::fs::File::options() + .read(false) + .create(false) + .write(true) + .truncate(true) + .open(path_out) + .unwrap(); + + let header = "#pragma once +// clang-format off +#ifndef __cplusplus + +"; + file_out.write_all(header.as_bytes()).unwrap(); + + let type_name_to_loan_func = find_loan_functions(path_in); + let out = generate_generic_loan_c(&type_name_to_loan_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let type_name_to_loan_mut_func = find_loan_mut_functions(path_in); + let out = generate_generic_loan_mut_c(&type_name_to_loan_mut_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let type_name_to_drop_func = find_drop_functions(path_in); + let out = generate_generic_drop_c(&type_name_to_drop_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let type_name_to_null_func = find_null_functions(path_in); + let out = generate_generic_null_c(&type_name_to_null_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let type_name_to_check_func = find_check_functions(path_in); + let out = generate_generic_check_c(&type_name_to_check_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let type_name_to_call_func = find_call_functions(path_in); + let out = generate_generic_call_c(&type_name_to_call_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let out = generate_generic_closure_c(&type_name_to_call_func); + file_out.write_all(out.as_bytes()).unwrap(); + + file_out + .write_all("\n#else // #ifndef __cplusplus\n".as_bytes()) + .unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let out = generate_generic_loan_cpp(&type_name_to_loan_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let out = generate_generic_loan_mut_cpp(&type_name_to_loan_mut_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let out = generate_generic_drop_cpp(&type_name_to_drop_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let out = generate_generic_null_cpp(&type_name_to_null_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let out = generate_generic_check_cpp(&type_name_to_check_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let out = generate_generic_call_cpp(&type_name_to_call_func); + file_out.write_all(out.as_bytes()).unwrap(); + file_out.write_all("\n\n".as_bytes()).unwrap(); + + let out = generate_generic_closure_cpp(&type_name_to_call_func); + file_out.write_all(out.as_bytes()).unwrap(); + + file_out + .write_all("\n#endif // #ifndef __cplusplus".as_bytes()) + .unwrap(); +} + +pub fn find_loan_functions(path_in: &str) -> Vec { + let bindings = std::fs::read_to_string(path_in).unwrap(); + let re = Regex::new(r"const struct (\w+) \*(\w+)_loan\(const struct (\w+) \*(\w+)\);").unwrap(); + let mut res = Vec::::new(); + + for (_, [return_type, func_name, arg_type, arg_name]) in + re.captures_iter(&bindings).map(|c| c.extract()) + { + let f = FunctionSignature { + return_type: return_type.to_string(), + func_name: func_name.to_string() + "_loan", + arg_type_and_name: [FuncArg::new(arg_type, "const", arg_name)].to_vec(), + }; + res.push(f); + } + res +} + +pub fn find_loan_mut_functions(path_in: &str) -> Vec { + let bindings = std::fs::read_to_string(path_in).unwrap(); + let re = Regex::new(r"struct (\w+) \*(\w+)_loan_mut\(struct (\w+) \*(\w+)\);").unwrap(); + let mut res = Vec::::new(); + + for (_, [return_type, func_name, arg_type, arg_name]) in + re.captures_iter(&bindings).map(|c| c.extract()) + { + let f = FunctionSignature { + return_type: return_type.to_string(), + func_name: func_name.to_string() + "_loan_mut", + arg_type_and_name: [FuncArg::new(arg_type, "", arg_name)].to_vec(), + }; + res.push(f); + } + res +} + +pub fn find_drop_functions(path_in: &str) -> Vec { + let bindings = std::fs::read_to_string(path_in).unwrap(); + let re = Regex::new(r"(\w+)_drop\(struct (\w+) \*(\w+)\);").unwrap(); + let mut res = Vec::::new(); + + for (_, [func_name, arg_type, arg_name]) in re.captures_iter(&bindings).map(|c| c.extract()) { + let f = FunctionSignature { + return_type: "void".to_string(), + func_name: func_name.to_string() + "_drop", + arg_type_and_name: [FuncArg::new(arg_type, "const", arg_name)].to_vec(), + }; + res.push(f); + } + res +} + +pub fn find_null_functions(path_in: &str) -> Vec { + let bindings = std::fs::read_to_string(path_in).unwrap(); + let re = Regex::new(r"(\w+)_null\(struct (\w+) \*(\w+)\);").unwrap(); + let mut res = Vec::::new(); + + for (_, [func_name, arg_type, arg_name]) in re.captures_iter(&bindings).map(|c| c.extract()) { + let f = FunctionSignature { + return_type: "void".to_string(), + func_name: func_name.to_string() + "_null", + arg_type_and_name: [FuncArg::new(arg_type, "", arg_name)].to_vec(), + }; + res.push(f); + } + res +} + +pub fn find_check_functions(path_in: &str) -> Vec { + let bindings = std::fs::read_to_string(path_in).unwrap(); + let re = Regex::new(r"bool (\w+)_check\(const struct (\w+) \*(\w+)\);").unwrap(); + let mut res = Vec::::new(); + + for (_, [func_name, arg_type, arg_name]) in re.captures_iter(&bindings).map(|c| c.extract()) { + let f = FunctionSignature { + return_type: "bool".to_string(), + func_name: func_name.to_string() + "_check", + arg_type_and_name: [FuncArg::new(arg_type, "const", arg_name)].to_vec(), + }; + res.push(f); + } + res +} + +pub fn find_call_functions(path_in: &str) -> Vec { + let bindings = std::fs::read_to_string(path_in).unwrap(); + let re = Regex::new( + r"(\w+) (\w+)_call\(const struct (\w+) \*(\w+),\s+(\w*)\s*struct (\w+) \*(\w+)\);", + ) + .unwrap(); + let mut res = Vec::::new(); + + for (_, [return_type, func_name, closure_type, closure_name, arg_cv, arg_type, arg_name]) in + re.captures_iter(&bindings).map(|c| c.extract()) + { + let f = FunctionSignature { + return_type: return_type.to_string(), + func_name: func_name.to_string() + "_call", + arg_type_and_name: [ + FuncArg::new(closure_type, "const", closure_name), + FuncArg::new(arg_type, arg_cv, arg_name), + ] + .to_vec(), + }; + res.push(f); + } + res +} + +pub fn generate_generic_loan_c(macro_func: &Vec) -> String { + let mut out = "#define z_loan(x) \\ + _Generic((x)" + .to_owned(); + + for func in macro_func { + let owned_type = &func.arg_type_and_name[0].typename; + let func_name = &func.func_name; + out += ", \\\n"; + out += &format!(" {owned_type} : {func_name}"); + } + out += " \\\n"; + out += " )(&x)"; + out +} + +pub fn generate_generic_loan_mut_c( + macro_func: &Vec +) -> String { + let mut out = "#define z_loan_mut(x) \\ + _Generic((x)" + .to_owned(); + + for func in macro_func { + let owned_type = &func.arg_type_and_name[0].typename; + let func_name = &func.func_name; + out += ", \\\n"; + out += &format!(" {owned_type} : {func_name}"); + } + out += " \\\n"; + out += " )(&x)"; + out +} + +pub fn generate_generic_drop_c(macro_func: &Vec) -> String { + let mut out = "#define z_drop(x) \\ + _Generic((x)" + .to_owned(); + + for func in macro_func { + let owned_type = &func.arg_type_and_name[0].typename; + let func_name = &func.func_name; + out += ",\\\n"; + out += &format!(" {owned_type} * : {func_name}"); + } + out += " \\\n"; + out += " )(x)"; + out +} + +pub fn generate_generic_null_c(macro_func: &Vec) -> String { + let mut out = "#define z_null(x) \\ + _Generic((x)" + .to_owned(); + + for func in macro_func { + let owned_type = &func.arg_type_and_name[0].typename; + let func_name = &func.func_name; + out += ", \\\n"; + out += &format!(" {owned_type} * : {func_name}"); + } + out += " \\\n"; + out += " )(x)"; + out +} + +pub fn generate_generic_check_c(macro_func: &Vec) -> String { + let mut out = "#define z_check(x) \\ + _Generic((x)" + .to_owned(); + + for func in macro_func { + let owned_type = &func.arg_type_and_name[0].typename; + let func_name = &func.func_name; + out += ", \\\n"; + out += &format!(" {owned_type} : {func_name}"); + } + out += " \\\n"; + out += " )(&x)"; + out +} + +pub fn generate_generic_call_c(macro_func: &Vec) -> String { + let mut out = "#define z_call(x, ...) \\ + _Generic((x)" + .to_owned(); + + for func in macro_func { + let func_name = &func.func_name; + let owned_type = &func.arg_type_and_name[0].typename; + out += ", \\\n"; + out += &format!(" {owned_type} : {func_name}"); + } + out += " \\\n"; + out += " )(&x, __VA_ARGS__)"; + + out +} + +pub fn generate_generic_closure_c( + macro_func: &Vec +) -> String { + let mut out = "#define z_closure(x, callback, dropper, ctx) \\ + _Generic((x)" + .to_owned(); + + for func in macro_func { + let owned_type = &func.arg_type_and_name[0].typename; + out += ", \\\n"; + out += &format!( +" {owned_type} * : {{ x->context = (void*)ctx; x->call = callback; x->drop = droper; }}"); + } + out += " \\\n"; + out += " )"; + + out +} + +pub fn generate_generic_loan_cpp(macro_func: &Vec) -> String { + let mut out = "".to_owned(); + + for func in macro_func { + let func_name = &func.func_name; + let return_type = &func.return_type; + let cv = &func.arg_type_and_name[0].cv; + let arg_name = &func.arg_type_and_name[0].name; + let arg_type = &func.arg_type_and_name[0].typename; + out += "\n"; + out += &format!("inline const {return_type}* z_loan({cv} {arg_type}* {arg_name}) {{ return {func_name}({arg_name}); }};"); + } + out +} + +pub fn generate_generic_loan_mut_cpp( + macro_func: &Vec +) -> String { + let mut out = "".to_owned(); + + for func in macro_func { + let func_name = &func.func_name; + let return_type = &func.return_type; + let cv = &func.arg_type_and_name[0].cv; + let arg_name = &func.arg_type_and_name[0].name; + let arg_type = &func.arg_type_and_name[0].typename; + out += "\n"; + out += &format!("inline {return_type}* z_loan_mut({cv} {arg_type}& {arg_name}) {{ return {func_name}(&{arg_name}); }};"); + } + out +} + +pub fn generate_generic_drop_cpp(macro_func: &Vec) -> String { + let mut out = "".to_owned(); + + for func in macro_func { + let func_name = &func.func_name; + let return_type = &func.return_type; + let cv = &func.arg_type_and_name[0].cv; + let arg_name = &func.arg_type_and_name[0].name; + let arg_type = &func.arg_type_and_name[0].typename; + out += "\n"; + out += &format!("inline {return_type} z_drop({cv} {arg_type}* {arg_name}) {{ return {func_name}({arg_name}); }};"); + } + out +} + +pub fn generate_generic_null_cpp(macro_func: &Vec) -> String { + let mut out = "".to_owned(); + + for func in macro_func { + let func_name = &func.func_name; + let return_type = &func.return_type; + let cv = &func.arg_type_and_name[0].cv; + let arg_name = &func.arg_type_and_name[0].name; + let arg_type = &func.arg_type_and_name[0].typename; + out += "\n"; + out += &format!("inline {return_type} z_null({cv} {arg_type}* {arg_name}) {{ return {func_name}({arg_name}); }};"); + } + out +} + +pub fn generate_generic_check_cpp( + macro_func: &Vec +) -> String { + let mut out = "".to_owned(); + + for func in macro_func { + let func_name = &func.func_name; + let return_type = &func.return_type; + let cv = &func.arg_type_and_name[0].cv; + let arg_name = &func.arg_type_and_name[0].name; + let arg_type = &func.arg_type_and_name[0].typename; + out += "\n"; + out += &format!("inline {return_type} z_check({cv} {arg_type}& {arg_name}) {{ return {func_name}(&{arg_name}); }};"); + } + out +} + +pub fn generate_generic_call_cpp(macro_func: &Vec) -> String { + let mut out = "".to_owned(); + + for func in macro_func { + let func_name = &func.func_name; + let return_type = &func.return_type; + let closure_cv = &func.arg_type_and_name[0].cv; + let closure_name = &func.arg_type_and_name[0].name; + let closure_type = &func.arg_type_and_name[0].typename; + let arg_cv = &func.arg_type_and_name[1].cv; + let arg_name = &func.arg_type_and_name[1].name; + let arg_type = &func.arg_type_and_name[1].typename; + out += "\n"; + out += &format!("inline {return_type} z_call({closure_cv} {closure_type}& {closure_name}, {arg_cv} {arg_type}* {arg_name}) {{ + return {func_name}(&{closure_name}, {arg_name}); +}};"); + } + out +} + +pub fn generate_generic_closure_cpp( + macro_func: &Vec +) -> String { + let mut out = "".to_owned(); + + for func in macro_func { + let return_type = &func.return_type; + let closure_name = &func.arg_type_and_name[0].name; + let closure_type = &func.arg_type_and_name[0].typename; + let arg_cv = &func.arg_type_and_name[1].cv; + let arg_type = &func.arg_type_and_name[1].typename; + out += "\n"; + out += &format!( + "inline void z_closure( + {closure_type}* {closure_name}, + {return_type} (*call)({arg_cv} {arg_type}*, void*), + void (*drop)(void*), + void *context) {{ + {closure_name}->context = context; + {closure_name}->drop = drop; + {closure_name}->call = call; +}};" + ); + } + out +} diff --git a/docs/api.rst b/docs/api.rst index 758c405b5..a5b0e1eea 100644 --- a/docs/api.rst +++ b/docs/api.rst @@ -22,29 +22,29 @@ Generic types Bytes ----- -.. autocstruct:: zenoh_commons.h::z_bytes_t +.. autocstruct:: zenoh_commons.h::z_loaned_slice_t -.. autocfunction:: zenoh_commons.h::z_bytes_new -.. autocfunction:: zenoh_commons.h::z_bytes_check -.. autocfunction:: zenoh_commons.h::z_bytes_null +.. autocfunction:: zenoh_commons.h::z_slice_new +.. autocfunction:: zenoh_commons.h::z_slice_check +.. autocfunction:: zenoh_commons.h::z_slice_null Bytes map --------- .. autocstruct:: zenoh_commons.h::z_owned_bytes_map_t -.. autocfunction:: zenoh_commons.h::z_bytes_map_new -.. autocfunction:: zenoh_commons.h::z_bytes_map_check -.. autocfunction:: zenoh_commons.h::z_bytes_map_null -.. autocfunction:: zenoh_commons.h::z_bytes_map_drop -.. autocfunction:: zenoh_commons.h::z_bytes_map_get -.. autocfunction:: zenoh_commons.h::z_bytes_map_len -.. autocfunction:: zenoh_commons.h::z_bytes_map_is_empty -.. autocfunction:: zenoh_commons.h::z_bytes_map_insert_by_alias -.. autocfunction:: zenoh_commons.h::z_bytes_map_insert_by_copy -.. autocfunction:: zenoh_commons.h::z_bytes_map_iter -.. autocfunction:: zenoh_commons.h::z_bytes_map_from_attachment -.. autocfunction:: zenoh_commons.h::z_bytes_map_from_attachment_aliasing +.. autocfunction:: zenoh_commons.h::z_slice_map_new +.. autocfunction:: zenoh_commons.h::z_slice_map_check +.. autocfunction:: zenoh_commons.h::z_slice_map_null +.. autocfunction:: zenoh_commons.h::z_slice_map_drop +.. autocfunction:: zenoh_commons.h::z_slice_map_get +.. autocfunction:: zenoh_commons.h::z_slice_map_len +.. autocfunction:: zenoh_commons.h::z_slice_map_is_empty +.. autocfunction:: zenoh_commons.h::z_slice_map_insert_by_alias +.. autocfunction:: zenoh_commons.h::z_slice_map_insert_by_copy +.. autocfunction:: zenoh_commons.h::z_slice_map_iter +.. autocfunction:: zenoh_commons.h::z_slice_map_from_attachment +.. autocfunction:: zenoh_commons.h::z_slice_map_from_attachment_aliasing .. Scouting .. ======== @@ -56,7 +56,7 @@ Session configuration --------------------- -.. autocstruct:: zenoh_commons.h::z_config_t +.. autocstruct:: zenoh_commons.h::z_loaned_config_t .. autocstruct:: zenoh_commons.h::z_owned_config_t .. autocstruct:: zenoh_commons.h::z_owned_scouting_config_t @@ -79,7 +79,7 @@ Session management Types ^^^^^ -.. autocstruct:: zenoh_concrete.h::z_session_t +.. autocstruct:: zenoh_concrete.h::z_loaned_session_t .. autocstruct:: zenoh_concrete.h::z_owned_session_t .. autocstruct:: zenoh_commons.h::z_owned_closure_zid_t @@ -104,13 +104,13 @@ Functions Key expression ============== -.. autocstruct:: zenoh_commons.h::z_keyexpr_t +.. autocstruct:: zenoh_commons.h::z_loaned_keyexpr_t .. autocstruct:: zenoh_commons.h::z_owned_keyexpr_t .. autocfunction:: zenoh_commons.h::z_keyexpr .. autocfunction:: zenoh_commons.h::z_keyexpr_autocanonize .. autocfunction:: zenoh_commons.h::z_keyexpr_unchecked -.. autocfunction:: zenoh_commons.h::z_keyexpr_to_string +.. autocfunction:: zenoh_commons.h::z_loaned_keyexpr_to_string .. autocfunction:: zenoh_commons.h::z_keyexpr_as_bytes .. autocfunction:: zenoh_commons.h::z_keyexpr_canonize .. autocfunction:: zenoh_commons.h::z_keyexpr_canonize_null_terminated @@ -133,7 +133,7 @@ Key expression Encoding ======== -.. autocstruct:: zenoh_commons.h::z_encoding_t +.. autocstruct:: zenoh_commons.h::z_loaned_encoding_t .. autocstruct:: zenoh_commons.h::z_owned_encoding_t .. autocfunction:: zenoh_commons.h::z_encoding_default @@ -147,12 +147,12 @@ Encoding Value ===== -.. autocstruct:: zenoh_commons.h::z_value_t +.. autocstruct:: zenoh_commons.h::z_loaned_value_t Sample ====== -.. autocstruct:: zenoh_commons.h::z_sample_t +.. autocstruct:: zenoh_commons.h::z_loaned_sample_t Attachment ========== @@ -237,7 +237,7 @@ Types .. autocstruct:: zenoh_commons.h::z_get_options_t -.. autocenum:: zenoh_commons.h::z_query_target_t +.. autocenum:: zenoh_commons.h::z_loaned_query_target_t .. autocenum:: zenoh_commons.h::z_consolidation_mode_t diff --git a/docs/examples.rst b/docs/examples.rst index bea19cbbe..1aab457a6 100644 --- a/docs/examples.rst +++ b/docs/examples.rst @@ -43,8 +43,8 @@ Subscribe #include #include "zenoh.h" - void data_handler(const z_sample_t *sample, const void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); + void data_handler(const z_loaned_sample_t *sample, const void *arg) { + z_owned_str_t keystr = z_loaned_keyexpr_to_string(sample->keyexpr); printf(">> Received (%s, %.*s)\n", keystr, (int)sample->payload.len, sample->payload.start); z_drop(z_move(keystr)); @@ -86,8 +86,8 @@ Query { if (z_reply_is_ok(&reply)) { - z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); + z_loaned_sample_t sample = z_reply_ok(&reply); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(sample.keyexpr); printf(">> Received ('%s': '%.*s')\n", keystr, (int)sample.payload.len, sample.payload.start); z_drop(z_move(keystr)); } diff --git a/examples/z_delete.c b/examples/z_delete.c index 5000444bc..6f364dc80 100644 --- a/examples/z_delete.c +++ b/examples/z_delete.c @@ -21,7 +21,8 @@ int main(int argc, char **argv) { if (argc > 1) keyexpr = argv[1]; - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (argc > 3) { if (zc_config_insert_json(z_loan(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) { printf( @@ -33,19 +34,22 @@ int main(int argc, char **argv) { } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("Deleting resources matching '%s'...\n", keyexpr); z_delete_options_t options = z_delete_options_default(); - int res = z_delete(z_loan(s), z_keyexpr(keyexpr), &options); + z_owned_keyexpr_t ke; + z_keyexpr(&ke, keyexpr); + int res = z_delete(z_loan(s), z_loan(ke), &options); if (res < 0) { printf("Delete failed...\n"); } + z_keyexpr_drop(z_move(ke)); z_close(z_move(s)); return 0; } diff --git a/examples/z_get.c b/examples/z_get.c index 272bef89a..00eb2a524 100644 --- a/examples/z_get.c +++ b/examples/z_get.c @@ -30,12 +30,13 @@ int main(int argc, char **argv) { // Do nothing break; } - z_keyexpr_t keyexpr = z_keyexpr(expr); - if (!z_check(keyexpr)) { + z_owned_keyexpr_t keyexpr; + if (z_keyexpr(&keyexpr, expr) < 0) { printf("%s is not a valid key expression", expr); exit(-1); } - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (argc > 3) { if (zc_config_insert_json(z_loan(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) { printf( @@ -47,8 +48,8 @@ int main(int argc, char **argv) { } printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + if (!z_open(&s, z_move(config))) { printf("Unable to open session!\n"); exit(-1); } @@ -56,22 +57,28 @@ int main(int argc, char **argv) { printf("Sending Query '%s'...\n", expr); z_owned_reply_channel_t channel = zc_reply_fifo_new(16); z_get_options_t opts = z_get_options_default(); + z_owned_bytes_t payload; if (value != NULL) { - opts.value.payload = z_bytes_from_str(value); + z_bytes_encode_from_string(&payload, value); + opts.payload = &payload; } - z_get(z_loan(s), keyexpr, "", z_move(channel.send), - &opts); // here, the send is moved and will be dropped by zenoh when adequate - z_owned_reply_t reply = z_reply_null(); + z_get(z_loan(s), z_loan(keyexpr), "", z_move(channel.send), + z_move(opts)); // here, the send is moved and will be dropped by zenoh when adequate + z_owned_reply_t reply; + z_owned_str_t reply_str; for (z_call(channel.recv, &reply); z_check(reply); z_call(channel.recv, &reply)) { - if (z_reply_is_ok(&reply)) { - z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(">> Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample.payload.len, sample.payload.start); - z_drop(z_move(keystr)); + if (z_reply_is_ok(z_loan(reply))) { + z_loaned_sample_t sample = z_reply_ok(z_loan(reply)); + z_owned_str_t key_str = z_loaned_keyexpr_to_string(z_sample_keyexpr(&sample)); + z_bytes_decode_into_string(z_sample_payload(&sample), &reply_str); + printf(">> Received ('%s': '%s')\n", z_loan(key_str), z_loan(reply_str)); + z_drop(z_move(reply_str)); + z_drop(z_move(key_str)); } else { printf("Received an error\n"); } } + z_drop(z_move(keyexpr)); z_drop(z_move(reply)); z_drop(z_move(channel)); z_close(z_move(s)); diff --git a/examples/z_get_liveliness.c b/examples/z_get_liveliness.c index c667cb03a..025b09db3 100644 --- a/examples/z_get_liveliness.c +++ b/examples/z_get_liveliness.c @@ -22,13 +22,14 @@ int main(int argc, char **argv) { expr = argv[1]; } - z_keyexpr_t keyexpr = z_keyexpr(expr); - if (!z_check(keyexpr)) { + z_owned_keyexpr_t keyexpr; + if (z_keyexpr(&keyexpr, expr) < 0) { printf("%s is not a valid key expression\n", expr); exit(-1); } - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (argc > 2) { if (zc_config_insert_json(z_loan(config), Z_CONFIG_CONNECT_KEY, argv[2]) < 0) { printf( @@ -39,27 +40,29 @@ int main(int argc, char **argv) { } } + z_owned_session_t s; printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } printf("Sending liveliness query '%s'...\n", expr); z_owned_reply_channel_t channel = zc_reply_fifo_new(16); - zc_liveliness_get(z_loan(s), keyexpr, z_move(channel.send), NULL); - z_owned_reply_t reply = z_reply_null(); + zc_liveliness_get(z_loan(s), z_loan(keyexpr), z_move(channel.send), NULL); + z_owned_reply_t reply; for (z_call(channel.recv, &reply); z_check(reply); z_call(channel.recv, &reply)) { - if (z_reply_is_ok(&reply)) { - z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(">> Alive token ('%s')\n", z_loan(keystr)); - z_drop(z_move(keystr)); + if (z_reply_is_ok(z_loan(reply))) { + z_loaned_sample_t sample = z_reply_ok(z_loan(reply)); + z_owned_str_t key_str = z_loaned_keyexpr_to_string(z_sample_keyexpr(&sample)); + printf(">> Alive token ('%s')\n", z_loan(key_str)); + z_drop(z_move(key_str)); } else { printf("Received an error\n"); } } + + z_drop(z_move(keyexpr)); z_drop(z_move(reply)); z_drop(z_move(channel)); z_close(z_move(s)); diff --git a/examples/z_liveliness.c b/examples/z_liveliness.c index 4191b0496..bc71da8eb 100644 --- a/examples/z_liveliness.c +++ b/examples/z_liveliness.c @@ -21,7 +21,7 @@ int main(int argc, char **argv) { expr = argv[1]; } - z_keyexpr_t keyexpr = z_keyexpr(expr); + z_loaned_keyexpr_t keyexpr = z_keyexpr(expr); if (!z_check(keyexpr)) { printf("%s is not a valid key expression\n", expr); exit(-1); diff --git a/examples/z_non_blocking_get.c b/examples/z_non_blocking_get.c index c0b02a274..c84074e67 100644 --- a/examples/z_non_blocking_get.c +++ b/examples/z_non_blocking_get.c @@ -21,7 +21,7 @@ int main(int argc, char **argv) { if (argc > 1) { expr = argv[1]; } - z_keyexpr_t keyexpr = z_keyexpr(expr); + z_loaned_keyexpr_t keyexpr = z_keyexpr(expr); if (!z_check(keyexpr)) { printf("%s is not a valid key expression", expr); exit(-1); @@ -49,17 +49,20 @@ int main(int argc, char **argv) { opts.target = Z_QUERY_TARGET_ALL; z_owned_reply_channel_t channel = zc_reply_non_blocking_fifo_new(16); z_get(z_loan(s), keyexpr, "", z_move(channel.send), - &opts); // here, the send is moved and will be dropped by zenoh when adequate + z_move(opts)); // here, the send is moved and will be dropped by zenoh when adequate z_owned_reply_t reply = z_reply_null(); + z_owned_str_t payload_value = z_str_null(); for (bool call_success = z_call(channel.recv, &reply); !call_success || z_check(reply); call_success = z_call(channel.recv, &reply)) { if (!call_success) { continue; } if (z_reply_is_ok(&reply)) { - z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - printf(">> Received ('%s': '%.*s')\n", z_loan(keystr), (int)sample.payload.len, sample.payload.start); + z_loaned_sample_t sample = z_reply_ok(&reply); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(&sample)); + z_bytes_decode_into_string(z_sample_payload(&sample), &payload_value); + printf(">> Received ('%s': '%s')\n", z_loan(keystr), z_loan(payload_value)); + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } else { printf("Received an error\n"); diff --git a/examples/z_ping.c b/examples/z_ping.c index fdc08f71d..87dc697ab 100644 --- a/examples/z_ping.c +++ b/examples/z_ping.c @@ -13,10 +13,10 @@ #define handle_error_en(en, msg) \ do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0) -z_condvar_t cond; -z_mutex_t mutex; +z_loaned_condvar_t cond; +z_loaned_mutex_t mutex; -void callback(const z_sample_t* sample, void* context) { z_condvar_signal(&cond); } +void callback(const z_loaned_sample_t* sample, void* context) { z_condvar_signal(&cond); } void drop(void* context) { z_condvar_free(&cond); } struct args_t { @@ -45,8 +45,8 @@ int main(int argc, char** argv) { z_condvar_init(&cond); z_owned_config_t config = args.config_path ? zc_config_from_file(args.config_path) : z_config_default(); z_owned_session_t session = z_open(z_move(config)); - z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); - z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); + z_loaned_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); + z_loaned_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); z_owned_publisher_t pub = z_declare_publisher(z_loan(session), ping, NULL); z_owned_closure_sample_t respond = z_closure(callback, drop, (void*)(&pub)); z_owned_subscriber_t sub = z_declare_subscriber(z_loan(session), pong, z_move(respond), NULL); @@ -54,6 +54,7 @@ int main(int argc, char** argv) { for (int i = 0; i < args.size; i++) { data[i] = i % 10; } + z_owned_bytes_t payload = z_bytes_encode_from_bytes((z_loaned_slice_t){.start = data, .len = args.size}); z_mutex_lock(&mutex); if (args.warmup_ms) { printf("Warming up for %dms...\n", args.warmup_ms); @@ -61,7 +62,7 @@ int main(int argc, char** argv) { unsigned long elapsed_us = 0; while (elapsed_us < args.warmup_ms * 1000) { - z_publisher_put(z_loan(pub), data, args.size, NULL); + z_publisher_put(z_loan(pub), z_move(payload), NULL); int s = z_condvar_wait(&cond, &mutex); if (s != 0) { handle_error_en(s, "z_condvar_wait"); @@ -72,7 +73,7 @@ int main(int argc, char** argv) { unsigned long* results = z_malloc(sizeof(unsigned long) * args.number_of_pings); for (int i = 0; i < args.number_of_pings; i++) { z_clock_t measure_start = z_clock_now(); - z_publisher_put(z_loan(pub), data, args.size, NULL); + z_publisher_put(z_loan(pub), z_move(payload), NULL); int s = z_condvar_wait(&cond, &mutex); if (s != 0) { handle_error_en(s, "z_condvar_wait"); diff --git a/examples/z_pong.c b/examples/z_pong.c index 8dbb2631e..b8920f70d 100644 --- a/examples/z_pong.c +++ b/examples/z_pong.c @@ -3,13 +3,11 @@ #include "zenoh.h" -void callback(const z_sample_t* sample, void* context) { - z_publisher_t pub = z_loan(*(z_owned_publisher_t*)context); -#ifdef ZENOH_C // The zc_owned_payload_t API is exclusive to zenoh-c, but allows avoiding some copies. - zc_owned_payload_t payload = zc_sample_payload_rcinc(sample); - zc_publisher_put_owned(pub, z_move(payload), NULL); -#else - z_publisher_put(pub, sample->payload.start, sample->payload.len, NULL); +void callback(const z_loaned_sample_t* sample, void* context) { + z_loaned_publisher_t pub = z_loan(*(z_owned_publisher_t*)context); +#ifdef ZENOH_C // The z_owned_bytes_t API is exclusive to zenoh-c, but allows avoiding some copies. + z_owned_bytes_t payload = z_sample_owned_payload(sample); + z_publisher_put(pub, z_move(payload), NULL); #endif } void drop(void* context) { @@ -21,21 +19,23 @@ void drop(void* context) { // valid. } struct args_t { - char* config_path; // -c - uint8_t help_requested; // -h + char* config_path; // -c + uint8_t help_requested; // -h }; struct args_t parse_args(int argc, char** argv); int main(int argc, char** argv) { struct args_t args = parse_args(argc, argv); if (args.help_requested) { - printf("-c (optional, string): the path to a configuration file for the session. If this option isn't passed, the default configuration will be used.\n"); + printf( + "-c (optional, string): the path to a configuration file for the session. If this option isn't passed, the " + "default configuration will be used.\n"); return 1; } z_owned_config_t config = args.config_path ? zc_config_from_file(args.config_path) : z_config_default(); z_owned_session_t session = z_open(z_move(config)); - z_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); - z_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); + z_loaned_keyexpr_t ping = z_keyexpr_unchecked("test/ping"); + z_loaned_keyexpr_t pong = z_keyexpr_unchecked("test/pong"); z_owned_publisher_t pub = z_declare_publisher(z_loan(session), pong, NULL); z_owned_closure_sample_t respond = z_closure(callback, drop, (void*)z_move(pub)); z_owned_subscriber_t sub = z_declare_subscriber(z_loan(session), ping, z_move(respond), NULL); diff --git a/examples/z_pub.c b/examples/z_pub.c index ecc95e42d..29ccd5c8e 100644 --- a/examples/z_pub.c +++ b/examples/z_pub.c @@ -71,7 +71,8 @@ int main(int argc, char **argv) { printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); z_publisher_put_options_t options = z_publisher_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), &options); + z_owned_bytes_t payload = z_bytes_encode_from_string(buf); + z_publisher_put(z_loan(pub), z_move(payload), &options); } z_undeclare_publisher(z_move(pub)); diff --git a/examples/z_pub_attachment.c b/examples/z_pub_attachment.c index a24133e91..c45b25811 100644 --- a/examples/z_pub_attachment.c +++ b/examples/z_pub_attachment.c @@ -52,13 +52,13 @@ int main(int argc, char **argv) { options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); // allocate attachment map - z_owned_bytes_map_t map = z_bytes_map_new(); + z_owned_bytes_map_t map = z_slice_map_new(); // set it as an attachment - options.attachment = z_bytes_map_as_attachment(&map); + options.attachment = z_slice_map_as_attachment(&map); // add some value - z_bytes_map_insert_by_alias(&map, z_bytes_from_str("source"), z_bytes_from_str("C")); + z_slice_map_insert_by_alias(&map, z_slice_from_str("source"), z_slice_from_str("C")); char buf[256]; char buf_ind[16]; @@ -67,11 +67,12 @@ int main(int argc, char **argv) { // add some other attachment value sprintf(buf_ind, "%d", idx); - z_bytes_map_insert_by_alias(&map, z_bytes_from_str("index"), z_bytes_from_str(buf_ind)); + z_slice_map_insert_by_alias(&map, z_slice_from_str("index"), z_slice_from_str(buf_ind)); sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put(z_loan(pub), (const uint8_t *)buf, strlen(buf), &options); + z_owned_bytes_t payload = z_bytes_encode_from_string(buf); + z_publisher_put(z_loan(pub), z_move(payload), &options); } z_undeclare_publisher(z_move(pub)); diff --git a/examples/z_pub_cache.c b/examples/z_pub_cache.c index 770bf9d93..7594fee1f 100644 --- a/examples/z_pub_cache.c +++ b/examples/z_pub_cache.c @@ -63,7 +63,8 @@ int main(int argc, char **argv) { z_sleep_s(1); sprintf(buf, "[%4d] %s", idx, value); printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)buf, strlen(buf), NULL); + z_owned_bytes_t payload = z_bytes_encode_from_string(buf); + z_put(z_loan(s), z_keyexpr(keyexpr), z_move(payload), NULL); } z_drop(z_move(pub_cache)); diff --git a/examples/z_pub_shm.c b/examples/z_pub_shm.c deleted file mode 100644 index 10970bf62..000000000 --- a/examples/z_pub_shm.c +++ /dev/null @@ -1,94 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// -#include -#include -#include -#include - -#include "zenoh.h" - -#define N 10 - -int main(int argc, char **argv) { - char *keyexpr = "demo/example/zenoh-c-pub-shm"; - char *value = "Pub from C!"; - - if (argc > 1) keyexpr = argv[1]; - if (argc > 2) value = argv[2]; - - z_owned_config_t config = z_config_default(); - // Enable shared memory - if (zc_config_insert_json(z_loan(config), "transport/shared_memory/enabled", "true") < 0) { - printf("Error enabling Shared Memory"); - exit(-1); - } - if (argc > 3) { - if (zc_config_insert_json(z_loan(config), Z_CONFIG_CONNECT_KEY, argv[3]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[3], Z_CONFIG_CONNECT_KEY, Z_CONFIG_CONNECT_KEY); - exit(-1); - } - } - - printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - z_id_t id = z_info_zid(z_loan(s)); - char idstr[33]; - for (int i = 0; i < 16; i++) { - sprintf(idstr + 2 * i, "%02x", id.id[i]); - } - idstr[32] = 0; - zc_owned_shm_manager_t manager = zc_shm_manager_new(z_loan(s), idstr, N * 1000000); - if (!z_check(s)) { - printf("Unable to open session!\n"); - exit(-1); - } - - printf("Declaring Publisher on '%s'...\n", keyexpr); - z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); - if (!z_check(pub)) { - printf("Unable to declare Publisher for key expression!\n"); - exit(-1); - } - - for (int idx = 0; true; ++idx) { - zc_owned_shmbuf_t shmbuf = zc_shm_alloc(&manager, 256); - if (!z_check(shmbuf)) { - zc_shm_gc(&manager); - shmbuf = zc_shm_alloc(&manager, 256); - if (!z_check(shmbuf)) { - printf("Failed to allocate a SHM buffer, even after GCing\n"); - exit(-1); - } - } - char *buf = (char *)zc_shmbuf_ptr(&shmbuf); - buf[256] = 0; - snprintf(buf, 255, "[%4d] %s", idx, value); - size_t len = strlen(buf); - zc_shmbuf_set_length(&shmbuf, len); - z_sleep_s(1); - printf("Putting Data ('%s': '%s')...\n", keyexpr, buf); - z_publisher_put_options_t options = z_publisher_put_options_default(); - options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - zc_owned_payload_t payload = zc_shmbuf_into_payload(z_move(shmbuf)); - zc_publisher_put_owned(z_loan(pub), z_move(payload), &options); - } - - z_undeclare_publisher(z_move(pub)); - - z_close(z_move(s)); - return 0; -} diff --git a/examples/z_pub_thr.c b/examples/z_pub_thr.c index 8686c33eb..c59f3f6c7 100644 --- a/examples/z_pub_thr.c +++ b/examples/z_pub_thr.c @@ -54,7 +54,8 @@ int main(int argc, char **argv) { } while (1) { - z_publisher_put(z_loan(pub), (const uint8_t *)value, len, NULL); + z_owned_bytes_t payload = z_bytes_encode_from_bytes((z_loaned_slice_t){.start = value, .len = len}); + z_publisher_put(z_loan(pub), z_move(payload), NULL); } z_undeclare_publisher(z_move(pub)); diff --git a/examples/z_pull.c b/examples/z_pull.c deleted file mode 100644 index 0af23f7e2..000000000 --- a/examples/z_pull.c +++ /dev/null @@ -1,83 +0,0 @@ -// -// Copyright (c) 2022 ZettaScale Technology -// -// This program and the accompanying materials are made available under the -// terms of the Eclipse Public License 2.0 which is available at -// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 -// which is available at https://www.apache.org/licenses/LICENSE-2.0. -// -// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 -// -// Contributors: -// ZettaScale Zenoh Team, -// -#include -#include "zenoh.h" - -const char *kind_to_str(z_sample_kind_t kind); - -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), - (int)sample->payload.len, sample->payload.start); - z_drop(z_move(keystr)); -} - -int main(int argc, char **argv) { - char *expr = "demo/example/**"; - if (argc > 1) { - expr = argv[1]; - } - - z_owned_config_t config = z_config_default(); - if (argc > 2) { - if (zc_config_insert_json(z_loan(config), Z_CONFIG_LISTEN_KEY, argv[2]) < 0) { - printf( - "Couldn't insert value `%s` in configuration at `%s`. This is likely because `%s` expects a " - "JSON-serialized list of strings\n", - argv[2], Z_CONFIG_LISTEN_KEY, Z_CONFIG_LISTEN_KEY); - exit(-1); - } - } - - printf("Opening session...\n"); - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { - printf("Unable to open session!\n"); - exit(-1); - } - - z_owned_closure_sample_t callback = z_closure(data_handler); - printf("Declaring Subscriber on '%s'...\n", expr); - z_owned_pull_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(expr), z_move(callback), NULL); - if (!z_check(sub)) { - printf("Unable to declare subscriber.\n"); - exit(-1); - } - - printf("Press to pull data...\n"); - char c = 0; - while (c != 'q') { - c = getchar(); - if (c == -1) { - z_sleep_s(1); - } else { - z_subscriber_pull(z_loan(sub)); - } - } - - z_undeclare_pull_subscriber(z_move(sub)); - z_close(z_move(s)); - return 0; -} - -const char *kind_to_str(z_sample_kind_t kind) { - switch (kind) { - case Z_SAMPLE_KIND_PUT: - return "PUT"; - case Z_SAMPLE_KIND_DELETE: - return "DELETE"; - default: - return "UNKNOWN"; - } -} \ No newline at end of file diff --git a/examples/z_put.c b/examples/z_put.c index 498d1e958..c74f95672 100644 --- a/examples/z_put.c +++ b/examples/z_put.c @@ -23,8 +23,8 @@ int main(int argc, char **argv) { if (argc > 1) keyexpr = argv[1]; if (argc > 2) value = argv[2]; - z_owned_bytes_map_t attachment = z_bytes_map_new(); - z_bytes_map_insert_by_alias(&attachment, z_bytes_from_str("hello"), z_bytes_from_str("there")); + z_owned_bytes_map_t attachment = z_slice_map_new(); + z_slice_map_insert_by_alias(&attachment, z_slice_from_str("hello"), z_slice_from_str("there")); z_owned_config_t config = z_config_default(); if (argc > 3) { @@ -47,8 +47,9 @@ int main(int argc, char **argv) { printf("Putting Data ('%s': '%s')...\n", keyexpr, value); z_put_options_t options = z_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - options.attachment = z_bytes_map_as_attachment(&attachment); - int res = z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)value, strlen(value), &options); + options.attachment = z_slice_map_as_attachment(&attachment); + z_owned_bytes_t payload = z_bytes_encode_from_string(value); + int res = z_put(z_loan(s), z_keyexpr(keyexpr), z_move(payload), &options); if (res < 0) { printf("Put failed...\n"); } diff --git a/examples/z_query_sub.c b/examples/z_query_sub.c index 15564be7c..4a2d72cc9 100644 --- a/examples/z_query_sub.c +++ b/examples/z_query_sub.c @@ -16,10 +16,13 @@ const char *kind_to_str(z_sample_kind_t kind); -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), - (int)sample->payload.len, sample->payload.start); +void data_handler(const z_loaned_sample_t *sample, void *arg) { + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(sample)); + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(z_sample_payload(sample), &payload_value); + printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + z_loan(payload_value)); + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } diff --git a/examples/z_queryable.c b/examples/z_queryable.c index 9d6ec7702..191daf413 100644 --- a/examples/z_queryable.c +++ b/examples/z_queryable.c @@ -17,21 +17,26 @@ const char *expr = "demo/example/zenoh-c-queryable"; const char *value = "Queryable from C!"; -z_keyexpr_t keyexpr; +z_loaned_keyexpr_t keyexpr; -void query_handler(const z_query_t *query, void *context) { - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - z_value_t payload_value = z_query_value(query); - if (payload_value.payload.len > 0) { - printf(">> [Queryable ] Received Query '%s?%.*s' with value '%.*s'\n", z_loan(keystr), (int)pred.len, - pred.start, (int)payload_value.payload.len, payload_value.payload.start); +void query_handler(const z_loaned_query_t *query, void *context) { + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_query_keyexpr(query)); + z_loaned_slice_t pred = z_query_parameters(query); + z_loaned_bytes_t payload = z_query_value(query).payload; + if (z_bytes_len(payload) > 0) { + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(payload, &payload_value); + printf(">> [Queryable ] Received Query '%s?%.*s' with value '%s'\n", z_loan(keystr), (int)pred.len, + pred.start, z_loan(payload_value)); + z_drop(z_move(payload_value)); } else { printf(">> [Queryable ] Received Query '%s?%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); } z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(query, z_keyexpr((const char *)context), (const unsigned char *)value, strlen(value), &options); + + z_owned_bytes_t reply_payload = z_bytes_encode_from_string(value); + z_query_reply(query, z_keyexpr((const char *)context), z_move(reply_payload), &options); z_drop(z_move(keystr)); } diff --git a/examples/z_queryable_with_channels.c b/examples/z_queryable_with_channels.c index 672ddd607..0fec21120 100644 --- a/examples/z_queryable_with_channels.c +++ b/examples/z_queryable_with_channels.c @@ -18,9 +18,9 @@ const char *expr = "demo/example/zenoh-c-queryable"; const char *value = "Queryable from C!"; -z_keyexpr_t keyexpr; +z_loaned_keyexpr_t keyexpr; -void query_handler(const z_query_t *query, void *context) { +void query_handler(const z_loaned_query_t *query, void *context) { z_owned_closure_owned_query_t *channel = (z_owned_closure_owned_query_t *)context; z_owned_query_t oquery = z_query_clone(query); z_call(*channel, &oquery); @@ -65,19 +65,23 @@ int main(int argc, char **argv) { printf("^C to quit...\n"); z_owned_query_t oquery = z_query_null(); for (z_call(channel.recv, &oquery); z_check(oquery); z_call(channel.recv, &oquery)) { - z_query_t query = z_loan(oquery); - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(&query)); - z_bytes_t pred = z_query_parameters(&query); - z_value_t payload_value = z_query_value(&query); - if (payload_value.payload.len > 0) { - printf(">> [Queryable ] Received Query '%s?%.*s' with value '%.*s'\n", z_loan(keystr), (int)pred.len, - pred.start, (int)payload_value.payload.len, payload_value.payload.start); + z_loaned_query_t query = z_loan(oquery); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_query_keyexpr(&query)); + z_loaned_slice_t pred = z_query_parameters(&query); + z_loaned_bytes_t payload = z_query_value(&query).payload; + if (z_bytes_len(payload) > 0) { + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(payload, &payload_value); + printf(">> [Queryable ] Received Query '%s?%.*s' with value '%s'\n", z_loan(keystr), (int)pred.len, + pred.start, z_loan(payload_value)); + z_drop(z_move(payload_value)); } else { printf(">> [Queryable ] Received Query '%s?%.*s'\n", z_loan(keystr), (int)pred.len, pred.start); } z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(&query, keyexpr, (const unsigned char *)value, strlen(value), &options); + z_owned_bytes_t reply_payload = z_bytes_encode_from_string(value); + z_query_reply(&query, keyexpr, z_move(reply_payload), &options); z_drop(z_move(keystr)); z_drop(z_move(oquery)); } diff --git a/examples/z_sub.c b/examples/z_sub.c index 867c1277e..f5b986634 100644 --- a/examples/z_sub.c +++ b/examples/z_sub.c @@ -16,10 +16,13 @@ const char *kind_to_str(z_sample_kind_t kind); -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), - (int)sample->payload.len, sample->payload.start); +void data_handler(const z_loaned_sample_t *sample, void *arg) { + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(sample)); + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(z_sample_payload(sample), &payload_value); + printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + z_loan(payload_value)); + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } diff --git a/examples/z_sub_attachment.c b/examples/z_sub_attachment.c index 58b0afd81..13412321a 100644 --- a/examples/z_sub_attachment.c +++ b/examples/z_sub_attachment.c @@ -17,27 +17,31 @@ const char *kind_to_str(z_sample_kind_t kind); -int8_t attachment_reader(z_bytes_t key, z_bytes_t val, void *ctx) { +int8_t attachment_reader(z_loaned_slice_t key, z_loaned_slice_t val, void *ctx) { printf(" attachment: %.*s: '%.*s'\n", (int)key.len, key.start, (int)val.len, val.start); return 0; } -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - printf(">> [Subscriber] Received %s ('%s': '%.*s')\n", kind_to_str(sample->kind), z_loan(keystr), - (int)sample->payload.len, sample->payload.start); +void data_handler(const z_loaned_sample_t *sample, void *arg) { + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(sample)); + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(z_sample_payload(sample), &payload_value); + printf(">> [Subscriber] Received %s ('%s': '%s')\n", kind_to_str(z_sample_kind(sample)), z_loan(keystr), + z_loan(payload_value)); + z_loaned_bytes_t attachment = z_sample_attachment(sample); // checks if attachment exists - if (z_check(sample->attachment)) { + if (z_check(attachment)) { // reads full attachment - z_attachment_iterate(sample->attachment, attachment_reader, NULL); + z_attachment_iterate(attachment, attachment_reader, NULL); // reads particular attachment item - z_bytes_t index = z_attachment_get(sample->attachment, z_bytes_from_str("index")); - if (z_check(index)) { + z_loaned_slice_t index = z_attachment_get(attachment, z_slice_from_str("index")); + if (z_slice_is_initialized(&index)) { printf(" message number: %.*s\n", (int)index.len, index.start); } } + z_drop(z_move(payload_value)); z_drop(z_move(keystr)); } diff --git a/examples/z_sub_liveliness.c b/examples/z_sub_liveliness.c index 36bf64515..5c6b49d6a 100644 --- a/examples/z_sub_liveliness.c +++ b/examples/z_sub_liveliness.c @@ -14,9 +14,9 @@ #include #include "zenoh.h" -void data_handler(const z_sample_t *sample, void *arg) { - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); - switch (sample->kind) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(sample)); + switch (z_sample_kind(sample)) { case Z_SAMPLE_KIND_PUT: printf(">> [LivelinessSubscriber] New alive token ('%s')\n", z_loan(keystr)); break; @@ -33,7 +33,7 @@ int main(int argc, char **argv) { expr = argv[1]; } - z_keyexpr_t keyexpr = z_keyexpr(expr); + z_loaned_keyexpr_t keyexpr = z_keyexpr(expr); if (!z_check(keyexpr)) { printf("%s is not a valid key expression\n", expr); exit(-1); diff --git a/examples/z_sub_thr.c b/examples/z_sub_thr.c index 05ee709d3..d7e69a29f 100644 --- a/examples/z_sub_thr.c +++ b/examples/z_sub_thr.c @@ -14,6 +14,7 @@ #include #include "zenoh.h" +#include #define N 1000000 @@ -33,7 +34,7 @@ z_stats_t *z_stats_make() { return stats; } -void on_sample(const z_sample_t *sample, void *context) { +void on_sample(z_loaned_sample_t sample, void *context) { z_stats_t *stats = (z_stats_t *)context; if (stats->count == 0) { stats->start = z_clock_now(); @@ -60,7 +61,8 @@ void drop_stats(void *context) { } int main(int argc, char **argv) { - z_owned_config_t config = z_config_default(); + z_owned_config_t config; + z_config_default(&config); if (argc > 1) { if (zc_config_insert_json(z_loan(config), Z_CONFIG_CONNECT_KEY, argv[1]) < 0) { printf( @@ -71,18 +73,22 @@ int main(int argc, char **argv) { } } - z_owned_session_t s = z_open(z_move(config)); - if (!z_check(s)) { + z_owned_session_t s; + + if (z_open(&s, z_move(config)) < 0) { printf("Unable to open session!\n"); exit(-1); } - z_owned_keyexpr_t ke = z_declare_keyexpr(z_loan(s), z_keyexpr("test/thr")); + z_owned_keyexpr_t ke; + z_keyexpr(&ke, "test/thr"); + z_owned_keyexpr_t declared_ke; + z_declare_keyexpr(&ke, z_loan(s), z_loan(ke)); z_stats_t *context = z_stats_make(); z_owned_closure_sample_t callback = z_closure(on_sample, drop_stats, context); - z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_loan(ke), z_move(callback), NULL); - if (!z_check(sub)) { + z_owned_subscriber_t sub; + if (z_declare_subscriber(&sub, z_loan(s), z_loan(declared_ke), z_move(callback), NULL)) { printf("Unable to create subscriber.\n"); exit(-1); } @@ -93,7 +99,8 @@ int main(int argc, char **argv) { } z_undeclare_subscriber(z_move(sub)); - z_undeclare_keyexpr(z_loan(s), z_move(ke)); + z_keyexpr_drop(z_move(ke)); + z_undeclare_keyexpr(z_loan(s), z_move(declared_ke)); z_close(z_move(s)); return 0; } diff --git a/include/zenoh_commons.h b/include/zenoh_commons.h index 84b125fbe..2dc3d7be3 100644 --- a/include/zenoh_commons.h +++ b/include/zenoh_commons.h @@ -45,54 +45,6 @@ typedef enum z_consolidation_mode_t { Z_CONSOLIDATION_MODE_MONOTONIC = 1, Z_CONSOLIDATION_MODE_LATEST = 2, } z_consolidation_mode_t; -/** - * A :c:type:`z_encoding_t` integer `prefix`. - * - * - **Z_ENCODING_PREFIX_EMPTY** - * - **Z_ENCODING_PREFIX_APP_OCTET_STREAM** - * - **Z_ENCODING_PREFIX_APP_CUSTOM** - * - **Z_ENCODING_PREFIX_TEXT_PLAIN** - * - **Z_ENCODING_PREFIX_APP_PROPERTIES** - * - **Z_ENCODING_PREFIX_APP_JSON** - * - **Z_ENCODING_PREFIX_APP_SQL** - * - **Z_ENCODING_PREFIX_APP_INTEGER** - * - **Z_ENCODING_PREFIX_APP_FLOAT** - * - **Z_ENCODING_PREFIX_APP_XML** - * - **Z_ENCODING_PREFIX_APP_XHTML_XML** - * - **Z_ENCODING_PREFIX_APP_X_WWW_FORM_URLENCODED** - * - **Z_ENCODING_PREFIX_TEXT_JSON** - * - **Z_ENCODING_PREFIX_TEXT_HTML** - * - **Z_ENCODING_PREFIX_TEXT_XML** - * - **Z_ENCODING_PREFIX_TEXT_CSS** - * - **Z_ENCODING_PREFIX_TEXT_CSV** - * - **Z_ENCODING_PREFIX_TEXT_JAVASCRIPT** - * - **Z_ENCODING_PREFIX_IMAGE_JPEG** - * - **Z_ENCODING_PREFIX_IMAGE_PNG** - * - **Z_ENCODING_PREFIX_IMAGE_GIF** - */ -typedef enum z_encoding_prefix_t { - Z_ENCODING_PREFIX_EMPTY = 0, - Z_ENCODING_PREFIX_APP_OCTET_STREAM = 1, - Z_ENCODING_PREFIX_APP_CUSTOM = 2, - Z_ENCODING_PREFIX_TEXT_PLAIN = 3, - Z_ENCODING_PREFIX_APP_PROPERTIES = 4, - Z_ENCODING_PREFIX_APP_JSON = 5, - Z_ENCODING_PREFIX_APP_SQL = 6, - Z_ENCODING_PREFIX_APP_INTEGER = 7, - Z_ENCODING_PREFIX_APP_FLOAT = 8, - Z_ENCODING_PREFIX_APP_XML = 9, - Z_ENCODING_PREFIX_APP_XHTML_XML = 10, - Z_ENCODING_PREFIX_APP_X_WWW_FORM_URLENCODED = 11, - Z_ENCODING_PREFIX_TEXT_JSON = 12, - Z_ENCODING_PREFIX_TEXT_HTML = 13, - Z_ENCODING_PREFIX_TEXT_XML = 14, - Z_ENCODING_PREFIX_TEXT_CSS = 15, - Z_ENCODING_PREFIX_TEXT_CSV = 16, - Z_ENCODING_PREFIX_TEXT_JAVASCRIPT = 17, - Z_ENCODING_PREFIX_IMAGE_JPEG = 18, - Z_ENCODING_PREFIX_IMAGE_PNG = 19, - Z_ENCODING_PREFIX_IMAGE_GIF = 20, -} z_encoding_prefix_t; /** * A :c:type:`z_keyexpr_intersection_level_t`. * @@ -107,6 +59,18 @@ typedef enum z_keyexpr_intersection_level_t { Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES = 2, Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS = 3, } z_keyexpr_intersection_level_t; +/** + * The Queryables that should be target of a :c:func:`z_get`. + * + * - **BEST_MATCHING**: The nearest complete queryable if any else all matching queryables. + * - **ALL_COMPLETE**: All complete queryables. + * - **ALL**: All matching queryables. + */ +typedef enum z_loaned_query_target_t { + Z_LOANED_QUERY_TARGET_BEST_MATCHING, + Z_LOANED_QUERY_TARGET_ALL, + Z_LOANED_QUERY_TARGET_ALL_COMPLETE, +} z_loaned_query_target_t; /** * The priority of zenoh messages. * @@ -127,18 +91,6 @@ typedef enum z_priority_t { Z_PRIORITY_DATA_LOW = 6, Z_PRIORITY_BACKGROUND = 7, } z_priority_t; -/** - * The Queryables that should be target of a :c:func:`z_get`. - * - * - **BEST_MATCHING**: The nearest complete queryable if any else all matching queryables. - * - **ALL_COMPLETE**: All complete queryables. - * - **ALL**: All matching queryables. - */ -typedef enum z_query_target_t { - Z_QUERY_TARGET_BEST_MATCHING, - Z_QUERY_TARGET_ALL, - Z_QUERY_TARGET_ALL_COMPLETE, -} z_query_target_t; /** * The subscription reliability. * @@ -163,55 +115,63 @@ typedef enum zcu_reply_keyexpr_t { ZCU_REPLY_KEYEXPR_MATCHING_QUERY = 1, } zcu_reply_keyexpr_t; /** - * A contiguous view of bytes owned by some other entity. + * A split buffer that owns all of its data. * - * `start` being `null` is considered a gravestone value, - * and empty slices are represented using a possibly dangling pointer for `start`. + * To minimize copies and reallocations, Zenoh may provide you data in split buffers. */ -typedef struct z_bytes_t { - size_t len; - const uint8_t *start; -} z_bytes_t; +typedef struct ALIGN(8) z_owned_bytes_t { + uint8_t _0[40]; +} z_owned_bytes_t; /** - * The body of a loop over an attachment's key-value pairs. - * - * `key` and `value` are loaned to the body for the duration of a single call. - * `context` is passed transparently through the iteration driver. - * - * Returning `0` is treated as `continue`. - * Returning any other value is treated as `break`. + * A loaned payload. */ -typedef int8_t (*z_attachment_iter_body_t)(struct z_bytes_t key, - struct z_bytes_t value, - void *context); +typedef struct ALIGN(8) z_loaned_bytes_t { + uint8_t _0[40]; +} z_loaned_bytes_t; +typedef int8_t z_error_t; /** - * The driver of a loop over an attachment's key-value pairs. + * A contiguous view of bytes owned by some other entity. * - * This function is expected to call `loop_body` once for each key-value pair - * within `iterator`, passing `context`, and returning any non-zero value immediately (breaking iteration). + * `start` being `null` is considered a gravestone value, + * and empty slices are represented using a possibly dangling pointer for `start`. */ -typedef int8_t (*z_attachment_iter_driver_t)(const void *iterator, - z_attachment_iter_body_t loop_body, - void *context); +typedef struct ALIGN(8) z_owned_slice_t { + uint8_t _0[16]; +} z_owned_slice_t; /** - * A iteration based map of byte slice to byte slice. + * A map of maybe-owned vector of bytes to maybe-owned vector of bytes. * - * `iteration_driver == NULL` marks the gravestone value, as this type is often optional. - * Users are encouraged to use `z_attachment_null` and `z_attachment_check` to interact. + * In Zenoh C, this map is backed by Rust's standard HashMap, with a DoS-resistant hasher */ -typedef struct z_attachment_t { - const void *data; - z_attachment_iter_driver_t iteration_driver; -} z_attachment_t; +typedef struct ALIGN(8) z_owned_slice_map_t { + uint8_t _0[48]; +} z_owned_slice_map_t; /** - * A map of maybe-owned vector of bytes to owned vector of bytes. - * - * In Zenoh C, this map is backed by Rust's standard HashMap, with a DoS-resistant hasher + * The wrapper type for null-terminated string values allocated by zenoh. The instances of `z_owned_str_t` + * should be released with `z_drop` macro or with `z_str_drop` function and checked to validity with + * `z_check` and `z_str_check` correspondently */ -typedef struct z_owned_bytes_map_t { - uint64_t _0[2]; - size_t _1[4]; -} z_owned_bytes_map_t; +typedef struct ALIGN(8) z_owned_str_t { + uint8_t _0[16]; +} z_owned_str_t; +typedef struct ALIGN(8) z_loaned_slice_t { + uint8_t _0[16]; +} z_loaned_slice_t; +typedef struct ALIGN(8) z_loaned_slice_map_t { + uint8_t _0[48]; +} z_loaned_slice_map_t; +typedef struct ALIGN(8) z_loaned_str_t { + uint8_t _0[16]; +} z_loaned_str_t; +/** + * A reader for payload data. + */ +typedef struct ALIGN(8) z_owned_bytes_reader_t { + uint8_t _0[24]; +} z_owned_bytes_reader_t; +typedef struct ALIGN(8) z_loaned_bytes_reader_t { + uint8_t _0[24]; +} z_loaned_bytes_reader_t; /** * Clock * Uses monotonic clock @@ -225,7 +185,7 @@ typedef struct z_clock_t { * * In general, valid Zenoh IDs are LSB-first 128bit unsigned and non-zero integers. */ -typedef struct z_id_t { +typedef struct ALIGN(1) z_id_t { uint8_t id[16]; } z_id_t; /** @@ -282,24 +242,19 @@ typedef struct z_owned_closure_hello_t { void (*drop)(void*); } z_owned_closure_hello_t; /** - * Owned variant of a Query received by a Queryable. - * - * You may construct it by `z_query_clone`-ing a loaned query. - * When the last `z_owned_query_t` corresponding to a query is destroyed, or the callback that produced the query cloned to build them returns, - * the query will receive its termination signal. * - * Holding onto an `z_owned_query_t` for too long (10s by default, can be set in `z_get`'s options) will trigger a timeout error - * to be sent to the querier by the infrastructure, and new responses to the outdated query will be silently dropped. + * Queries are atomically reference-counted, letting you extract them from the callback that handed them to you by cloning. + * `z_loaned_query_t`'s are valid as long as at least one corresponding `z_owned_query_t` exists, including the one owned by Zenoh until the callback returns. */ -typedef struct z_owned_query_t { - void *_0; +typedef struct ALIGN(8) z_owned_query_t { + uint8_t _0[16]; } z_owned_query_t; /** * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks: * * Members: * void *context: a pointer to an arbitrary state. - * void *call(const struct z_query_t*, const void *context): the typical callback function. `context` will be passed as its last argument. + * void *call(const struct z_loaned_query_t*, const void *context): the typical callback function. `context` will be passed as its last argument. * void *drop(void*): allows the callback's state to be freed. * * Closures are not guaranteed not to be called concurrently. @@ -320,7 +275,7 @@ typedef struct z_owned_closure_owned_query_t { * * Members: * void *context: a pointer to an arbitrary state. - * void *call(const struct z_query_t*, const void *context): the typical callback function. `context` will be passed as its last argument. + * void *call(z_loaned_query_t, const void *context): the typical callback function. `context` will be passed as its last argument. * void *drop(void*): allows the callback's state to be freed. * * Closures are not guaranteed not to be called concurrently. @@ -333,28 +288,12 @@ typedef struct z_owned_closure_owned_query_t { */ typedef struct z_owned_closure_query_t { void *context; - void (*call)(const struct z_query_t*, void *context); + void (*call)(const struct z_loaned_query_t*, void *context); void (*drop)(void*); } z_owned_closure_query_t; -/** - * An owned reply to a :c:func:`z_get`. - * - * Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. - * To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. - * After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. - * - * To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. - */ -#if !defined(TARGET_ARCH_ARM) -typedef struct ALIGN(8) z_owned_reply_t { - uint64_t _0[30]; -} z_owned_reply_t; -#endif -#if defined(TARGET_ARCH_ARM) -typedef struct ALIGN(8) z_owned_reply_t { - uint64_t _0[19]; -} z_owned_reply_t; -#endif +typedef struct ALIGN(8) z_loaned_reply_t { + uint8_t _0[256]; +} z_loaned_reply_t; /** * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks: * @@ -373,84 +312,18 @@ typedef struct ALIGN(8) z_owned_reply_t { */ typedef struct z_owned_closure_reply_t { void *context; - void (*call)(struct z_owned_reply_t*, void*); + void (*call)(const struct z_loaned_reply_t*, void*); void (*drop)(void*); } z_owned_closure_reply_t; -/** - * A loaned key expression. - * - * Key expressions can identify a single key or a set of keys. - * - * Examples : - * - ``"key/expression"``. - * - ``"key/ex*"``. - * - * Using :c:func:`z_declare_keyexpr` allows zenoh to optimize a key expression, - * both for local processing and network-wise. - */ -#if !defined(TARGET_ARCH_ARM) -typedef struct ALIGN(8) z_keyexpr_t { - uint64_t _0[4]; -} z_keyexpr_t; -#endif -#if defined(TARGET_ARCH_ARM) -typedef struct ALIGN(4) z_keyexpr_t { - uint32_t _0[5]; -} z_keyexpr_t; -#endif -/** - * The encoding of a payload, in a MIME-like format. - * - * For wire and matching efficiency, common MIME types are represented using an integer as `prefix`, and a `suffix` may be used to either provide more detail, or in combination with the `Empty` prefix to write arbitrary MIME types. - * - * Members: - * z_encoding_prefix_t prefix: The integer prefix of this encoding. - * z_bytes_t suffix: The suffix of this encoding. `suffix` MUST be a valid UTF-8 string. - */ -typedef struct z_encoding_t { - enum z_encoding_prefix_t prefix; - struct z_bytes_t suffix; -} z_encoding_t; -typedef struct z_timestamp_t { - uint64_t time; - struct z_id_t id; -} z_timestamp_t; -/** - * QoS settings of zenoh message. - * - */ -typedef struct z_qos_t { - uint8_t _0; -} z_qos_t; -/** - * A data sample. - * - * A sample is the value associated to a given resource at a given point in time. - * - * Members: - * z_keyexpr_t keyexpr: The resource key of this data sample. - * z_bytes_t payload: The value of this data sample. - * z_encoding_t encoding: The encoding of the value of this data sample. - * z_sample_kind_t kind: The kind of this data sample (PUT or DELETE). - * z_timestamp_t timestamp: The timestamp of this data sample. - * z_attachment_t attachment: The attachment of this data sample. - */ -typedef struct z_sample_t { - struct z_keyexpr_t keyexpr; - struct z_bytes_t payload; - struct z_encoding_t encoding; - const void *_zc_buf; - enum z_sample_kind_t kind; - struct z_timestamp_t timestamp; - struct z_qos_t qos; - struct z_attachment_t attachment; -} z_sample_t; +typedef struct ALIGN(8) z_loaned_sample_t { + uint8_t _0[240]; +} z_loaned_sample_t; /** * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. * * Members: * void *context: a pointer to an arbitrary state. - * void *call(const struct z_sample_t*, const void *context): the typical callback function. `context` will be passed as its last argument. + * void *call(struct z_loaned_sample_t, const void *context): the typical callback function. `context` will be passed as its last argument. * void *drop(void*): allows the callback's state to be freed. * * Closures are not guaranteed not to be called concurrently. @@ -463,7 +336,7 @@ typedef struct z_sample_t { */ typedef struct z_owned_closure_sample_t { void *context; - void (*call)(const struct z_sample_t*, void *context); + void (*call)(const struct z_loaned_sample_t*, void *context); void (*drop)(void*); } z_owned_closure_sample_t; /** @@ -487,20 +360,15 @@ typedef struct z_owned_closure_zid_t { void (*call)(const struct z_id_t*, void*); void (*drop)(void*); } z_owned_closure_zid_t; -/** - * Condvar - * - */ -typedef struct z_condvar_t { - size_t _0; -} z_condvar_t; -/** - * Mutex - * - */ -typedef struct z_mutex_t { - size_t _0; -} z_mutex_t; +typedef struct ALIGN(4) z_owned_condvar_t { + uint8_t _0[8]; +} z_owned_condvar_t; +typedef struct ALIGN(4) z_loaned_condvar_t { + uint8_t _0[4]; +} z_loaned_condvar_t; +typedef struct ALIGN(8) z_loaned_mutex_t { + uint8_t _0[24]; +} z_loaned_mutex_t; /** * An owned zenoh configuration. * @@ -513,15 +381,15 @@ typedef struct z_mutex_t { * * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ -typedef struct z_owned_config_t { - void *_0; +typedef struct ALIGN(8) z_owned_config_t { + uint8_t _0[1544]; } z_owned_config_t; /** * A loaned zenoh configuration. */ -typedef struct z_config_t { - const struct z_owned_config_t *_0; -} z_config_t; +typedef struct ALIGN(8) z_loaned_config_t { + uint8_t _0[1544]; +} z_loaned_config_t; /** * A zenoh-allocated key expression. * @@ -548,16 +416,24 @@ typedef struct z_config_t { * * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ -#if !defined(TARGET_ARCH_ARM) typedef struct ALIGN(8) z_owned_keyexpr_t { - uint64_t _0[4]; -} z_owned_keyexpr_t; -#endif -#if defined(TARGET_ARCH_ARM) -typedef struct ALIGN(4) z_owned_keyexpr_t { - uint32_t _0[5]; + uint8_t _0[32]; } z_owned_keyexpr_t; -#endif +/** + * A loaned key expression. + * + * Key expressions can identify a single key or a set of keys. + * + * Examples : + * - ``"key/expression"``. + * - ``"key/ex*"``. + * + * Using :c:func:`z_declare_keyexpr` allows zenoh to optimize a key expression, + * both for local processing and network-wise. + */ +typedef struct ALIGN(8) z_loaned_keyexpr_t { + uint8_t _0[32]; +} z_loaned_keyexpr_t; /** * An owned zenoh publisher. * @@ -570,16 +446,9 @@ typedef struct ALIGN(4) z_owned_keyexpr_t { * * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ -#if !defined(TARGET_ARCH_ARM) typedef struct ALIGN(8) z_owned_publisher_t { - uint64_t _0[7]; + uint8_t _0[56]; } z_owned_publisher_t; -#endif -#if defined(TARGET_ARCH_ARM) -typedef struct ALIGN(4) z_owned_publisher_t { - uint32_t _0[8]; -} z_owned_publisher_t; -#endif /** * Options passed to the :c:func:`z_declare_publisher` function. * @@ -591,16 +460,6 @@ typedef struct z_publisher_options_t { enum z_congestion_control_t congestion_control; enum z_priority_t priority; } z_publisher_options_t; -/** - * Represents the set of options that can be applied to a pull subscriber, - * upon its declaration via :c:func:`z_declare_pull_subscriber`. - * - * Members: - * z_reliability_t reliability: The subscription reliability. - */ -typedef struct z_pull_subscriber_options_t { - enum z_reliability_t reliability; -} z_pull_subscriber_options_t; /** * Options passed to the :c:func:`z_declare_queryable` function. * @@ -626,56 +485,39 @@ typedef struct z_delete_options_t { enum z_congestion_control_t congestion_control; enum z_priority_t priority; } z_delete_options_t; +typedef struct ALIGN(8) z_owned_encoding_t { + uint8_t _0[48]; +} z_owned_encoding_t; /** - * An owned payload encoding. - * - * Members: - * z_encoding_prefix_t prefix: The integer prefix of this encoding. - * z_bytes_t suffix: The suffix of this encoding. `suffix` MUST be a valid UTF-8 string. - * - * Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. - * To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. - * After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. + * The encoding of a payload, in a MIME-like format. * - * To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. + * For wire and matching efficiency, common MIME types are represented using an integer as `prefix`, and a `suffix` may be used to either provide more detail, or in combination with the `Empty` prefix to write arbitrary MIME types. */ -typedef struct z_owned_encoding_t { - enum z_encoding_prefix_t prefix; - struct z_bytes_t suffix; - bool _dropped; -} z_owned_encoding_t; +typedef struct ALIGN(8) z_loaned_encoding_t { + uint8_t _0[48]; +} z_loaned_encoding_t; /** * The replies consolidation strategy to apply on replies to a :c:func:`z_get`. */ typedef struct z_query_consolidation_t { enum z_consolidation_mode_t mode; } z_query_consolidation_t; -/** - * A zenoh value. - * - * Members: - * z_bytes_t payload: The payload of this zenoh value. - * z_encoding_t encoding: The encoding of this zenoh value `payload`. - */ -typedef struct z_value_t { - struct z_bytes_t payload; - struct z_encoding_t encoding; -} z_value_t; /** * Options passed to the :c:func:`z_get` function. * * Members: - * z_query_target_t target: The Queryables that should be target of the query. + * z_loaned_query_target_t target: The Queryables that should be target of the query. * z_query_consolidation_t consolidation: The replies consolidation strategy to apply on replies to the query. - * z_value_t value: An optional value to attach to the query. - * z_attachment_t attachment: The attachment to attach to the query. + * z_loaned_value_t value: An optional value to attach to the query. + * z_loaned_bytes_t attachment: The attachment to attach to the query. * uint64_t timeout: The timeout for the query in milliseconds. 0 means default query timeout from zenoh configuration. */ typedef struct z_get_options_t { - enum z_query_target_t target; + enum z_loaned_query_target_t target; struct z_query_consolidation_t consolidation; - struct z_value_t value; - struct z_attachment_t attachment; + struct z_owned_bytes_t *payload; + struct z_owned_encoding_t *encoding; + struct z_owned_bytes_t *attachment; uint64_t timeout_ms; } z_get_options_t; /** @@ -704,20 +546,21 @@ typedef struct z_hello_t { struct z_id_t pid; struct z_str_array_t locators; } z_hello_t; -/** - * The wrapper type for null-terminated string values allocated by zenoh. The instances of `z_owned_str_t` - * should be released with `z_drop` macro or with `z_str_drop` function and checked to validity with - * `z_check` and `z_str_check` correspondently - */ -typedef struct z_owned_str_t { - char *_cstr; -} z_owned_str_t; -/** - * A loaned zenoh publisher. - */ -typedef struct z_publisher_t { - const struct z_owned_publisher_t *_0; -} z_publisher_t; +typedef struct ALIGN(8) z_view_slice_t { + uint8_t _0[16]; +} z_view_slice_t; +typedef struct ALIGN(8) z_view_keyexpr_t { + uint8_t _0[32]; +} z_view_keyexpr_t; +typedef struct ALIGN(8) z_timestamp_t { + uint8_t _0[24]; +} z_timestamp_t; +typedef struct ALIGN(8) z_owned_mutex_t { + uint8_t _0[24]; +} z_owned_mutex_t; +typedef struct ALIGN(8) z_loaned_publisher_t { + uint8_t _0[56]; +} z_loaned_publisher_t; /** * Represents the set of options that can be applied to the delete operation by a previously declared publisher, * whenever issued via :c:func:`z_publisher_delete`. @@ -729,30 +572,27 @@ typedef struct z_publisher_delete_options_t { * Options passed to the :c:func:`z_publisher_put` function. * * Members: - * z_encoding_t encoding: The encoding of the payload. - * z_attachment_t attachment: The attachment to attach to the publication. + * z_owned_encoding_t encoding: The encoding of the payload. + * z_owned_bytes_t attachment: The attachment to attach to the publication. */ typedef struct z_publisher_put_options_t { - struct z_encoding_t encoding; - struct z_attachment_t attachment; + struct z_owned_encoding_t *encoding; + struct z_owned_bytes_t *attachment; } z_publisher_put_options_t; -typedef struct z_pull_subscriber_t { - const struct z_owned_pull_subscriber_t *_0; -} z_pull_subscriber_t; /** * Options passed to the :c:func:`z_put` function. * * Members: - * z_encoding_t encoding: The encoding of the payload. + * z_loaned_encoding_t encoding: The encoding of the payload. * z_congestion_control_t congestion_control: The congestion control to apply when routing this message. * z_priority_t priority: The priority of this message. - * z_attachment_t attachment: The attachment to this message. + * z_loaned_bytes_t attachment: The attachment to this message. */ typedef struct z_put_options_t { - struct z_encoding_t encoding; + struct z_owned_encoding_t *encoding; enum z_congestion_control_t congestion_control; enum z_priority_t priority; - struct z_attachment_t attachment; + struct z_owned_bytes_t *attachment; } z_put_options_t; /** * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks: @@ -776,7 +616,7 @@ typedef struct z_owned_query_channel_closure_t { * A pair of closures */ typedef struct z_owned_query_channel_t { - struct z_owned_closure_owned_query_t send; + struct z_owned_closure_query_t send; struct z_owned_query_channel_closure_t recv; } z_owned_query_channel_t; /** @@ -784,13 +624,28 @@ typedef struct z_owned_query_channel_t { * sent via :c:func:`z_query_reply`. * * Members: - * z_encoding_t encoding: The encoding of the payload. - * z_attachment_t attachment: The attachment to this reply. + * z_owned_encoding_t encoding: The encoding of the payload. + * z_owned_bytes_t attachment: The attachment to this reply. */ typedef struct z_query_reply_options_t { - struct z_encoding_t encoding; - struct z_attachment_t attachment; + struct z_owned_encoding_t *encoding; + struct z_owned_bytes_t *attachment; } z_query_reply_options_t; +typedef struct ALIGN(8) z_loaned_value_t { + uint8_t _0[88]; +} z_loaned_value_t; +/** + * An owned reply to a :c:func:`z_get`. + * + * Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. + * To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. + * After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. + * + * To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. + */ +typedef struct ALIGN(8) z_owned_reply_t { + uint8_t _0[256]; +} z_owned_reply_t; /** * A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks: * - `this` is a pointer to an arbitrary state. @@ -816,24 +671,37 @@ typedef struct z_owned_reply_channel_t { struct z_owned_closure_reply_t send; struct z_owned_reply_channel_closure_t recv; } z_owned_reply_channel_t; +/** + * An owned sample. + * + * This is a read only type that can only be constructed by cloning a `z_loaned_sample_t`. + * Like all owned types, its memory must be freed by passing a mutable reference to it to `z_sample_drop`. + */ +typedef struct ALIGN(8) z_owned_sample_t { + uint8_t _0[240]; +} z_owned_sample_t; typedef struct z_owned_scouting_config_t { struct z_owned_config_t _config; unsigned long zc_timeout_ms; uint8_t zc_what; } z_owned_scouting_config_t; /** - * A loaned zenoh subscriber. - */ -typedef struct z_subscriber_t { - const struct z_owned_subscriber_t *_0; -} z_subscriber_t; -/** - * Task + * The body of a loop over a z_slice_map's key-value pairs. * - */ -typedef struct z_task_t { - size_t _0; -} z_task_t; + * `key` and `value` are loaned to the body for the duration of a single call. + * `context` is passed transparently through the iteration driver. + * + * Returning `true` is treated as `continue`. + */ +typedef bool (*z_slice_map_iter_body_t)(const struct z_loaned_slice_t *key, + const struct z_loaned_slice_t *value, + void *context); +typedef struct ALIGN(8) z_loaned_subscriber_t { + uint8_t _0[32]; +} z_loaned_subscriber_t; +typedef struct ALIGN(8) z_owned_task_t { + uint8_t _0[24]; +} z_owned_task_t; typedef struct z_task_attr_t { size_t _0; } z_task_attr_t; @@ -844,18 +712,21 @@ typedef struct z_task_attr_t { typedef struct z_time_t { uint64_t t; } z_time_t; +typedef struct ALIGN(8) z_view_str_t { + uint8_t _0[16]; +} z_view_str_t; /** * The options for `zc_liveliness_declare_token` */ -typedef struct zc_owned_liveliness_declaration_options_t { - uint8_t _inner; -} zc_owned_liveliness_declaration_options_t; +typedef struct zc_liveliness_declaration_options_t { + uint8_t _dummy; +} zc_liveliness_declaration_options_t; /** * The options for :c:func:`zc_liveliness_declare_subscriber` */ -typedef struct zc_owned_liveliness_declare_subscriber_options_t { - uint8_t _inner; -} zc_owned_liveliness_declare_subscriber_options_t; +typedef struct zc_liveliness_declare_subscriber_options_t { + uint8_t _dummy; +} zc_liveliness_declare_subscriber_options_t; /** * A liveliness token that can be used to provide the network with information about connectivity to its * declarer: when constructed, a PUT sample will be received by liveliness subscribers on intersecting key @@ -863,8 +734,8 @@ typedef struct zc_owned_liveliness_declare_subscriber_options_t { * * A DELETE on the token's key expression will be received by subscribers if the token is destroyed, or if connectivity between the subscriber and the token's creator is lost. */ -typedef struct zc_owned_liveliness_token_t { - size_t _inner[4]; +typedef struct ALIGN(8) zc_owned_liveliness_token_t { + uint8_t _0[32]; } zc_owned_liveliness_token_t; /** * The options for :c:func:`zc_liveliness_declare_subscriber` @@ -872,22 +743,6 @@ typedef struct zc_owned_liveliness_token_t { typedef struct zc_liveliness_get_options_t { uint32_t timeout_ms; } zc_liveliness_get_options_t; -/** - * An owned payload, backed by a reference counted owner. - * - * The `payload` field may be modified, and Zenoh will take the new values into account, - * however, assuming `ostart` and `olen` are the respective values of `payload.start` and - * `payload.len` when constructing the `zc_owned_payload_t payload` value was created, - * then `payload.start` MUST remain within the `[ostart, ostart + olen[` interval, and - * `payload.len` must remain within `[0, olen -(payload.start - ostart)]`. - * - * Should this invariant be broken when the payload is passed to one of zenoh's `put_owned` - * functions, then the operation will fail (but the passed value will still be consumed). - */ -typedef struct zc_owned_payload_t { - struct z_bytes_t payload; - size_t _owner[5]; -} zc_owned_payload_t; typedef struct zc_owned_shmbuf_t { size_t _0[9]; } zc_owned_shmbuf_t; @@ -937,7 +792,7 @@ typedef struct zcu_owned_closure_matching_status_t { * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ typedef struct ALIGN(8) zcu_owned_matching_listener_t { - uint64_t _0[4]; + uint8_t _0[40]; } zcu_owned_matching_listener_t; /** * An owned zenoh publication_cache. @@ -951,14 +806,14 @@ typedef struct ALIGN(8) zcu_owned_matching_listener_t { * * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ -typedef struct ze_owned_publication_cache_t { - size_t _0[1]; +typedef struct ALIGN(8) ze_owned_publication_cache_t { + uint8_t _0[96]; } ze_owned_publication_cache_t; /** * Options passed to the :c:func:`ze_declare_publication_cache` function. * * Members: - * z_keyexpr_t queryable_prefix: The prefix used for queryable + * z_loaned_keyexpr_t queryable_prefix: The prefix used for queryable * zcu_locality_t queryable_origin: The restriction for the matching queries that will be receive by this * publication cache * bool queryable_complete: the `complete` option for the queryable @@ -966,7 +821,7 @@ typedef struct ze_owned_publication_cache_t { * size_t resources_limit: The limit number of cached resources */ typedef struct ze_publication_cache_options_t { - struct z_keyexpr_t queryable_prefix; + const struct z_loaned_keyexpr_t *queryable_prefix; enum zcu_locality_t queryable_origin; bool queryable_complete; size_t history; @@ -984,8 +839,8 @@ typedef struct ze_publication_cache_options_t { * * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ -typedef struct ze_owned_querying_subscriber_t { - size_t _0[1]; +typedef struct ALIGN(8) ze_owned_querying_subscriber_t { + uint8_t _0[64]; } ze_owned_querying_subscriber_t; /** * Represents the set of options that can be applied to a querying subscriber, @@ -995,8 +850,8 @@ typedef struct ze_owned_querying_subscriber_t { * z_reliability_t reliability: The subscription reliability. * zcu_locality_t allowed_origin: The restriction for the matching publications that will be * receive by this subscriber. - * z_keyexpr_t query_selector: The selector to be used for queries. - * z_query_target_t query_target: The target to be used for queries. + * z_loaned_keyexpr_t query_selector: The selector to be used for queries. + * z_loaned_query_target_t query_target: The target to be used for queries. * z_query_consolidation_t query_consolidation: The consolidation mode to be used for queries. * zcu_reply_keyexpr_t query_accept_replies: The accepted replies for queries. * uint64_t query_timeout_ms: The timeout to be used for queries. @@ -1004,15 +859,15 @@ typedef struct ze_owned_querying_subscriber_t { typedef struct ze_querying_subscriber_options_t { enum z_reliability_t reliability; enum zcu_locality_t allowed_origin; - struct z_keyexpr_t query_selector; - enum z_query_target_t query_target; + const struct z_loaned_keyexpr_t *query_selector; + enum z_loaned_query_target_t query_target; struct z_query_consolidation_t query_consolidation; enum zcu_reply_keyexpr_t query_accept_replies; uint64_t query_timeout_ms; } ze_querying_subscriber_options_t; -typedef struct ze_querying_subscriber_t { - const struct ze_owned_querying_subscriber_t *_0; -} ze_querying_subscriber_t; +typedef struct ALIGN(8) ze_loaned_querying_subscriber_t { + uint8_t _0[64]; +} ze_loaned_querying_subscriber_t; ZENOHC_API extern const unsigned int Z_ROUTER; ZENOHC_API extern const unsigned int Z_PEER; ZENOHC_API extern const unsigned int Z_CLIENT; @@ -1028,151 +883,102 @@ ZENOHC_API extern const char *Z_CONFIG_SCOUTING_TIMEOUT_KEY; ZENOHC_API extern const char *Z_CONFIG_SCOUTING_DELAY_KEY; ZENOHC_API extern const char *Z_CONFIG_ADD_TIMESTAMP_KEY; /** - * Returns the gravestone value for `z_attachment_t`. - */ -ZENOHC_API bool z_attachment_check(const struct z_attachment_t *this_); -/** - * Returns the value associated with the key. + * Returns `true` if the payload is in a valid state. */ -ZENOHC_API struct z_bytes_t z_attachment_get(struct z_attachment_t this_, struct z_bytes_t key); +ZENOHC_API bool z_bytes_check(const struct z_owned_bytes_t *payload); /** - * Returns true if `z_attachment_t` contains no key-value pairs, false otherwise. + * Increments the payload's reference count, returning an owned version of it. */ -ZENOHC_API bool z_attachment_is_empty(struct z_attachment_t this_); +ZENOHC_API void z_bytes_clone(const struct z_loaned_bytes_t *src, struct z_owned_bytes_t *dst); /** - * Iterate over `this`'s key-value pairs, breaking if `body` returns a non-zero - * value for a key-value pair, and returning the latest return value. - * - * `context` is passed to `body` to allow stateful closures. - * - * This function takes no ownership whatsoever. + * Decodes payload into owned bytes */ ZENOHC_API -int8_t z_attachment_iterate(struct z_attachment_t this_, - z_attachment_iter_body_t body, - void *context); -/** - * Returns number of key-value pairs for `z_attachment_t`. - * - * Does so by iterating over all existing key-value pairs. - */ -ZENOHC_API size_t z_attachment_len(struct z_attachment_t this_); +z_error_t z_bytes_decode_into_bytes(const struct z_loaned_bytes_t *payload, + struct z_owned_slice_t *dst); /** - * Returns the gravestone value for `z_attachment_t`. + * Decodes payload into bytes map. */ -ZENOHC_API struct z_attachment_t z_attachment_null(void); +ZENOHC_API +z_error_t z_bytes_decode_into_bytes_map(struct z_loaned_bytes_t payload, + struct z_owned_slice_map_t *dst); /** - * Returns ``true`` if `b` is initialized. + * Decodes payload into null-terminated string. */ -ZENOHC_API bool z_bytes_check(const struct z_bytes_t *b); +ZENOHC_API +z_error_t z_bytes_decode_into_string(const struct z_loaned_bytes_t *payload, + struct z_owned_str_t *dst); /** - * Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). + * Decrements the payload's reference counter, destroying it if applicable. * - * `str == NULL` will cause this to return `z_bytes_null()` + * `this` will be reset to `z_buffer_null`, preventing UB on double-frees. */ -ZENOHC_API struct z_bytes_t z_bytes_from_str(const char *str); +ZENOHC_API void z_bytes_drop(struct z_owned_bytes_t *this_); /** - * Aliases `this` into a generic `z_attachment_t`, allowing it to be passed to corresponding APIs. + * Encodes byte sequence by aliasing. */ -ZENOHC_API struct z_attachment_t z_bytes_map_as_attachment(const struct z_owned_bytes_map_t *this_); +ZENOHC_API +void z_bytes_encode_from_bytes(struct z_owned_bytes_t *this_, + const struct z_loaned_slice_t *bytes); /** - * Returns `true` if the map is not in its gravestone state + * Encodes bytes map by copying. */ -ZENOHC_API bool z_bytes_map_check(const struct z_owned_bytes_map_t *this_); +ZENOHC_API +void z_bytes_encode_from_bytes_map(struct z_owned_bytes_t *this_, + const struct z_loaned_slice_map_t *bytes_map); /** - * Destroys the map, resetting `this` to its gravestone value. - * - * This function is double-free safe, passing a pointer to the gravestone value will have no effect. + * Encodes a null-terminated string by aliasing. */ -ZENOHC_API void z_bytes_map_drop(struct z_owned_bytes_map_t *this_); +ZENOHC_API +void z_bytes_encode_from_string(struct z_owned_bytes_t *this_, + const struct z_loaned_str_t *s); /** - * Constructs a map from the provided attachment, copying keys and values. - * - * If `this` is at gravestone value, the returned value will also be at gravestone value. + * Returns total number bytes in the payload. */ -ZENOHC_API struct z_owned_bytes_map_t z_bytes_map_from_attachment(struct z_attachment_t this_); +ZENOHC_API size_t z_bytes_len(const struct z_loaned_bytes_t *payload); /** - * Constructs a map from the provided attachment, aliasing the attachment's keys and values. - * - * If `this` is at gravestone value, the returned value will also be at gravestone value. + * Loans the payload, allowing you to call functions that only need a loan of it. */ -ZENOHC_API -struct z_owned_bytes_map_t z_bytes_map_from_attachment_aliasing(struct z_attachment_t this_); +ZENOHC_API const struct z_loaned_bytes_t *z_bytes_loan(const struct z_owned_bytes_t *payload); /** - * Returns the value associated with `key`, returning a gravestone value if: - * - `this` or `key` is in gravestone state. - * - `this` has no value associated to `key` + * The gravestone value for `z_owned_bytes_t`. */ +ZENOHC_API void z_bytes_null(struct z_owned_bytes_t *this_); +ZENOHC_API bool z_bytes_reader_check(const struct z_owned_bytes_reader_t *this_); +ZENOHC_API void z_bytes_reader_drop(struct z_owned_bytes_reader_t *this_); ZENOHC_API -struct z_bytes_t z_bytes_map_get(const struct z_owned_bytes_map_t *this_, - struct z_bytes_t key); -/** - * Associates `value` to `key` in the map, aliasing them. - * - * Note that once `key` is aliased, reinserting at the same key may alias the previous instance, or the new instance of `key`. - * - * Calling this with `NULL` or the gravestone value is undefined behaviour. - */ +const struct z_loaned_bytes_reader_t *z_bytes_reader_loan(const struct z_owned_bytes_reader_t *reader); ZENOHC_API -void z_bytes_map_insert_by_alias(const struct z_owned_bytes_map_t *this_, - struct z_bytes_t key, - struct z_bytes_t value); +struct z_loaned_bytes_reader_t *z_bytes_reader_loan_mut(struct z_owned_bytes_reader_t *reader); /** - * Associates `value` to `key` in the map, copying them to obtain ownership: `key` and `value` are not aliased past the function's return. + * Creates a reader for the specified `payload`. * - * Calling this with `NULL` or the gravestone value is undefined behaviour. + * Returns 0 in case of success, -1 if `payload` is not valid. */ ZENOHC_API -void z_bytes_map_insert_by_copy(const struct z_owned_bytes_map_t *this_, - struct z_bytes_t key, - struct z_bytes_t value); -/** - * Returns true if the map is empty, false otherwise. - */ -ZENOHC_API bool z_bytes_map_is_empty(struct z_owned_bytes_map_t *this_); +void z_bytes_reader_new(struct z_loaned_bytes_t payload, + struct z_owned_bytes_reader_t *this_); +ZENOHC_API void z_bytes_reader_null(struct z_owned_bytes_reader_t *this_); /** - * Iterates over the key-value pairs in the map. + * Reads data into specified destination. * - * `body` will be called once per pair, with `ctx` as its last argument. - * If `body` returns a non-zero value, the iteration will stop immediately and the value will be returned. - * Otherwise, this will return 0 once all pairs have been visited. - * `body` is not given ownership of the key nor value, which alias the pairs in the map. - * It is safe to keep these aliases until existing keys are modified/removed, or the map is destroyed. - * Note that this map is unordered. - * - * Calling this with `NULL` or the gravestone value is undefined behaviour. + * Will read at most `len` bytes. + * Returns number of bytes read. If return value is smaller than `len`, it means that end of the payload was reached. */ ZENOHC_API -int8_t z_bytes_map_iter(const struct z_owned_bytes_map_t *this_, - z_attachment_iter_body_t body, - void *ctx); -/** - * Returns number of key-value pairs in the map. - */ -ZENOHC_API size_t z_bytes_map_len(struct z_owned_bytes_map_t *this_); +size_t z_bytes_reader_read(struct z_loaned_bytes_reader_t *this_, + uint8_t *dest, + size_t len); /** - * Constructs a new map. - */ -ZENOHC_API struct z_owned_bytes_map_t z_bytes_map_new(void); -/** - * Constructs the gravestone value for `z_owned_bytes_map_t` - */ -ZENOHC_API struct z_owned_bytes_map_t z_bytes_map_null(void); -/** - * Deprecated in favor of `z_bytes_from_str`: Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). - * - * `str == NULL` will cause this to return `z_bytes_null()` + * Sets the `reader` position indicator for the payload to the value pointed to by offset. + * The new position is exactly offset bytes measured from the beginning of the payload if origin is SEEK_SET, + * from the current reader position if origin is SEEK_CUR, and from the end of the payload if origin is SEEK_END. + * Return ​0​ upon success, negative error code otherwise. */ ZENOHC_API -struct z_bytes_t z_bytes_new(const char *str); -/** - * Returns the gravestone value for `z_bytes_t` - */ -ZENOHC_API struct z_bytes_t z_bytes_null(void); -/** - * Constructs a `len` bytes long view starting at `start`. - */ -ZENOHC_API struct z_bytes_t z_bytes_wrap(const uint8_t *start, size_t len); +z_error_t z_bytes_reader_seek(struct z_loaned_bytes_reader_t *this_, + int64_t offset, + int origin); ZENOHC_API uint64_t z_clock_elapsed_ms(const struct z_clock_t *time); ZENOHC_API uint64_t z_clock_elapsed_s(const struct z_clock_t *time); ZENOHC_API uint64_t z_clock_elapsed_us(const struct z_clock_t *time); @@ -1183,7 +989,7 @@ ZENOHC_API struct z_clock_t z_clock_now(void); * Returns a negative value if an error occured while closing the session. * Returns the remaining reference count of the session otherwise, saturating at i8::MAX. */ -ZENOHC_API int8_t z_close(struct z_owned_session_t *session); +ZENOHC_API z_error_t z_close(struct z_owned_session_t *session); /** * Calls the closure. Calling an uninitialized closure is a no-op. */ @@ -1217,7 +1023,7 @@ ZENOHC_API struct z_owned_closure_owned_query_t z_closure_owned_query_null(void) */ ZENOHC_API void z_closure_query_call(const struct z_owned_closure_query_t *closure, - const struct z_query_t *query); + const struct z_loaned_query_t *query); /** * Drops the closure. Droping an uninitialized closure is a no-op. */ @@ -1231,7 +1037,7 @@ ZENOHC_API struct z_owned_closure_query_t z_closure_query_null(void); */ ZENOHC_API void z_closure_reply_call(const struct z_owned_closure_reply_t *closure, - struct z_owned_reply_t *sample); + const struct z_loaned_reply_t *reply); /** * Drops the closure. Droping an uninitialized closure is a no-op. */ @@ -1245,7 +1051,7 @@ ZENOHC_API struct z_owned_closure_reply_t z_closure_reply_null(void); */ ZENOHC_API void z_closure_sample_call(const struct z_owned_closure_sample_t *closure, - const struct z_sample_t *sample); + const struct z_loaned_sample_t *sample); /** * Drops the closure. Droping an uninitialized closure is a no-op. */ @@ -1268,10 +1074,16 @@ ZENOHC_API void z_closure_zid_drop(struct z_owned_closure_zid_t *closure); * Constructs a null safe-to-drop value of 'z_owned_closure_zid_t' type */ ZENOHC_API struct z_owned_closure_zid_t z_closure_zid_null(void); -ZENOHC_API int8_t z_condvar_free(struct z_condvar_t *cv); -ZENOHC_API int8_t z_condvar_init(struct z_condvar_t *cv); -ZENOHC_API int8_t z_condvar_signal(struct z_condvar_t *cv); -ZENOHC_API int8_t z_condvar_wait(struct z_condvar_t *cv, struct z_mutex_t *m); +ZENOHC_API bool z_condvar_check(const struct z_owned_condvar_t *this_); +ZENOHC_API void z_condvar_drop(struct z_owned_condvar_t *this_); +ZENOHC_API void z_condvar_init(struct z_owned_condvar_t *this_); +ZENOHC_API const struct z_loaned_condvar_t *z_condvar_loan(const struct z_owned_condvar_t *this_); +ZENOHC_API struct z_loaned_condvar_t *z_condvar_loan_mut(struct z_owned_condvar_t *this_); +ZENOHC_API void z_condvar_null(struct z_owned_condvar_t *this_); +ZENOHC_API z_error_t z_condvar_signal(const struct z_loaned_condvar_t *this_); +ZENOHC_API +z_error_t z_condvar_wait(const struct z_loaned_condvar_t *this_, + struct z_loaned_mutex_t *m); /** * Returns ``true`` if `config` is valid. */ @@ -1280,19 +1092,14 @@ ZENOHC_API bool z_config_check(const struct z_owned_config_t *config); * Constructs a default, zenoh-allocated, client mode configuration. * If `peer` is not null, it is added to the configuration as remote peer. */ -ZENOHC_API struct z_owned_config_t z_config_client(const char *const *peers, size_t n_peers); -/** - * Creates a default, zenoh-allocated, configuration. - */ -ZENOHC_API struct z_owned_config_t z_config_default(void); -/** - * Frees `config`, invalidating it for double-drop safety. - */ -ZENOHC_API void z_config_drop(struct z_owned_config_t *config); +ZENOHC_API +z_error_t z_config_client(struct z_owned_config_t *this_, + const char *const *peers, + size_t n_peers); /** - * Returns a :c:type:`z_config_t` loaned from `s`. + * Clones the config. */ -ZENOHC_API struct z_config_t z_config_loan(const struct z_owned_config_t *s); +ZENOHC_API void z_config_clone(const struct z_loaned_config_t *src, struct z_owned_config_t *dst); /** * Return a new, zenoh-allocated, empty configuration. * @@ -1306,24 +1113,37 @@ ZENOHC_API struct z_config_t z_config_loan(const struct z_owned_config_t *s); * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ ZENOHC_API -struct z_owned_config_t z_config_new(void); +void z_config_default(struct z_owned_config_t *this_); +/** + * Frees `config`, invalidating it for double-drop safety. + */ +ZENOHC_API void z_config_drop(struct z_owned_config_t *config); +/** + * Returns a :c:type:`z_loaned_config_t` loaned from `s`. + */ +ZENOHC_API const struct z_loaned_config_t *z_config_loan(const struct z_owned_config_t *this_); +/** + * Returns a :c:type:`z_loaned_config_t` loaned from `s`. + */ +ZENOHC_API struct z_loaned_config_t *z_config_loan_mut(struct z_owned_config_t *this_); /** * Constructs a null safe-to-drop value of 'z_owned_config_t' type */ -ZENOHC_API struct z_owned_config_t z_config_null(void); +ZENOHC_API void z_config_null(struct z_owned_config_t *this_); /** * Constructs a default, zenoh-allocated, peer mode configuration. */ -ZENOHC_API struct z_owned_config_t z_config_peer(void); +ZENOHC_API void z_config_peer(struct z_owned_config_t *this_); /** - * Declare a key expression. The id is returned as a :c:type:`z_keyexpr_t` with a nullptr suffix. + * Declare a key expression. The id is returned as a :c:type:`z_loaned_keyexpr_t` with a nullptr suffix. * * This numerical id will be used on the network to save bandwidth and * ease the retrieval of the concerned resource in the routing tables. */ ZENOHC_API -struct z_owned_keyexpr_t z_declare_keyexpr(struct z_session_t session, - struct z_keyexpr_t keyexpr); +z_error_t z_declare_keyexpr(struct z_owned_keyexpr_t *this_, + const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr); /** * Declares a publisher for the given key expression. * @@ -1332,7 +1152,7 @@ struct z_owned_keyexpr_t z_declare_keyexpr(struct z_session_t session, * * Parameters: * session: The zenoh session. - * keyexpr: The key expression to publish. + * key_expr: The key expression to publish. * options: additional options for the publisher. * * Returns: @@ -1360,53 +1180,16 @@ struct z_owned_keyexpr_t z_declare_keyexpr(struct z_session_t session, * z_owned_publisher_t sub = z_declare_publisher(z_loan(s), z_keyexpr(expr), &opts); */ ZENOHC_API -struct z_owned_publisher_t z_declare_publisher(struct z_session_t session, - struct z_keyexpr_t keyexpr, - const struct z_publisher_options_t *options); -/** - * Declares a pull subscriber for a given key expression. - * - * Parameters: - * session: The zenoh session. - * keyexpr: The key expression to subscribe. - * callback: The callback function that will be called each time a data matching the subscribed expression is received. - * opts: additional options for the pull subscriber. - * - * Returns: - * A :c:type:`z_owned_subscriber_t`. - * - * To check if the subscription succeeded and if the pull subscriber is still valid, - * you may use `z_pull_subscriber_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. - * - * Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. - * To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. - * After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. - * - * Example: - * Declaring a subscriber passing ``NULL`` for the options: - * - * .. code-block:: C - * - * z_owned_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(expr), callback, NULL); - * - * is equivalent to initializing and passing the default subscriber options: - * - * .. code-block:: C - * - * z_subscriber_options_t opts = z_subscriber_options_default(); - * z_owned_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(expr), callback, &opts); - */ -ZENOHC_API -struct z_owned_pull_subscriber_t z_declare_pull_subscriber(struct z_session_t session, - struct z_keyexpr_t keyexpr, - struct z_owned_closure_sample_t *callback, - const struct z_pull_subscriber_options_t *opts); +z_error_t z_declare_publisher(struct z_owned_publisher_t *this_, + const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + const struct z_publisher_options_t *options); /** * Creates a Queryable for the given key expression. * * Parameters: * session: The zenoh session. - * keyexpr: The key expression the Queryable will reply to. + * key_expr: The key expression the Queryable will reply to. * callback: The callback function that will be called each time a matching query is received. * options: Options for the queryable. * @@ -1414,16 +1197,17 @@ struct z_owned_pull_subscriber_t z_declare_pull_subscriber(struct z_session_t se * The created :c:type:`z_owned_queryable_t` or ``null`` if the creation failed. */ ZENOHC_API -struct z_owned_queryable_t z_declare_queryable(struct z_session_t session, - struct z_keyexpr_t keyexpr, - struct z_owned_closure_query_t *callback, - const struct z_queryable_options_t *options); +z_error_t z_declare_queryable(struct z_owned_queryable_t *this_, + const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct z_owned_closure_query_t *callback, + struct z_queryable_options_t *options); /** * Declare a subscriber for a given key expression. * * Parameters: * session: The zenoh session. - * keyexpr: The key expression to subscribe. + * key_expr: The key expression to subscribe. * callback: The callback function that will be called each time a data matching the subscribed expression is received. * opts: The options to be passed to describe the options to be passed to the subscriber declaration. * @@ -1452,52 +1236,54 @@ struct z_owned_queryable_t z_declare_queryable(struct z_session_t session, * z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(expr), callback, &opts); */ ZENOHC_API -struct z_owned_subscriber_t z_declare_subscriber(struct z_session_t session, - struct z_keyexpr_t keyexpr, - struct z_owned_closure_sample_t *callback, - const struct z_subscriber_options_t *opts); +z_error_t z_declare_subscriber(struct z_owned_subscriber_t *this_, + const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct z_owned_closure_sample_t *callback, + struct z_subscriber_options_t *options); /** * Delete data. * * Parameters: * session: The zenoh session. - * keyexpr: The key expression to delete. - * options: The put options. + * key_expr: The key expression to delete. + * options: The delete options. * Returns: * ``0`` in case of success, negative values in case of failure. */ ZENOHC_API -int8_t z_delete(struct z_session_t session, - struct z_keyexpr_t keyexpr, - const struct z_delete_options_t *opts); +z_error_t z_delete(const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct z_delete_options_t *options); /** * Constructs the default value for :c:type:`z_put_options_t`. */ -ZENOHC_API struct z_delete_options_t z_delete_options_default(void); -/** - * Constructs a specific :c:type:`z_encoding_t`. - */ -ZENOHC_API struct z_encoding_t z_encoding(enum z_encoding_prefix_t prefix, const char *suffix); +ZENOHC_API void z_delete_options_default(struct z_delete_options_t *this_); /** * Returns ``true`` if `encoding` is valid. */ ZENOHC_API bool z_encoding_check(const struct z_owned_encoding_t *encoding); /** - * Constructs a default :c:type:`z_encoding_t`. + * Constructs a default :c:type:`z_loaned_encoding_t`. */ -ZENOHC_API struct z_encoding_t z_encoding_default(void); +ZENOHC_API const struct z_loaned_encoding_t *z_encoding_default(void); /** * Frees `encoding`, invalidating it for double-drop safety. */ ZENOHC_API void z_encoding_drop(struct z_owned_encoding_t *encoding); /** - * Returns a :c:type:`z_encoding_t` loaned from `encoding`. + * Constructs a specific :c:type:`z_loaned_encoding_t`. */ -ZENOHC_API struct z_encoding_t z_encoding_loan(const struct z_owned_encoding_t *encoding); +ZENOHC_API int8_t z_encoding_from_str(struct z_owned_encoding_t *encoding, const char *s); +/** + * Returns a :c:type:`z_loaned_encoding_t` loaned from `encoding`. + */ +ZENOHC_API +const struct z_loaned_encoding_t *z_encoding_loan(const struct z_owned_encoding_t *encoding); /** * Constructs a null safe-to-drop value of 'z_owned_encoding_t' type */ -ZENOHC_API struct z_owned_encoding_t z_encoding_null(void); +ZENOHC_API void z_encoding_null(struct z_owned_encoding_t *encoding); /** * Query data from the matching queryables in the system. * Replies are provided through a callback function. @@ -1506,7 +1292,7 @@ ZENOHC_API struct z_owned_encoding_t z_encoding_null(void); * * Parameters: * session: The zenoh session. - * keyexpr: The key expression matching resources to query. + * key_expr: The key expression matching resources to query. * parameters: The query's parameters, similar to a url's query segment. * callback: The callback function that will be called on reception of replies for this query. * Note that the `reply` parameter of the callback is passed by mutable reference, @@ -1515,12 +1301,12 @@ ZENOHC_API struct z_owned_encoding_t z_encoding_null(void); * options: additional options for the get. */ ZENOHC_API -int8_t z_get(struct z_session_t session, - struct z_keyexpr_t keyexpr, - const char *parameters, - struct z_owned_closure_reply_t *callback, - const struct z_get_options_t *options); -ZENOHC_API struct z_get_options_t z_get_options_default(void); +z_error_t z_get(const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + const char *parameters, + struct z_owned_closure_reply_t *callback, + struct z_get_options_t *options); +ZENOHC_API void z_get_options_default(struct z_get_options_t *this_); /** * Returns ``true`` if `hello` is valid. */ @@ -1532,11 +1318,11 @@ ZENOHC_API void z_hello_drop(struct z_owned_hello_t *hello); /** * Returns a :c:type:`z_hello_t` loaned from :c:type:`z_owned_hello_t`. */ -ZENOHC_API struct z_hello_t z_hello_loan(const struct z_owned_hello_t *hello); +ZENOHC_API const struct z_hello_t *z_hello_loan(const struct z_owned_hello_t *hello); /** * Constructs a gravestone value for hello, useful to steal one from a callback */ -ZENOHC_API struct z_owned_hello_t z_hello_null(void); +ZENOHC_API void z_hello_null(struct z_owned_hello_t *this_); /** * Fetches the Zenoh IDs of all connected peers. * @@ -1546,8 +1332,8 @@ ZENOHC_API struct z_owned_hello_t z_hello_null(void); * Retuns 0 on success, negative values on failure */ ZENOHC_API -int8_t z_info_peers_zid(struct z_session_t session, - struct z_owned_closure_zid_t *callback); +z_error_t z_info_peers_zid(struct z_loaned_session_t session, + struct z_owned_closure_zid_t *callback); /** * Fetches the Zenoh IDs of all connected routers. * @@ -1557,8 +1343,8 @@ int8_t z_info_peers_zid(struct z_session_t session, * Retuns 0 on success, negative values on failure. */ ZENOHC_API -int8_t z_info_routers_zid(struct z_session_t session, - struct z_owned_closure_zid_t *callback); +z_error_t z_info_routers_zid(struct z_loaned_session_t session, + struct z_owned_closure_zid_t *callback); /** * Returns the local Zenoh ID. * @@ -1566,26 +1352,13 @@ int8_t z_info_routers_zid(struct z_session_t session, * In other words, this function returning an array of 16 zeros means you failed * to pass it a valid session. */ -ZENOHC_API struct z_id_t z_info_zid(struct z_session_t session); -/** - * Constructs a :c:type:`z_keyexpr_t` departing from a string. - * It is a loaned key expression that aliases `name`. - */ -ZENOHC_API struct z_keyexpr_t z_keyexpr(const char *name); +ZENOHC_API struct z_id_t z_info_zid(struct z_loaned_session_t session); /** * Returns the key expression's internal string by aliasing it. * * Currently exclusive to zenoh-c */ -ZENOHC_API struct z_bytes_t z_keyexpr_as_bytes(struct z_keyexpr_t keyexpr); -/** - * Constructs a :c:type:`z_keyexpr_t` departing from a string. - * It is a loaned key expression that aliases `name`. - * The string is canonized in-place before being passed to keyexpr. - * May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). - */ -ZENOHC_API -struct z_keyexpr_t z_keyexpr_autocanonize(char *name); +ZENOHC_API void z_keyexpr_as_bytes(const struct z_loaned_keyexpr_t *ke, struct z_view_slice_t *b); /** * Canonizes the passed string in place, possibly shortening it by modifying `len`. * @@ -1596,8 +1369,8 @@ struct z_keyexpr_t z_keyexpr_autocanonize(char *name); * May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). */ ZENOHC_API -int8_t z_keyexpr_canonize(char *start, - size_t *len); +z_error_t z_keyexpr_canonize(char *start, + size_t *len); /** * Canonizes the passed string in place, possibly shortening it by placing a new null-terminator. * @@ -1608,7 +1381,7 @@ int8_t z_keyexpr_canonize(char *start, * May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). */ ZENOHC_API -int8_t z_keyexpr_canonize_null_terminated(char *start); +z_error_t z_keyexpr_canonize_null_terminated(char *start); /** * Returns ``true`` if `keyexpr` is valid. */ @@ -1623,81 +1396,76 @@ ZENOHC_API bool z_keyexpr_check(const struct z_owned_keyexpr_t *keyexpr); * as this would extremely likely cause bugs. */ ZENOHC_API -struct z_owned_keyexpr_t z_keyexpr_concat(struct z_keyexpr_t left, - const char *right_start, - size_t right_len); +z_error_t z_keyexpr_concat(struct z_owned_keyexpr_t *this_, + const struct z_loaned_keyexpr_t *left, + const char *right_start, + size_t right_len); /** * Frees `keyexpr` and invalidates it for double-drop safety. */ ZENOHC_API void z_keyexpr_drop(struct z_owned_keyexpr_t *keyexpr); /** - * Returns ``0`` if both ``left`` and ``right`` are equal. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. + * Returns ``0`` if both ``left`` and ``right`` are equal. */ ZENOHC_API -int8_t z_keyexpr_equals(struct z_keyexpr_t left, - struct z_keyexpr_t right); +bool z_keyexpr_equals(const struct z_loaned_keyexpr_t *left, + const struct z_loaned_keyexpr_t *right); /** * Returns ``0`` if ``left`` includes ``right``, i.e. the set defined by ``left`` contains every key belonging to the set - * defined by ``right``. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. + * defined by ``right``. */ ZENOHC_API -int8_t z_keyexpr_includes(struct z_keyexpr_t left, - struct z_keyexpr_t right); +bool z_keyexpr_includes(const struct z_loaned_keyexpr_t *left, + const struct z_loaned_keyexpr_t *right); /** * Returns ``0`` if the keyexprs intersect, i.e. there exists at least one key which is contained in both of the - * sets defined by ``left`` and ``right``. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. + * sets defined by ``left`` and ``right``. */ ZENOHC_API -int8_t z_keyexpr_intersects(struct z_keyexpr_t left, - struct z_keyexpr_t right); +bool z_keyexpr_intersects(const struct z_loaned_keyexpr_t *left, + const struct z_loaned_keyexpr_t *right); /** * Returns ``0`` if the passed string is a valid (and canon) key expression. * Otherwise returns error value */ -ZENOHC_API int8_t z_keyexpr_is_canon(const char *start, size_t len); -/** - * Returns ``true`` if `keyexpr` is initialized. - */ -ZENOHC_API bool z_keyexpr_is_initialized(const struct z_keyexpr_t *keyexpr); +ZENOHC_API z_error_t z_keyexpr_is_canon(const char *start, size_t len); /** * Performs path-joining (automatically inserting) and returns the result as a `z_owned_keyexpr_t`. * In case of error, the return value will be set to its invalidated state. */ ZENOHC_API -struct z_owned_keyexpr_t z_keyexpr_join(struct z_keyexpr_t left, - struct z_keyexpr_t right); +z_error_t z_keyexpr_join(struct z_owned_keyexpr_t *this_, + const struct z_loaned_keyexpr_t *left, + const struct z_loaned_keyexpr_t *right); /** - * Returns a :c:type:`z_keyexpr_t` loaned from :c:type:`z_owned_keyexpr_t`. + * Returns a :c:type:`z_loaned_keyexpr_t` loaned from :c:type:`z_owned_keyexpr_t`. */ -ZENOHC_API struct z_keyexpr_t z_keyexpr_loan(const struct z_owned_keyexpr_t *keyexpr); +ZENOHC_API +const struct z_loaned_keyexpr_t *z_keyexpr_loan(const struct z_owned_keyexpr_t *key_expr); /** - * Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string. + * Constructs a :c:type:`z_owned_keyexpr_t` departing from a string, copying the passed string. */ -ZENOHC_API struct z_owned_keyexpr_t z_keyexpr_new(const char *name); +ZENOHC_API z_error_t z_keyexpr_new(const char *name, struct z_owned_keyexpr_t *this_); /** - * Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string. The copied string is canonized. + * Constructs a :c:type:`z_owned_keyexpr_t` departing from a string, copying the passed string. The copied string is canonized. */ ZENOHC_API -struct z_owned_keyexpr_t z_keyexpr_new_autocanonize(const char *name); +z_error_t z_keyexpr_new_autocanonize(const char *name, + struct z_owned_keyexpr_t *this_); /** * Constructs a null safe-to-drop value of 'z_owned_keyexpr_t' type */ -ZENOHC_API struct z_owned_keyexpr_t z_keyexpr_null(void); +ZENOHC_API void z_keyexpr_null(struct z_owned_keyexpr_t *this_); /** * Returns the relation between `left` and `right` from `left`'s point of view. * * Note that this is slower than `z_keyexpr_intersects` and `keyexpr_includes`, so you should favor these methods for most applications. */ ZENOHC_API -enum z_keyexpr_intersection_level_t z_keyexpr_relation_to(struct z_keyexpr_t left, - struct z_keyexpr_t right); -/** - * Constructs a null-terminated string departing from a :c:type:`z_keyexpr_t`. - * The user is responsible of droping the returned string using `z_drop` - */ -ZENOHC_API struct z_owned_str_t z_keyexpr_to_string(struct z_keyexpr_t keyexpr); +enum z_keyexpr_intersection_level_t z_keyexpr_relation_to(const struct z_loaned_keyexpr_t *left, + const struct z_loaned_keyexpr_t *right); /** - * Constructs a :c:type:`z_keyexpr_t` departing from a string without checking any of `z_keyexpr_t`'s assertions: + * Constructs a :c:type:`z_loaned_keyexpr_t` by aliasing a string without checking any of `z_loaned_keyexpr_t`'s assertions: * * - `name` MUST be valid UTF8. * - `name` MUST follow the Key Expression specification, ie: @@ -1709,21 +1477,61 @@ ZENOHC_API struct z_owned_str_t z_keyexpr_to_string(struct z_keyexpr_t keyexpr); * It is a loaned key expression that aliases `name`. */ ZENOHC_API -struct z_keyexpr_t z_keyexpr_unchecked(const char *name); -ZENOHC_API int8_t z_mutex_free(struct z_mutex_t *m); -ZENOHC_API int8_t z_mutex_init(struct z_mutex_t *m); -ZENOHC_API int8_t z_mutex_lock(struct z_mutex_t *m); -ZENOHC_API int8_t z_mutex_try_lock(struct z_mutex_t *m); -ZENOHC_API int8_t z_mutex_unlock(struct z_mutex_t *m); +void z_keyexpr_unchecked(struct z_view_keyexpr_t *this_, + const char *name); +/** + * Returns the read position indicator. + * Returns read position indicator on success or -1L if failure occurs. + */ +ZENOHC_API int64_t z_loaned_bytes_reader_tell(struct z_loaned_bytes_reader_t *this_); +/** + * Constructs a null-terminated string departing from a :c:type:`z_loaned_keyexpr_t`. + * The user is responsible of droping the returned string using `z_drop` + */ +ZENOHC_API +void z_loaned_keyexpr_to_string(const struct z_loaned_keyexpr_t *ke, + struct z_owned_str_t *s); +ZENOHC_API z_error_t z_loaned_mutex_try_lock(struct z_loaned_mutex_t *this_); +/** + * Create a default :c:type:`z_loaned_query_target_t`. + */ +ZENOHC_API enum z_loaned_query_target_t z_loaned_query_target_default(void); +/** + * The samples timestamp + * + * Returns true if Sample contains timestamp, false otherwise. In the latter case the timestamp_out value is not altered. + */ +ZENOHC_API +bool z_loaned_sample_timestamp(const struct z_loaned_sample_t *sample, + struct z_timestamp_t *timestamp_out); +ZENOHC_API bool z_mutex_check(const struct z_owned_mutex_t *this_); +ZENOHC_API void z_mutex_drop(struct z_owned_mutex_t *this_); +ZENOHC_API z_error_t z_mutex_init(struct z_owned_mutex_t *this_); +ZENOHC_API struct z_loaned_mutex_t *z_mutex_loan_mut(struct z_owned_mutex_t *this_); +ZENOHC_API z_error_t z_mutex_lock(struct z_loaned_mutex_t *this_); +ZENOHC_API void z_mutex_null(struct z_owned_mutex_t *this_); +ZENOHC_API z_error_t z_mutex_unlock(struct z_loaned_mutex_t *this_); /** * Opens a zenoh session. Should the session opening fail, `z_check` ing the returned value will return `false`. + * Config value is always consumed upon function return. */ ZENOHC_API -struct z_owned_session_t z_open(struct z_owned_config_t *config); +z_error_t z_open(struct z_owned_session_t *this_, + struct z_owned_config_t *config); +/** + * Opens a zenoh session. Should the session opening fail, `z_check` ing the returned value will return `false`. + */ +ZENOHC_API +struct z_owned_session_t z_open_with_shm_clients(struct z_owned_config_t *config, + z_shared_memory_client_storage_t shm_clients); +/** + * Returns ``true`` if `this` is initialized. + */ +ZENOHC_API bool z_owned_slice_check(const struct z_owned_slice_t *this_); /** * Returns ``true`` if `pub` is valid. */ -ZENOHC_API bool z_publisher_check(const struct z_owned_publisher_t *pbl); +ZENOHC_API bool z_publisher_check(const struct z_owned_publisher_t *this_); /** * Sends a `DELETE` message onto the publisher's key expression. * @@ -1731,122 +1539,93 @@ ZENOHC_API bool z_publisher_check(const struct z_owned_publisher_t *pbl); * ``0`` in case of success, ``1`` in case of failure. */ ZENOHC_API -int8_t z_publisher_delete(struct z_publisher_t publisher, - const struct z_publisher_delete_options_t *_options); +z_error_t z_publisher_delete(const struct z_loaned_publisher_t *publisher, + struct z_publisher_delete_options_t _options); /** * Constructs the default values for the delete operation via a publisher entity. * * Returns: * Returns the constructed :c:type:`z_publisher_delete_options_t`. */ -ZENOHC_API struct z_publisher_delete_options_t z_publisher_delete_options_default(void); +ZENOHC_API void z_publisher_delete_options_default(struct z_publisher_delete_options_t *this_); /** * Returns the key expression of the publisher */ -ZENOHC_API struct z_owned_keyexpr_t z_publisher_keyexpr(struct z_publisher_t publisher); +ZENOHC_API +const struct z_loaned_keyexpr_t *z_publisher_keyexpr(const struct z_loaned_publisher_t *publisher); /** - * Returns a :c:type:`z_publisher_t` loaned from `p`. + * Returns a :c:type:`z_loaned_publisher_t` loaned from `p`. */ -ZENOHC_API struct z_publisher_t z_publisher_loan(const struct z_owned_publisher_t *p); +ZENOHC_API +const struct z_loaned_publisher_t *z_publisher_loan(const struct z_owned_publisher_t *this_); /** * Constructs a null safe-to-drop value of 'z_owned_publisher_t' type */ -ZENOHC_API struct z_owned_publisher_t z_publisher_null(void); +ZENOHC_API void z_publisher_null(struct z_owned_publisher_t *this_); /** * Constructs the default value for :c:type:`z_publisher_options_t`. */ -ZENOHC_API struct z_publisher_options_t z_publisher_options_default(void); +ZENOHC_API void z_publisher_options_default(struct z_publisher_options_t *this_); /** - * Sends a `PUT` message onto the publisher's key expression. + * Sends a `PUT` message onto the publisher's key expression, transfering the payload ownership. + * + * This is avoids copies when transfering data that was either: + * - `z_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher + * - constructed from a `zc_owned_shmbuf_t` * - * The payload's encoding can be sepcified through the options. + * The payload and all owned options fields are consumed upon function return. * * Parameters: * session: The zenoh session. * payload: The value to put. - * len: The length of the value to put. * options: The publisher put options. * Returns: * ``0`` in case of success, negative values in case of failure. */ ZENOHC_API -int8_t z_publisher_put(struct z_publisher_t publisher, - const uint8_t *payload, - size_t len, - const struct z_publisher_put_options_t *options); +z_error_t z_publisher_put(const struct z_loaned_publisher_t *publisher, + struct z_owned_bytes_t *payload, + struct z_publisher_put_options_t *options); /** * Constructs the default value for :c:type:`z_publisher_put_options_t`. */ -ZENOHC_API struct z_publisher_put_options_t z_publisher_put_options_default(void); +ZENOHC_API void z_publisher_put_options_default(struct z_publisher_put_options_t *this_); /** - * Returns ``true`` if `sub` is valid. - */ -ZENOHC_API bool z_pull_subscriber_check(const struct z_owned_pull_subscriber_t *sub); -/** - * Returns ``true`` if `sub` is valid. - */ -ZENOHC_API -struct z_pull_subscriber_t z_pull_subscriber_loan(const struct z_owned_pull_subscriber_t *sub); -/** - * Constructs a null safe-to-drop value of 'z_owned_pull_subscriber_t' type - */ -ZENOHC_API struct z_owned_pull_subscriber_t z_pull_subscriber_null(void); -/** - * Constructs the default value for :c:type:`z_pull_subscriber_options_t`. - */ -ZENOHC_API struct z_pull_subscriber_options_t z_pull_subscriber_options_default(void); -/** - * Put data. + * Put data, transfering its ownership. * - * The payload's encoding can be sepcified through the options. + * + * The payload's encoding and attachment can be sepcified through the options. These values are consumed upon function + * return. * * Parameters: * session: The zenoh session. - * keyexpr: The key expression to put. - * payload: The value to put. - * len: The length of the value to put. + * key_expr: The key expression to put. + * payload: The value to put (consumed upon function return). * options: The put options. * Returns: - * ``0`` in case of success, negative values in case of failure. + * ``0`` in case of success, negative error values in case of failure. */ ZENOHC_API -int8_t z_put(struct z_session_t session, - struct z_keyexpr_t keyexpr, - const uint8_t *payload, - size_t len, - const struct z_put_options_t *opts); +z_error_t z_put(const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct z_owned_bytes_t *payload, + struct z_put_options_t *options); /** * Constructs the default value for :c:type:`z_put_options_t`. */ -ZENOHC_API struct z_put_options_t z_put_options_default(void); -/** - * Returns default qos settings. - */ -ZENOHC_API struct z_qos_t z_qos_default(void); -/** - * Returns message congestion control. - */ -ZENOHC_API enum z_congestion_control_t z_qos_get_congestion_control(struct z_qos_t qos); -/** - * Returns message express flag. If set to true, the message is not batched to reduce the latency. - */ -ZENOHC_API bool z_qos_get_express(struct z_qos_t qos); -/** - * Returns message priority. - */ -ZENOHC_API enum z_priority_t z_qos_get_priority(struct z_qos_t qos); +ZENOHC_API void z_put_options_default(struct z_put_options_t *this_); /** - * Returns the attachment to the query by aliasing. + * Gets the attachment to the query by aliasing. * - * `z_check(return_value) == false` if there was no attachment to the query. + * Returns NULL if query does not contain an attachment. */ -ZENOHC_API struct z_attachment_t z_query_attachment(const struct z_query_t *query); +ZENOHC_API const struct z_loaned_bytes_t *z_query_attachment(const struct z_loaned_query_t *query); /** * Calls the closure. Calling an uninitialized closure is a no-op. */ ZENOHC_API bool z_query_channel_closure_call(const struct z_owned_query_channel_closure_t *closure, - struct z_owned_query_t *sample); + struct z_owned_query_t *query); /** * Drops the closure. Droping an uninitialized closure is a no-op. */ @@ -1866,14 +1645,15 @@ ZENOHC_API struct z_owned_query_channel_t z_query_channel_null(void); * This function may not be called with the null pointer, but can be called with the gravestone value. */ ZENOHC_API -bool z_query_check(const struct z_owned_query_t *this_); +bool z_query_check(const struct z_owned_query_t *query); /** * Clones the query, allowing to keep it in an "open" state past the callback's return. * * This operation is infallible, but may return a gravestone value if `query` itself was a gravestone value (which cannot be the case in a callback). */ ZENOHC_API -struct z_owned_query_t z_query_clone(const struct z_query_t *query); +void z_query_clone(const struct z_loaned_query_t *this_, + struct z_owned_query_t *dst); /** * Automatic query consolidation strategy selection. * @@ -1908,26 +1688,31 @@ ZENOHC_API struct z_query_consolidation_t z_query_consolidation_none(void); */ ZENOHC_API void z_query_drop(struct z_owned_query_t *this_); +/** + * Checks if query contains a payload value. + */ +ZENOHC_API bool z_query_has_value(const struct z_loaned_query_t *query); /** * Get a query's key by aliasing it. */ -ZENOHC_API struct z_keyexpr_t z_query_keyexpr(const struct z_query_t *query); +ZENOHC_API const struct z_loaned_keyexpr_t *z_query_keyexpr(const struct z_loaned_query_t *query); /** * Aliases the query. * * This function may not be called with the null pointer, but can be called with the gravestone value. */ ZENOHC_API -struct z_query_t z_query_loan(const struct z_owned_query_t *this_); +const struct z_loaned_query_t *z_query_loan(const struct z_owned_query_t *this_); /** * The gravestone value of `z_owned_query_t`. */ -ZENOHC_API struct z_owned_query_t z_query_null(void); +ZENOHC_API void z_query_null(struct z_owned_query_t *this_); /** * Get a query's `value selector `_ by aliasing it. */ ZENOHC_API -struct z_bytes_t z_query_parameters(const struct z_query_t *query); +void z_query_parameters(const struct z_loaned_query_t *query, + struct z_view_slice_t *parameters); /** * Send a reply to a query. * @@ -1938,32 +1723,29 @@ struct z_bytes_t z_query_parameters(const struct z_query_t *query); * * Parameters: * query: The query to reply to. - * key: The key of this reply. + * key_expr: The key of this reply. * payload: The value of this reply. - * len: The length of the value of this reply. * options: The options of this reply. + * + * The payload and all owned options fields are consumed upon function return. */ ZENOHC_API -int8_t z_query_reply(const struct z_query_t *query, - struct z_keyexpr_t key, - const uint8_t *payload, - size_t len, - const struct z_query_reply_options_t *options); +z_error_t z_query_reply(struct z_loaned_query_t query, + struct z_loaned_keyexpr_t key_expr, + struct z_owned_bytes_t *payload, + struct z_query_reply_options_t *options); /** * Constructs the default value for :c:type:`z_query_reply_options_t`. */ -ZENOHC_API struct z_query_reply_options_t z_query_reply_options_default(void); -/** - * Create a default :c:type:`z_query_target_t`. - */ -ZENOHC_API enum z_query_target_t z_query_target_default(void); +ZENOHC_API void z_query_reply_options_default(struct z_query_reply_options_t *this_); /** - * Get a query's `payload value `_ by aliasing it. + * Gets a query's `payload value `_ by aliasing it. * * **WARNING: This API has been marked as unstable: it works as advertised, but it may change in a future release.** + * Before calling this funciton, the user must ensure that `z_query_has_value` returns true. */ ZENOHC_API -struct z_value_t z_query_value(const struct z_query_t *query); +const struct z_loaned_value_t *z_query_value(const struct z_loaned_query_t *query); /** * Returns ``true`` if `qable` is valid. */ @@ -1971,11 +1753,11 @@ ZENOHC_API bool z_queryable_check(const struct z_owned_queryable_t *qable); /** * Constructs a null safe-to-drop value of 'z_owned_queryable_t' type */ -ZENOHC_API struct z_owned_queryable_t z_queryable_null(void); +ZENOHC_API void z_queryable_null(struct z_owned_queryable_t *this_); /** * Constructs the default value for :c:type:`z_query_reply_options_t`. */ -ZENOHC_API struct z_queryable_options_t z_queryable_options_default(void); +ZENOHC_API void z_queryable_options_default(struct z_queryable_options_t *this_); ZENOHC_API void z_random_fill(void *buf, size_t len); ZENOHC_API uint16_t z_random_u16(void); ZENOHC_API uint32_t z_random_u32(void); @@ -1986,7 +1768,7 @@ ZENOHC_API uint8_t z_random_u8(void); */ ZENOHC_API bool z_reply_channel_closure_call(const struct z_owned_reply_channel_closure_t *closure, - struct z_owned_reply_t *sample); + struct z_owned_reply_t *reply); /** * Drops the closure. Droping an uninitialized closure is a no-op. */ @@ -2001,27 +1783,29 @@ ZENOHC_API void z_reply_channel_drop(struct z_owned_reply_channel_t *channel); */ ZENOHC_API struct z_owned_reply_channel_t z_reply_channel_null(void); /** - * Returns ``true`` if `reply_data` is valid. + * Returns ``true`` if `reply` is valid. */ -ZENOHC_API bool z_reply_check(const struct z_owned_reply_t *reply_data); +ZENOHC_API bool z_reply_check(const struct z_owned_reply_t *this_); +ZENOHC_API void z_reply_clone(struct z_owned_reply_t *this_, const struct z_loaned_reply_t *reply); /** - * Frees `reply_data`, invalidating it for double-drop safety. + * Frees `reply`, invalidating it for double-drop safety. */ -ZENOHC_API void z_reply_drop(struct z_owned_reply_t *reply_data); +ZENOHC_API void z_reply_drop(struct z_owned_reply_t *this_); /** * Yields the contents of the reply by asserting it indicates a failure. * - * You should always make sure that :c:func:`z_reply_is_ok` returns ``false`` before calling this function. + * Returns null if reply does not contain a error (i. e. if :c:func:`z_reply_is_ok` returns ``true``). */ ZENOHC_API -struct z_value_t z_reply_err(const struct z_owned_reply_t *reply); +const struct z_loaned_value_t *z_reply_err(const struct z_loaned_reply_t *reply); /** * Returns ``true`` if the queryable answered with an OK, which allows this value to be treated as a sample. * * If this returns ``false``, you should use :c:func:`z_check` before trying to use :c:func:`z_reply_err` if you want to process the error that may be here. */ ZENOHC_API -bool z_reply_is_ok(const struct z_owned_reply_t *reply); +bool z_reply_is_ok(const struct z_loaned_reply_t *reply); +ZENOHC_API const struct z_loaned_reply_t *z_reply_loan(struct z_owned_reply_t *this_); /** * Returns an invalidated :c:type:`z_owned_reply_t`. * @@ -2031,14 +1815,71 @@ bool z_reply_is_ok(const struct z_owned_reply_t *reply); * - overwrite the pointee with this function's return value, * - you are now responsible for dropping your copy of the reply. */ -ZENOHC_API struct z_owned_reply_t z_reply_null(void); +ZENOHC_API void z_reply_null(struct z_owned_reply_t *this_); /** * Yields the contents of the reply by asserting it indicates a success. * - * You should always make sure that :c:func:`z_reply_is_ok` returns ``true`` before calling this function. + * Returns null if reply does not contains a sample (i. e. if :c:func:`z_reply_is_ok` returns ``false``). + */ +ZENOHC_API +const struct z_loaned_sample_t *z_reply_ok(const struct z_loaned_reply_t *reply); +/** + * The qos with which the sample was received. + * TODO: split to methods (priority, congestion_control, express) + * Gets sample's attachment. + * + * Returns NULL if sample does not contain an attachement. */ ZENOHC_API -struct z_sample_t z_reply_ok(const struct z_owned_reply_t *reply); +const struct z_loaned_bytes_t *z_sample_attachment(const struct z_loaned_sample_t *sample); +/** + * Returns `true` if `sample` is valid. + * + * Note that there exist no fallinle constructors for `z_owned_sample_t`, so validity is always guaranteed + * unless the value has been dropped already. + */ +ZENOHC_API +bool z_sample_check(const struct z_owned_sample_t *sample); +/** + * Clone a sample in the cheapest way available. + */ +ZENOHC_API void z_sample_clone(const struct z_loaned_sample_t *src, struct z_owned_sample_t *dst); +ZENOHC_API +enum z_congestion_control_t z_sample_congestion_control(const struct z_loaned_sample_t *sample); +/** + * Destroy the sample. + */ +ZENOHC_API void z_sample_drop(struct z_owned_sample_t *sample); +/** + * The encoding of the payload. + */ +ZENOHC_API +const struct z_loaned_encoding_t *z_sample_encoding(const struct z_loaned_sample_t *sample); +ZENOHC_API bool z_sample_express(const struct z_loaned_sample_t *sample); +/** + * The Key Expression of the sample. + * + * `sample` is aliased by its return value. + */ +ZENOHC_API +const struct z_loaned_keyexpr_t *z_sample_keyexpr(const struct z_loaned_sample_t *sample); +/** + * The sample's kind (put or delete). + */ +ZENOHC_API enum z_sample_kind_t z_sample_kind(const struct z_loaned_sample_t *sample); +/** + * Borrow the sample, allowing calling its accessor methods. + * + * Calling this function using a dropped sample is undefined behaviour. + */ +ZENOHC_API const struct z_loaned_sample_t *z_sample_loan(const struct z_owned_sample_t *sample); +ZENOHC_API void z_sample_null(struct z_owned_sample_t *sample); +/** + * The sample's data, the return value aliases the sample. + * + */ +ZENOHC_API const struct z_loaned_bytes_t *z_sample_payload(const struct z_loaned_sample_t *sample); +ZENOHC_API enum z_priority_t z_sample_priority(const struct z_loaned_sample_t *sample); /** * Scout for routers and/or peers. * @@ -2050,36 +1891,124 @@ struct z_sample_t z_reply_ok(const struct z_owned_reply_t *reply); * Returns 0 if successful, negative values upon failure. */ ZENOHC_API -int8_t z_scout(struct z_owned_scouting_config_t *config, - struct z_owned_closure_hello_t *callback); +z_error_t z_scout(struct z_owned_scouting_config_t *config, + struct z_owned_closure_hello_t *callback); ZENOHC_API bool z_scouting_config_check(const struct z_owned_scouting_config_t *config); -ZENOHC_API struct z_owned_scouting_config_t z_scouting_config_default(void); +ZENOHC_API void z_scouting_config_default(struct z_owned_scouting_config_t *this_); ZENOHC_API void z_scouting_config_drop(struct z_owned_scouting_config_t *config); -ZENOHC_API struct z_owned_scouting_config_t z_scouting_config_from(struct z_config_t config); -ZENOHC_API struct z_owned_scouting_config_t z_scouting_config_null(void); +ZENOHC_API +void z_scouting_config_from(struct z_owned_scouting_config_t *this_, + const struct z_loaned_config_t *config); +ZENOHC_API void z_scouting_config_null(struct z_owned_scouting_config_t *this_); /** * Returns ``true`` if `session` is valid. */ -ZENOHC_API bool z_session_check(const struct z_owned_session_t *session); +ZENOHC_API bool z_session_check(const struct z_owned_session_t *this_); /** - * Returns a :c:type:`z_session_t` loaned from `s`. + * Returns a :c:type:`z_loaned_session_t` loaned from `s`. * * This handle doesn't increase the refcount of the session, but does allow to do so with `zc_session_rcinc`. * * # Safety - * The returned `z_session_t` aliases `z_owned_session_t`'s internal allocation, + * The returned `z_loaned_session_t` aliases `z_owned_session_t`'s internal allocation, * attempting to use it after all owned handles to the session (including publishers, queryables and subscribers) * have been destroyed is UB (likely SEGFAULT) */ ZENOHC_API -struct z_session_t z_session_loan(const struct z_owned_session_t *s); +const struct z_loaned_session_t *z_session_loan(const struct z_owned_session_t *this_); /** * Constructs a null safe-to-drop value of 'z_owned_session_t' type */ -ZENOHC_API struct z_owned_session_t z_session_null(void); +ZENOHC_API void z_session_null(struct z_owned_session_t *this_); ZENOHC_API int8_t z_sleep_ms(size_t time); ZENOHC_API int8_t z_sleep_s(size_t time); ZENOHC_API int8_t z_sleep_us(size_t time); +ZENOHC_API void z_slice_clone(const struct z_loaned_slice_t *this_, struct z_owned_slice_t *dst); +ZENOHC_API const uint8_t *z_slice_data(const struct z_loaned_slice_t *this_); +/** + * Frees `this` and invalidates it for double-drop safety. + */ +ZENOHC_API void z_slice_drop(struct z_owned_slice_t *this_); +/** + * Returns an empty `z_owned_slice_t` + */ +ZENOHC_API void z_slice_empty(struct z_owned_slice_t *this_); +/** + * Copies a string into `z_owned_slice_t` using `strlen` (this should therefore not be used with untrusted inputs). + * + * Calling this with `str == NULL` is equivalent to `z_slice_null`. + */ +ZENOHC_API +void z_slice_from_str(struct z_owned_slice_t *this_, + const char *str); +ZENOHC_API size_t z_slice_len(const struct z_loaned_slice_t *this_); +ZENOHC_API const struct z_loaned_slice_t *z_slice_loan(const struct z_owned_slice_t *this_); +/** + * Returns `true` if the map is not in its gravestone state + */ +ZENOHC_API bool z_slice_map_check(const struct z_owned_slice_map_t *map); +/** + * Destroys the map, resetting `this` to its gravestone value. + * + * This function is double-free safe, passing a pointer to the gravestone value will have no effect. + */ +ZENOHC_API void z_slice_map_drop(struct z_owned_slice_map_t *this_); +/** + * Returns the value associated with `key`. + * + * Will return NULL if the key is not present in the map. + */ +ZENOHC_API +const struct z_loaned_slice_t *z_slice_map_get(const struct z_loaned_slice_map_t *this_, + const struct z_loaned_slice_t *key); +/** + * Associates `value` to `key` in the map, aliasing them. + * + * Note that once `key` is aliased, reinserting at the same key may alias the previous instance, or the new instance of `key`. + * + * Returns 1 if there was already an entry associated with the key, 0 otherwise. + */ +ZENOHC_API +z_error_t z_slice_map_insert_by_alias(struct z_loaned_slice_map_t *this_, + const struct z_loaned_slice_t *key, + const struct z_loaned_slice_t *value); +/** + * Associates `value` to `key` in the map, copying them to obtain ownership: `key` and `value` are not aliased past the function's return. + * + * Returns 1 if there was already an entry associated with the key, 0 otherwise. + */ +ZENOHC_API +uint8_t z_slice_map_insert_by_copy(struct z_loaned_slice_map_t *this_, + const struct z_loaned_slice_t *key, + const struct z_loaned_slice_t *value); +/** + * Returns true if the map is empty, false otherwise. + */ +ZENOHC_API bool z_slice_map_is_empty(const struct z_loaned_slice_map_t *this_); +ZENOHC_API +void z_slice_map_iterate(const struct z_loaned_slice_map_t *this_, + z_slice_map_iter_body_t body, + void *context); +/** + * Returns number of key-value pairs in the map. + */ +ZENOHC_API size_t z_slice_map_len(const struct z_loaned_slice_map_t *this_); +ZENOHC_API +const struct z_loaned_slice_map_t *z_slice_map_loan(const struct z_owned_slice_map_t *this_); +ZENOHC_API struct z_loaned_slice_map_t *z_slice_map_loan_mut(struct z_owned_slice_map_t *this_); +/** + * Constructs a new empty map. + */ +ZENOHC_API void z_slice_map_new(struct z_owned_slice_map_t *this_); +/** + * Constructs the gravestone value for `z_owned_slice_map_t` + */ +ZENOHC_API void z_slice_map_null(struct z_owned_slice_map_t *this_); +ZENOHC_API void z_slice_null(struct z_owned_slice_t *this_); +/** + * Constructs a `len` bytes long view starting at `start`. + */ +ZENOHC_API void z_slice_wrap(struct z_owned_slice_t *this_, const uint8_t *start, size_t len); /** * Returns ``true`` if `strs` is valid. */ @@ -2091,92 +2020,197 @@ ZENOHC_API void z_str_array_drop(struct z_owned_str_array_t *strs); /** * Returns a :c:type:`z_str_array_t` loaned from :c:type:`z_owned_str_array_t`. */ -ZENOHC_API struct z_str_array_t z_str_array_loan(const struct z_owned_str_array_t *strs); +ZENOHC_API const struct z_str_array_t *z_str_array_loan(const struct z_owned_str_array_t *strs); /** * Returns ``true`` if `s` is a valid string */ -ZENOHC_API bool z_str_check(const struct z_owned_str_t *s); +ZENOHC_API bool z_str_check(const struct z_owned_str_t *this_); +ZENOHC_API void z_str_clone(const struct z_loaned_str_t *this_, struct z_owned_str_t *dst); /** * Frees `z_owned_str_t`, invalidating it for double-drop safety. */ -ZENOHC_API void z_str_drop(struct z_owned_str_t *s); +ZENOHC_API void z_str_drop(struct z_owned_str_t *this_); +ZENOHC_API void z_str_empty(struct z_owned_str_t *this_); /** - * Returns :c:type:`z_str_t` structure loaned from :c:type:`z_owned_str_t`. + * Copies a a substring of length `len`into `z_owned_str_t`. + * + * Calling this with `str == NULL` is equivalent to `z_str_null`. + */ +ZENOHC_API void z_str_from_substring(struct z_owned_str_t *this_, const char *str, size_t len); +/** + * Returns :c:type:`z_loaned_str_t` structure loaned from :c:type:`z_owned_str_t`. */ -ZENOHC_API const char *z_str_loan(const struct z_owned_str_t *s); +ZENOHC_API const struct z_loaned_str_t *z_str_loan(const struct z_owned_str_t *this_); /** * Returns undefined `z_owned_str_t` */ -ZENOHC_API struct z_owned_str_t z_str_null(void); +ZENOHC_API void z_str_null(struct z_owned_str_t *this_); +/** + * Copies a string into `z_owned_str_t` using `strlen` (this should therefore not be used with untrusted inputs). + * + * Calling this with `str == NULL` is equivalent to `z_str_null`. + */ +ZENOHC_API +void z_str_wrap(struct z_owned_slice_t *this_, + const char *str); /** * Returns ``true`` if `sub` is valid. */ -ZENOHC_API bool z_subscriber_check(const struct z_owned_subscriber_t *sub); +ZENOHC_API bool z_subscriber_check(const struct z_owned_subscriber_t *subscriber); /** * Returns the key expression of the subscriber. */ -ZENOHC_API struct z_owned_keyexpr_t z_subscriber_keyexpr(struct z_subscriber_t subscriber); +ZENOHC_API +const struct z_loaned_keyexpr_t *z_subscriber_keyexpr(const struct z_loaned_subscriber_t *subscriber); /** - * Returns a :c:type:`z_subscriber_t` loaned from `p`. + * Returns a :c:type:`z_loaned_subscriber_t` loaned from `this`. */ -ZENOHC_API struct z_subscriber_t z_subscriber_loan(const struct z_owned_subscriber_t *p); +ZENOHC_API +const struct z_loaned_subscriber_t *z_subscriber_loan(const struct z_owned_subscriber_t *this_); /** * Constructs a null safe-to-drop value of 'z_owned_subscriber_t' type */ -ZENOHC_API struct z_owned_subscriber_t z_subscriber_null(void); +ZENOHC_API void z_subscriber_null(struct z_owned_subscriber_t *this_); /** * Constructs the default value for :c:type:`z_subscriber_options_t`. */ -ZENOHC_API struct z_subscriber_options_t z_subscriber_options_default(void); +ZENOHC_API void z_subscriber_options_default(struct z_subscriber_options_t *this_); +ZENOHC_API bool z_task_check(const struct z_owned_task_t *this_); /** - * Pull data for :c:type:`z_owned_pull_subscriber_t`. The pulled data will be provided - * by calling the **callback** function provided to the :c:func:`z_declare_subscriber` function. - * - * Parameters: - * sub: The :c:type:`z_owned_pull_subscriber_t` to pull from. + * Detaches the task and releases all allocated resources. */ -ZENOHC_API int8_t z_subscriber_pull(struct z_pull_subscriber_t sub); +ZENOHC_API void z_task_detach(struct z_owned_task_t *this_); ZENOHC_API -int8_t z_task_init(struct z_task_t *task, - const struct z_task_attr_t *_attr, - void (*fun)(void *arg), - void *arg); -ZENOHC_API int8_t z_task_join(struct z_task_t *task); +z_error_t z_task_init(struct z_owned_task_t *this_, + const struct z_task_attr_t *_attr, + void (*fun)(void *arg), + void *arg); +/** + * Joins the task and releases all allocated resources + */ +ZENOHC_API z_error_t z_task_join(struct z_owned_task_t *this_); +ZENOHC_API void z_task_null(struct z_owned_task_t *this_); ZENOHC_API uint64_t z_time_elapsed_ms(const struct z_time_t *time); ZENOHC_API uint64_t z_time_elapsed_s(const struct z_time_t *time); ZENOHC_API uint64_t z_time_elapsed_us(const struct z_time_t *time); ZENOHC_API struct z_time_t z_time_now(void); ZENOHC_API const char *z_time_now_as_str(const char *buf, size_t len); -/** - * Returns ``true`` if `ts` is a valid timestamp - */ -ZENOHC_API bool z_timestamp_check(struct z_timestamp_t ts); +ZENOHC_API struct z_id_t z_timestamp_get_id(const struct z_timestamp_t *timestamp); +ZENOHC_API uint64_t z_timestamp_npt64_time(const struct z_timestamp_t *timestamp); /** * Undeclare the key expression generated by a call to :c:func:`z_declare_keyexpr`. - */ -ZENOHC_API int8_t z_undeclare_keyexpr(struct z_session_t session, struct z_owned_keyexpr_t *kexpr); -/** - * Undeclares the given :c:type:`z_owned_publisher_t`, droping it and invalidating it for double-drop safety. + * The keyxpr is consumed. */ ZENOHC_API -int8_t z_undeclare_publisher(struct z_owned_publisher_t *publisher); +z_error_t z_undeclare_keyexpr(const struct z_loaned_session_t *session, + struct z_owned_keyexpr_t *kexpr); /** - * Undeclares the given :c:type:`z_owned_pull_subscriber_t`, droping it and invalidating it for double-drop safety. + * Undeclares the given :c:type:`z_owned_publisher_t`, droping it and invalidating it for double-drop safety. */ ZENOHC_API -int8_t z_undeclare_pull_subscriber(struct z_owned_pull_subscriber_t *sub); +z_error_t z_undeclare_publisher(struct z_owned_publisher_t *this_); /** * Undeclares a `z_owned_queryable_t`, droping it and invalidating it for doube-drop safety. * * Parameters: * qable: The :c:type:`z_owned_queryable_t` to undeclare. */ -ZENOHC_API int8_t z_undeclare_queryable(struct z_owned_queryable_t *qable); +ZENOHC_API z_error_t z_undeclare_queryable(struct z_owned_queryable_t *qable); /** * Undeclares the given :c:type:`z_owned_subscriber_t`, droping it and invalidating it for double-drop safety. */ ZENOHC_API -int8_t z_undeclare_subscriber(struct z_owned_subscriber_t *sub); +z_error_t z_undeclare_subscriber(struct z_owned_subscriber_t *subscriber); +/** + * Constructs a :c:type:`z_loaned_keyexpr_t` departing from a string. + * It is a loaned key expression that aliases `name`. + */ +ZENOHC_API z_error_t z_view_keyexpr(struct z_view_keyexpr_t *this_, const char *name); +/** + * Constructs a :c:type:`z_loaned_keyexpr_t` by aliasing a string. + * The string is canonized in-place before being passed to keyexpr. + * May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). + */ +ZENOHC_API +z_error_t z_view_keyexpr_autocanonize(struct z_view_keyexpr_t *this_, + char *name); +/** + * Returns ``true`` if `keyexpr` is valid. + */ +ZENOHC_API bool z_view_keyexpr_check(const struct z_view_keyexpr_t *keyexpr); +/** + * Constructs a :c:type:`z_loaned_keyexpr_t` by aliasing a string. + */ +ZENOHC_API +z_error_t z_view_keyexpr_from_slice(struct z_view_keyexpr_t *this_, + const char *name, + size_t len); +/** + * Constructs a :c:type:`z_loaned_keyexpr_t` by aliasing a string. + * The string is canonized in-place before being passed to keyexpr. + * May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). + */ +ZENOHC_API +z_error_t z_view_keyexpr_from_slice_autocanonize(struct z_view_keyexpr_t *this_, + char *name, + size_t *len); +/** + * Constructs a :c:type:`z_eyexpr_t` by aliasing a string without checking any of `z_loaned_keyexpr_t`'s assertions: + * - `name` MUST be valid UTF8. + * - `name` MUST follow the Key Expression specification, ie: + * - MUST NOT contain ``//``, MUST NOT start nor end with ``/``, MUST NOT contain any of the characters ``?#$``. + * - any instance of ``**`` may only be lead or followed by ``/``. + * - the key expression must have canon form. + * + * It is a loaned key expression that aliases `name`. + */ +ZENOHC_API +void z_view_keyexpr_from_slice_unchecked(struct z_view_keyexpr_t *this_, + const char *start, + size_t len); +/** + * Returns a :c:type:`z_loaned_keyexpr_t` loaned from :c:type:`z_owned_keyexpr_t`. + */ +ZENOHC_API +const struct z_loaned_keyexpr_t *z_view_keyexpr_loan(const struct z_view_keyexpr_t *key_expr); +ZENOHC_API void z_view_keyexpr_null(struct z_view_keyexpr_t *this_); +/** + * Returns ``true`` if `this` is initialized. + */ +ZENOHC_API bool z_view_slice_check(const struct z_view_slice_t *this_); +/** + * Returns an empty `z_view_slice_t` + */ +ZENOHC_API void z_view_slice_empty(struct z_view_slice_t *this_); +/** + * Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). + * + * Calling this with `str == NULL` is equivalent to `z_view_slice_null`. + */ +ZENOHC_API void z_view_slice_from_str(struct z_view_slice_t *this_, const char *str); +ZENOHC_API const struct z_loaned_slice_t *z_view_slice_loan(const struct z_view_slice_t *this_); +ZENOHC_API void z_view_slice_null(struct z_view_slice_t *this_); +/** + * Constructs a `len` bytes long view starting at `start`. + */ +ZENOHC_API void z_view_slice_wrap(struct z_view_slice_t *this_, const uint8_t *start, size_t len); +ZENOHC_API const char *z_view_str_data(const struct z_loaned_str_t *this_); +ZENOHC_API void z_view_str_empty(struct z_view_str_t *this_); +ZENOHC_API size_t z_view_str_len(const struct z_loaned_str_t *this_); +/** + * Returns :c:type:`z_loaned_str_t` structure loaned from :c:type:`z_view_str_t`. + */ +ZENOHC_API const struct z_loaned_str_t *z_view_str_loan(const struct z_view_str_t *this_); +/** + * Returns undefined `z_owned_str_t` + */ +ZENOHC_API void z_view_str_null(struct z_view_str_t *this_); +/** + * Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). + * + * Calling this with `str == NULL` is equivalent to `z_view_str_null`. + */ +ZENOHC_API void z_view_str_wrap(struct z_view_slice_t *this_, const char *str); /** * Converts the kind of zenoh entity into a string. * @@ -2193,35 +2227,39 @@ ZENOHC_API int8_t z_whatami_to_str(uint8_t whatami, char *buf, size_t len); * Constructs a configuration by parsing a file at `path`. Currently supported format is JSON5, a superset of JSON. */ ZENOHC_API -struct z_owned_config_t zc_config_from_file(const char *path); +z_error_t zc_config_from_file(struct z_owned_config_t *this_, + const char *path); /** * Reads a configuration from a JSON-serialized string, such as '{mode:"client",connect:{endpoints:["tcp/127.0.0.1:7447"]}}'. * * Passing a null-ptr will result in a gravestone value (`z_check(x) == false`). */ ZENOHC_API -struct z_owned_config_t zc_config_from_str(const char *s); +z_error_t zc_config_from_str(struct z_owned_config_t *this_, + const char *s); /** * Gets the property with the given path key from the configuration, returning an owned, null-terminated, JSON serialized string. * Use `z_drop` to safely deallocate this string */ ZENOHC_API -struct z_owned_str_t zc_config_get(struct z_config_t config, - const char *key); +z_error_t zc_config_get(const struct z_loaned_config_t *config, + const char *key, + struct z_owned_str_t *value_string); /** * Inserts a JSON-serialized `value` at the `key` position of the configuration. * * Returns 0 if successful, a negative value otherwise. */ ZENOHC_API -int8_t zc_config_insert_json(struct z_config_t config, - const char *key, - const char *value); +z_error_t zc_config_insert_json(struct z_loaned_config_t *config, + const char *key, + const char *value); /** * Converts `config` into a JSON-serialized string, such as '{"mode":"client","connect":{"endpoints":["tcp/127.0.0.1:7447"]}}'. */ ZENOHC_API -struct z_owned_str_t zc_config_to_string(struct z_config_t config); +z_error_t zc_config_to_string(const struct z_loaned_config_t *config, + struct z_owned_str_t *config_string); /** * Initialises the zenoh runtime logger. * @@ -2229,54 +2267,14 @@ struct z_owned_str_t zc_config_to_string(struct z_config_t config); * this will be performed automatically by `z_open` and `z_scout`. */ ZENOHC_API void zc_init_logger(void); -/** - * Constructs a :c:type:`z_keyexpr_t` departing from a string. - * It is a loaned key expression that aliases `name`. - */ -ZENOHC_API struct z_keyexpr_t zc_keyexpr_from_slice(const char *name, size_t len); -/** - * Constructs a :c:type:`z_keyexpr_t` departing from a string. - * It is a loaned key expression that aliases `name`. - * The string is canonized in-place before being passed to keyexpr. - * May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). - */ ZENOHC_API -struct z_keyexpr_t zc_keyexpr_from_slice_autocanonize(char *name, - size_t *len); -/** - * Constructs a :c:type:`z_keyexpr_t` departing from a string without checking any of `z_keyexpr_t`'s assertions: - * - `name` MUST be valid UTF8. - * - `name` MUST follow the Key Expression specification, ie: - * - MUST NOT contain ``//``, MUST NOT start nor end with ``/``, MUST NOT contain any of the characters ``?#$``. - * - any instance of ``**`` may only be lead or followed by ``/``. - * - the key expression must have canon form. - * - * It is a loaned key expression that aliases `name`. - */ -ZENOHC_API -struct z_keyexpr_t zc_keyexpr_from_slice_unchecked(const char *start, - size_t len); -/** - * Returns `true` if the options are valid. - */ -ZENOHC_API -bool zc_liveliness_declaration_options_check(const struct zc_owned_liveliness_declaration_options_t *_opts); -/** - * Destroys the options. - */ -ZENOHC_API -void zc_liveliness_declaration_options_drop(struct zc_owned_liveliness_declaration_options_t *opts); -/** - * The gravestone value for `zc_owned_liveliness_declaration_options_t` - */ -ZENOHC_API -struct zc_owned_liveliness_declaration_options_t zc_liveliness_declaration_options_null(void); +void zc_liveliness_declaration_options_default(struct zc_liveliness_declaration_options_t *this_); /** * Declares a subscriber on liveliness tokens that intersect `key`. * * Parameters: - * z_session_t session: The zenoh session. - * z_keyexpr_t keyexpr: The key expression to subscribe. + * z_loaned_session_t session: The zenoh session. + * z_loaned_keyexpr_t key_expr: The key expression to subscribe. * z_owned_closure_sample_t callback: The callback function that will be called each time a * liveliness token status changed. * zc_owned_liveliness_declare_subscriber_options_t _options: The options to be passed to describe the options to be passed to the liveliness subscriber declaration. @@ -2288,10 +2286,11 @@ struct zc_owned_liveliness_declaration_options_t zc_liveliness_declaration_optio * you may use `z_subscriber_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ ZENOHC_API -struct z_owned_subscriber_t zc_liveliness_declare_subscriber(struct z_session_t session, - struct z_keyexpr_t key, - struct z_owned_closure_sample_t *callback, - const struct zc_owned_liveliness_declare_subscriber_options_t *_options); +z_error_t zc_liveliness_declare_subscriber(struct z_owned_subscriber_t *this_, + const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct z_owned_closure_sample_t *callback, + struct zc_liveliness_declare_subscriber_options_t *_options); /** * Constructs and declares a liveliness token on the network. * @@ -2301,9 +2300,10 @@ struct z_owned_subscriber_t zc_liveliness_declare_subscriber(struct z_session_t * Passing `NULL` as options is valid and equivalent to a pointer to the default options. */ ZENOHC_API -struct zc_owned_liveliness_token_t zc_liveliness_declare_token(struct z_session_t session, - struct z_keyexpr_t key, - const struct zc_owned_liveliness_declaration_options_t *_options); +z_error_t zc_liveliness_declare_token(struct zc_owned_liveliness_token_t *this_, + const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct zc_liveliness_declaration_options_t *_options); /** * Queries liveliness tokens currently on the network with a key expression intersecting with `key`. * @@ -2312,112 +2312,28 @@ struct zc_owned_liveliness_token_t zc_liveliness_declare_token(struct z_session_ * Passing `NULL` as options is valid and equivalent to passing a pointer to the default options. */ ZENOHC_API -int8_t zc_liveliness_get(struct z_session_t session, - struct z_keyexpr_t key, - struct z_owned_closure_reply_t *callback, - const struct zc_liveliness_get_options_t *options); -/** - * Returns `true` if the options are valid. - */ -ZENOHC_API bool zc_liveliness_get_options_check(const struct zc_liveliness_get_options_t *_opts); +z_error_t zc_liveliness_get(const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct z_owned_closure_reply_t *callback, + struct zc_liveliness_get_options_t *options); /** * The gravestone value for `zc_liveliness_get_options_t` */ -ZENOHC_API struct zc_liveliness_get_options_t zc_liveliness_get_options_default(void); -/** - * Destroys the options. - */ -ZENOHC_API void zc_liveliness_get_options_drop(struct zc_liveliness_get_options_t *opts); -/** - * The gravestone value for `zc_liveliness_get_options_t` - */ -ZENOHC_API struct zc_liveliness_get_options_t zc_liveliness_get_options_null(void); -/** - * Returns `true` if the options are valid. - */ -ZENOHC_API -bool zc_liveliness_subscriber_options_check(const struct zc_owned_liveliness_declare_subscriber_options_t *_opts); -/** - * Destroys the options. - */ +ZENOHC_API void zc_liveliness_get_options_default(struct zc_liveliness_get_options_t *this_); ZENOHC_API -void zc_liveliness_subscriber_options_drop(struct zc_owned_liveliness_declare_subscriber_options_t *opts); -/** - * The gravestone value for `zc_owned_liveliness_declare_subscriber_options_t` - */ -ZENOHC_API -struct zc_owned_liveliness_declare_subscriber_options_t zc_liveliness_subscriber_options_null(void); +void zc_liveliness_subscriber_options_default(struct zc_liveliness_declare_subscriber_options_t *this_); /** * Returns `true` unless the token is at its gravestone value. */ -ZENOHC_API bool zc_liveliness_token_check(const struct zc_owned_liveliness_token_t *token); +ZENOHC_API bool zc_liveliness_token_check(const struct zc_owned_liveliness_token_t *this_); /** * The gravestone value for liveliness tokens. */ -ZENOHC_API struct zc_owned_liveliness_token_t zc_liveliness_token_null(void); +ZENOHC_API void zc_liveliness_token_null(struct zc_owned_liveliness_token_t *this_); /** * Destroys a liveliness token, notifying subscribers of its destruction. */ -ZENOHC_API void zc_liveliness_undeclare_token(struct zc_owned_liveliness_token_t *token); -/** - * Returns `false` if `payload` is the gravestone value. - */ -ZENOHC_API bool zc_payload_check(const struct zc_owned_payload_t *payload); -/** - * Decrements `payload`'s backing refcount, releasing the memory if appropriate. - */ -ZENOHC_API void zc_payload_drop(struct zc_owned_payload_t *payload); -/** - * Constructs `zc_owned_payload_t`'s gravestone value. - */ -ZENOHC_API struct zc_owned_payload_t zc_payload_null(void); -/** - * Clones the `payload` by incrementing its reference counter. - */ -ZENOHC_API struct zc_owned_payload_t zc_payload_rcinc(const struct zc_owned_payload_t *payload); -/** - * Sends a `PUT` message onto the publisher's key expression, transfering the buffer ownership. - * - * This is avoids copies when transfering data that was either: - * - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher - * - constructed from a `zc_owned_shmbuf_t` - * - * The payload's encoding can be sepcified through the options. - * - * Parameters: - * session: The zenoh session. - * payload: The value to put. - * len: The length of the value to put. - * options: The publisher put options. - * Returns: - * ``0`` in case of success, negative values in case of failure. - */ -ZENOHC_API -int8_t zc_publisher_put_owned(struct z_publisher_t publisher, - struct zc_owned_payload_t *payload, - const struct z_publisher_put_options_t *options); -/** - * Put data, transfering the buffer ownership. - * - * This is avoids copies when transfering data that was either: - * - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher - * - constructed from a `zc_owned_shmbuf_t` - * - * The payload's encoding can be sepcified through the options. - * - * Parameters: - * session: The zenoh session. - * keyexpr: The key expression to put. - * payload: The value to put. - * options: The put options. - * Returns: - * ``0`` in case of success, negative values in case of failure. - */ -ZENOHC_API -int8_t zc_put_owned(struct z_session_t session, - struct z_keyexpr_t keyexpr, - struct zc_owned_payload_t *payload, - const struct z_put_options_t *opts); +ZENOHC_API z_error_t zc_liveliness_undeclare_token(struct zc_owned_liveliness_token_t *this_); /** * Creates a new blocking fifo channel, returned as a pair of closures. * @@ -2470,14 +2386,12 @@ struct z_owned_reply_channel_t zc_reply_fifo_new(size_t bound); */ ZENOHC_API struct z_owned_reply_channel_t zc_reply_non_blocking_fifo_new(size_t bound); -/** - * Clones the sample's payload by incrementing its backing refcount (this doesn't imply any copies). - */ -ZENOHC_API struct zc_owned_payload_t zc_sample_payload_rcinc(const struct z_sample_t *sample); /** * Increments the session's reference count, returning a new owning handle. */ -ZENOHC_API struct z_owned_session_t zc_session_rcinc(struct z_session_t session); +ZENOHC_API +z_error_t zc_session_clone(struct z_owned_session_t *dst, + const struct z_owned_session_t *src); /** * Allocates a buffer of size `capacity` in the manager's memory. * @@ -2509,7 +2423,7 @@ ZENOHC_API size_t zc_shm_gc(const struct zc_owned_shm_manager_t *manager); ZENOHC_API bool zc_shm_manager_check(const struct zc_owned_shm_manager_t *manager); ZENOHC_API void zc_shm_manager_drop(struct zc_owned_shm_manager_t *manager); ZENOHC_API -struct zc_owned_shm_manager_t zc_shm_manager_new(struct z_session_t session, +struct zc_owned_shm_manager_t zc_shm_manager_new(struct z_loaned_session_t session, const char *id, size_t size); ZENOHC_API struct zc_owned_shm_manager_t zc_shm_manager_null(void); @@ -2528,7 +2442,7 @@ ZENOHC_API void zc_shmbuf_drop(struct zc_owned_shmbuf_t *buf); /** * Constructs an owned payload from an owned SHM buffer. */ -ZENOHC_API struct zc_owned_payload_t zc_shmbuf_into_payload(struct zc_owned_shmbuf_t *buf); +ZENOHC_API struct z_owned_bytes_t zc_shmbuf_into_payload(struct zc_owned_shmbuf_t *buf); /** * Returns the length of the SHM buffer. * @@ -2571,15 +2485,16 @@ ZENOHC_API enum zcu_locality_t zcu_locality_default(void); * Register callback for notifying subscribers matching. */ ZENOHC_API -struct zcu_owned_matching_listener_t zcu_publisher_matching_listener_callback(struct z_publisher_t publisher, - struct zcu_owned_closure_matching_status_t *callback); +z_error_t zcu_publisher_matching_listener_callback(struct zcu_owned_matching_listener_t *this_, + const struct z_loaned_publisher_t *publisher, + struct zcu_owned_closure_matching_status_t *callback); ZENOHC_API enum zcu_reply_keyexpr_t zcu_reply_keyexpr_default(void); /** * Declares a Publication Cache. * * Parameters: - * z_session_t session: The zenoh session. - * z_keyexpr_t keyexpr: The key expression to publish. + * z_loaned_session_t session: The zenoh session. + * z_loaned_keyexpr_t key_expr: The key expression to publish. * ze_publication_cache_options_t options: Additional options for the publication_cache. * * Returns: @@ -2601,15 +2516,16 @@ ZENOHC_API enum zcu_reply_keyexpr_t zcu_reply_keyexpr_default(void); * ze_owned_publication_cache_t pub_cache = ze_declare_publication_cache(z_loan(s), z_keyexpr(expr), &opts); */ ZENOHC_API -struct ze_owned_publication_cache_t ze_declare_publication_cache(struct z_session_t session, - struct z_keyexpr_t keyexpr, - const struct ze_publication_cache_options_t *options); +z_error_t ze_declare_publication_cache(struct ze_owned_publication_cache_t *this_, + const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct ze_publication_cache_options_t *options); /** * Declares a Querying Subscriber for a given key expression. * * Parameters: - * z_session_t session: The zenoh session. - * z_keyexpr_t keyexpr: The key expression to subscribe. + * z_loaned_session_t session: The zenoh session. + * z_loaned_keyexpr_t keyexpr: The key expression to subscribe. * z_owned_closure_sample_t callback: The callback function that will be called each time a data matching the subscribed expression is received. * ze_querying_subscriber_options_t options: Additional options for the querying subscriber. * @@ -2638,54 +2554,56 @@ struct ze_owned_publication_cache_t ze_declare_publication_cache(struct z_sessio * ze_owned_subscriber_t sub = ze_declare_querying_subscriber(z_loan(s), z_keyexpr(expr), callback, &opts); */ ZENOHC_API -struct ze_owned_querying_subscriber_t ze_declare_querying_subscriber(struct z_session_t session, - struct z_keyexpr_t keyexpr, - struct z_owned_closure_sample_t *callback, - const struct ze_querying_subscriber_options_t *options); +z_error_t ze_declare_querying_subscriber(struct ze_owned_querying_subscriber_t *this_, + const struct z_loaned_session_t *session, + const struct z_loaned_keyexpr_t *key_expr, + struct z_owned_closure_sample_t *callback, + struct ze_querying_subscriber_options_t *options); /** * Returns ``true`` if `pub_cache` is valid. */ -ZENOHC_API bool ze_publication_cache_check(const struct ze_owned_publication_cache_t *pub_cache); +ZENOHC_API bool ze_publication_cache_check(const struct ze_owned_publication_cache_t *this_); /** * Constructs a null safe-to-drop value of 'ze_owned_publication_cache_t' type */ -ZENOHC_API struct ze_owned_publication_cache_t ze_publication_cache_null(void); +ZENOHC_API void ze_publication_cache_null(struct ze_owned_publication_cache_t *this_); /** * Constructs the default value for :c:type:`ze_publication_cache_options_t`. */ -ZENOHC_API struct ze_publication_cache_options_t ze_publication_cache_options_default(void); +ZENOHC_API void ze_publication_cache_options_default(struct ze_publication_cache_options_t *this_); /** - * Returns ``true`` if `sub` is valid. + * Returns ``true`` if `this` is valid. */ -ZENOHC_API bool ze_querying_subscriber_check(const struct ze_owned_querying_subscriber_t *sub); +ZENOHC_API bool ze_querying_subscriber_check(const struct ze_owned_querying_subscriber_t *this_); /** * Make a :c:type:`ze_owned_querying_subscriber_t` to perform an additional query on a specified selector. * The queried samples will be merged with the received publications and made available in the subscriber callback. */ ZENOHC_API -int8_t ze_querying_subscriber_get(struct ze_querying_subscriber_t sub, - struct z_keyexpr_t selector, - const struct z_get_options_t *options); +z_error_t ze_querying_subscriber_get(const struct ze_loaned_querying_subscriber_t *sub, + const struct z_loaned_keyexpr_t *selector, + const struct z_get_options_t *options); /** - * Returns a :c:type:`ze_querying_subscriber_loan` loaned from `p`. + * Returns a :c:type:`ze_querying_subscriber_loan` loaned from `this`. */ ZENOHC_API -struct ze_querying_subscriber_t ze_querying_subscriber_loan(const struct ze_owned_querying_subscriber_t *p); +const struct ze_loaned_querying_subscriber_t *ze_querying_subscriber_loan(const struct ze_owned_querying_subscriber_t *this_); /** * Constructs a null safe-to-drop value of 'ze_owned_querying_subscriber_t' type */ -ZENOHC_API struct ze_owned_querying_subscriber_t ze_querying_subscriber_null(void); +ZENOHC_API void ze_querying_subscriber_null(struct ze_owned_querying_subscriber_t *this_); /** * Constructs the default value for :c:type:`ze_querying_subscriber_options_t`. */ -ZENOHC_API struct ze_querying_subscriber_options_t ze_querying_subscriber_options_default(void); +ZENOHC_API +void ze_querying_subscriber_options_default(struct ze_querying_subscriber_options_t *this_); /** * Closes the given :c:type:`ze_owned_publication_cache_t`, droping it and invalidating it for double-drop safety. */ ZENOHC_API -int8_t ze_undeclare_publication_cache(struct ze_owned_publication_cache_t *pub_cache); +z_error_t ze_undeclare_publication_cache(struct ze_owned_publication_cache_t *this_); /** * Undeclares the given :c:type:`ze_owned_querying_subscriber_t`, droping it and invalidating it for double-drop safety. */ ZENOHC_API -int8_t ze_undeclare_querying_subscriber(struct ze_owned_querying_subscriber_t *sub); +z_error_t ze_undeclare_querying_subscriber(struct ze_owned_querying_subscriber_t *this_); diff --git a/include/zenoh_concrete.h b/include/zenoh_concrete.h index 44f208496..f9f91304e 100644 --- a/include/zenoh_concrete.h +++ b/include/zenoh_concrete.h @@ -33,46 +33,15 @@ * * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ -typedef struct z_owned_session_t { - size_t _0; +typedef struct ALIGN(8) z_owned_session_t { + uint8_t _0[8]; } z_owned_session_t; -/** - * Loaned variant of a Query received by a Queryable. - * - * Queries are atomically reference-counted, letting you extract them from the callback that handed them to you by cloning. - * `z_query_t`'s are valid as long as at least one corresponding `z_owned_query_t` exists, including the one owned by Zenoh until the callback returns. - */ -typedef struct z_query_t { - void *_0; -} z_query_t; -/** - * A loaned zenoh session. - */ -typedef struct z_session_t { - size_t _0; -} z_session_t; -/** - * An owned zenoh pull subscriber. Destroying the subscriber cancels the subscription. - * - * Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. - * The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. - * - * Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. - * To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. - * After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. - * - * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. - */ -#if !defined(TARGET_ARCH_ARM) -typedef struct ALIGN(8) z_owned_pull_subscriber_t { - uint64_t _0[1]; -} z_owned_pull_subscriber_t; -#endif -#if defined(TARGET_ARCH_ARM) -typedef struct ALIGN(4) z_owned_pull_subscriber_t { - uint32_t _0[1]; -} z_owned_pull_subscriber_t; -#endif +typedef struct ALIGN(8) z_loaned_query_t { + uint8_t _0[16]; +} z_loaned_query_t; +typedef struct ALIGN(8) z_loaned_session_t { + uint8_t _0[40]; +} z_loaned_session_t; /** * An owned zenoh queryable. * @@ -85,16 +54,9 @@ typedef struct ALIGN(4) z_owned_pull_subscriber_t { * * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ -#if !defined(TARGET_ARCH_ARM) typedef struct ALIGN(8) z_owned_queryable_t { - uint64_t _0[4]; + uint8_t _0[32]; } z_owned_queryable_t; -#endif -#if defined(TARGET_ARCH_ARM) -typedef struct ALIGN(4) z_owned_queryable_t { - uint32_t _0[4]; -} z_owned_queryable_t; -#endif /** * An owned zenoh subscriber. Destroying the subscriber cancels the subscription. * @@ -107,13 +69,18 @@ typedef struct ALIGN(4) z_owned_queryable_t { * * To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. */ -#if !defined(TARGET_ARCH_ARM) typedef struct ALIGN(8) z_owned_subscriber_t { - uint64_t _0[1]; + uint8_t _0[32]; } z_owned_subscriber_t; -#endif -#if defined(TARGET_ARCH_ARM) -typedef struct ALIGN(4) z_owned_subscriber_t { - uint32_t _0[1]; -} z_owned_subscriber_t; -#endif +#define Z_OK 0 +#define Z_EINVAL -1 +#define Z_EPARSE -2 +#define Z_EIO -3 +#define Z_ENETWORK -4 +#define Z_ENULL -5 +#define Z_EUNAVAILABLE -6 +#define Z_EBUSY_MUTEX -16 +#define Z_EINVAL_MUTEX -22 +#define Z_EAGAIN_MUTEX -11 +#define Z_EPOISON_MUTEX -22 +#define Z_EGENERIC INT8_MIN diff --git a/include/zenoh_macros.h b/include/zenoh_macros.h index fa6668d48..d11e11838 100644 --- a/include/zenoh_macros.h +++ b/include/zenoh_macros.h @@ -1,293 +1,390 @@ #pragma once - +// clang-format off #ifndef __cplusplus -// clang-format off #define z_loan(x) \ - _Generic((x), z_owned_session_t : z_session_loan, \ - z_owned_keyexpr_t : z_keyexpr_loan, \ - z_owned_config_t : z_config_loan, \ - z_owned_publisher_t : z_publisher_loan, \ - z_owned_subscriber_t : z_subscriber_loan, \ - z_owned_pull_subscriber_t : z_pull_subscriber_loan, \ - z_owned_encoding_t : z_encoding_loan, \ - z_owned_hello_t : z_hello_loan, \ - z_owned_str_t : z_str_loan, \ - z_owned_query_t : z_query_loan, \ - ze_owned_querying_subscriber_t : ze_querying_subscriber_loan \ - )(&x) + _Generic((x), \ + z_owned_bytes_t : z_bytes_loan, \ + z_owned_bytes_reader_t : z_bytes_reader_loan, \ + z_owned_condvar_t : z_condvar_loan, \ + z_owned_config_t : z_config_loan, \ + z_owned_encoding_t : z_encoding_loan, \ + z_owned_hello_t : z_hello_loan, \ + z_owned_keyexpr_t : z_keyexpr_loan, \ + z_owned_publisher_t : z_publisher_loan, \ + z_owned_query_t : z_query_loan, \ + z_owned_sample_t : z_sample_loan, \ + z_owned_session_t : z_session_loan, \ + z_owned_slice_t : z_slice_loan, \ + z_owned_slice_map_t : z_slice_map_loan, \ + z_owned_str_array_t : z_str_array_loan, \ + z_owned_str_t : z_str_loan, \ + z_owned_subscriber_t : z_subscriber_loan, \ + z_view_keyexpr_t : z_view_keyexpr_loan, \ + z_view_slice_t : z_view_slice_loan, \ + z_view_str_t : z_view_str_loan, \ + ze_owned_querying_subscriber_t : ze_querying_subscriber_loan \ + )(&x) + +#define z_loan_mut(x) \ + _Generic((x), \ + z_owned_bytes_reader_t : z_bytes_reader_loan_mut, \ + z_owned_condvar_t : z_condvar_loan_mut, \ + z_owned_config_t : z_config_loan_mut, \ + z_owned_mutex_t : z_mutex_loan_mut, \ + z_owned_slice_map_t : z_slice_map_loan_mut \ + )(&x) #define z_drop(x) \ - _Generic((x), z_owned_session_t * : z_close, \ - z_owned_publisher_t * : z_undeclare_publisher, \ - z_owned_keyexpr_t * : z_keyexpr_drop, \ - z_owned_config_t * : z_config_drop, \ - z_owned_scouting_config_t * : z_scouting_config_drop, \ - z_owned_pull_subscriber_t * : z_undeclare_pull_subscriber, \ - z_owned_subscriber_t * : z_undeclare_subscriber, \ - z_owned_queryable_t * : z_undeclare_queryable, \ - z_owned_encoding_t * : z_encoding_drop, \ - z_owned_reply_t * : z_reply_drop, \ - z_owned_hello_t * : z_hello_drop, \ - z_owned_str_t * : z_str_drop, \ - z_owned_query_t * : z_query_drop, \ - z_owned_closure_sample_t * : z_closure_sample_drop, \ - z_owned_closure_query_t * : z_closure_query_drop, \ - z_owned_closure_reply_t * : z_closure_reply_drop, \ - z_owned_closure_hello_t * : z_closure_hello_drop, \ - z_owned_closure_zid_t * : z_closure_zid_drop, \ - zcu_owned_closure_matching_status_t * : zcu_closure_matching_status_drop, \ - z_owned_reply_channel_closure_t * : z_reply_channel_closure_drop, \ - z_owned_query_channel_closure_t * : z_query_channel_closure_drop, \ - z_owned_reply_channel_t * : z_reply_channel_drop, \ - z_owned_query_channel_t * : z_query_channel_drop, \ - z_owned_bytes_map_t * : z_bytes_map_drop, \ - zc_owned_payload_t * : zc_payload_drop, \ - zc_owned_shmbuf_t * : zc_shmbuf_drop, \ - zc_owned_shm_manager_t * : zc_shm_manager_drop, \ - zc_owned_liveliness_token_t * : zc_liveliness_undeclare_token, \ - ze_owned_publication_cache_t * : ze_undeclare_publication_cache, \ - ze_owned_querying_subscriber_t * : ze_undeclare_querying_subscriber \ - )(x) + _Generic((x),\ + z_owned_bytes_t * : z_bytes_drop,\ + z_owned_bytes_reader_t * : z_bytes_reader_drop,\ + z_owned_closure_hello_t * : z_closure_hello_drop,\ + z_owned_closure_owned_query_t * : z_closure_owned_query_drop,\ + z_owned_closure_query_t * : z_closure_query_drop,\ + z_owned_closure_reply_t * : z_closure_reply_drop,\ + z_owned_closure_sample_t * : z_closure_sample_drop,\ + z_owned_closure_zid_t * : z_closure_zid_drop,\ + z_owned_condvar_t * : z_condvar_drop,\ + z_owned_config_t * : z_config_drop,\ + z_owned_encoding_t * : z_encoding_drop,\ + z_owned_hello_t * : z_hello_drop,\ + z_owned_keyexpr_t * : z_keyexpr_drop,\ + z_owned_mutex_t * : z_mutex_drop,\ + z_owned_query_channel_closure_t * : z_query_channel_closure_drop,\ + z_owned_query_channel_t * : z_query_channel_drop,\ + z_owned_query_t * : z_query_drop,\ + z_owned_reply_channel_closure_t * : z_reply_channel_closure_drop,\ + z_owned_reply_channel_t * : z_reply_channel_drop,\ + z_owned_reply_t * : z_reply_drop,\ + z_owned_sample_t * : z_sample_drop,\ + z_owned_scouting_config_t * : z_scouting_config_drop,\ + z_owned_slice_t * : z_slice_drop,\ + z_owned_slice_map_t * : z_slice_map_drop,\ + z_owned_str_array_t * : z_str_array_drop,\ + z_owned_str_t * : z_str_drop,\ + zc_owned_shm_manager_t * : zc_shm_manager_drop,\ + zc_owned_shmbuf_t * : zc_shmbuf_drop,\ + zcu_owned_closure_matching_status_t * : zcu_closure_matching_status_drop \ + )(x) -#define z_null(x) (*x = \ - _Generic((x), z_owned_session_t * : z_session_null, \ - z_owned_publisher_t * : z_publisher_null, \ - z_owned_keyexpr_t * : z_keyexpr_null, \ - z_owned_config_t * : z_config_null, \ - z_owned_scouting_config_t * : z_scouting_config_null, \ - z_owned_pull_subscriber_t * : z_pull_subscriber_null, \ - z_owned_subscriber_t * : z_subscriber_null, \ - z_owned_queryable_t * : z_queryable_null, \ - z_owned_encoding_t * : z_encoding_null, \ - z_owned_reply_t * : z_reply_null, \ - z_owned_hello_t * : z_hello_null, \ - z_owned_str_t * : z_str_null, \ - z_owned_query_t * : z_query_null, \ - z_owned_closure_sample_t * : z_closure_sample_null, \ - z_owned_closure_query_t * : z_closure_query_null, \ - z_owned_closure_reply_t * : z_closure_reply_null, \ - z_owned_closure_hello_t * : z_closure_hello_null, \ - z_owned_closure_zid_t * : z_closure_zid_null, \ - zcu_owned_closure_matching_status_t * : zcu_closure_matching_status_null, \ - z_owned_reply_channel_closure_t * : z_reply_channel_closure_null, \ - z_owned_reply_channel_t * : z_reply_channel_null, \ - z_owned_bytes_map_t * : z_bytes_map_null, \ - z_attachment_t * : z_attachment_null, \ - zc_owned_payload_t * : zc_payload_null, \ - zc_owned_shmbuf_t * : zc_shmbuf_null, \ - zc_owned_shm_manager_t * : zc_shm_manager_null, \ - ze_owned_publication_cache_t * : ze_publication_cache_null, \ - zc_owned_liveliness_token_t * : zc_liveliness_token_null \ - )()) +#define z_null(x) \ + _Generic((x), \ + z_owned_bytes_t * : z_bytes_null, \ + z_owned_bytes_reader_t * : z_bytes_reader_null, \ + z_owned_condvar_t * : z_condvar_null, \ + z_owned_config_t * : z_config_null, \ + z_owned_encoding_t * : z_encoding_null, \ + z_owned_hello_t * : z_hello_null, \ + z_owned_keyexpr_t * : z_keyexpr_null, \ + z_owned_mutex_t * : z_mutex_null, \ + z_owned_publisher_t * : z_publisher_null, \ + z_owned_query_t * : z_query_null, \ + z_owned_queryable_t * : z_queryable_null, \ + z_owned_reply_t * : z_reply_null, \ + z_owned_sample_t * : z_sample_null, \ + z_owned_scouting_config_t * : z_scouting_config_null, \ + z_owned_session_t * : z_session_null, \ + z_owned_slice_map_t * : z_slice_map_null, \ + z_owned_slice_t * : z_slice_null, \ + z_owned_str_t * : z_str_null, \ + z_owned_subscriber_t * : z_subscriber_null, \ + z_owned_task_t * : z_task_null, \ + z_view_keyexpr_t * : z_view_keyexpr_null, \ + z_view_slice_t * : z_view_slice_null, \ + z_view_str_t * : z_view_str_null, \ + zc_owned_liveliness_token_t * : zc_liveliness_token_null, \ + ze_owned_publication_cache_t * : ze_publication_cache_null, \ + ze_owned_querying_subscriber_t * : ze_querying_subscriber_null \ + )(x) #define z_check(x) \ - _Generic((x), z_owned_session_t : z_session_check, \ - z_owned_publisher_t : z_publisher_check, \ - z_owned_keyexpr_t : z_keyexpr_check, \ - z_keyexpr_t : z_keyexpr_is_initialized, \ - z_owned_config_t : z_config_check, \ - z_owned_scouting_config_t : z_scouting_config_check, \ - z_bytes_t : z_bytes_check, \ - z_owned_subscriber_t : z_subscriber_check, \ - z_owned_pull_subscriber_t : z_pull_subscriber_check, \ - z_owned_queryable_t : z_queryable_check, \ - z_owned_encoding_t : z_encoding_check, \ - z_owned_reply_t : z_reply_check, \ - z_owned_hello_t : z_hello_check, \ - z_owned_query_t : z_query_check, \ - z_owned_str_t : z_str_check, \ - z_owned_bytes_map_t : z_bytes_map_check, \ - z_attachment_t : z_attachment_check, \ - zc_owned_payload_t : zc_payload_check, \ - zc_owned_shmbuf_t : zc_shmbuf_check, \ - zc_owned_shm_manager_t : zc_shm_manager_check, \ - zc_owned_liveliness_token_t : zc_liveliness_token_check, \ - ze_owned_publication_cache_t : ze_publication_cache_check, \ - ze_owned_querying_subscriber_t : ze_querying_subscriber_check \ - )(&x) + _Generic((x), \ + z_owned_bytes_t : z_bytes_check, \ + z_owned_bytes_reader_t : z_bytes_reader_check, \ + z_owned_condvar_t : z_condvar_check, \ + z_owned_config_t : z_config_check, \ + z_owned_encoding_t : z_encoding_check, \ + z_owned_hello_t : z_hello_check, \ + z_owned_keyexpr_t : z_keyexpr_check, \ + z_owned_mutex_t : z_mutex_check, \ + z_owned_slice_t : z_owned_slice_check, \ + z_owned_publisher_t : z_publisher_check, \ + z_owned_query_t : z_query_check, \ + z_owned_queryable_t : z_queryable_check, \ + z_owned_reply_t : z_reply_check, \ + z_owned_sample_t : z_sample_check, \ + z_owned_scouting_config_t : z_scouting_config_check, \ + z_owned_session_t : z_session_check, \ + z_owned_slice_map_t : z_slice_map_check, \ + z_owned_str_array_t : z_str_array_check, \ + z_owned_str_t : z_str_check, \ + z_owned_subscriber_t : z_subscriber_check, \ + z_owned_task_t : z_task_check, \ + z_view_keyexpr_t : z_view_keyexpr_check, \ + z_view_slice_t : z_view_slice_check, \ + zc_owned_liveliness_token_t : zc_liveliness_token_check, \ + zc_owned_shm_manager_t : zc_shm_manager_check, \ + zc_owned_shmbuf_t : zc_shmbuf_check, \ + ze_owned_publication_cache_t : ze_publication_cache_check, \ + ze_owned_querying_subscriber_t : ze_querying_subscriber_check \ + )(&x) #define z_call(x, ...) \ - _Generic((x), z_owned_closure_sample_t : z_closure_sample_call, \ - z_owned_closure_query_t : z_closure_query_call, \ - z_owned_closure_owned_query_t : z_closure_owned_query_call, \ - z_owned_closure_reply_t : z_closure_reply_call, \ - z_owned_closure_hello_t : z_closure_hello_call, \ - z_owned_closure_zid_t : z_closure_zid_call, \ - zcu_owned_closure_matching_status_t : zcu_closure_matching_status_call, \ - z_owned_reply_channel_closure_t : z_reply_channel_closure_call, \ - z_owned_query_channel_closure_t : z_query_channel_closure_call \ - ) (&x, __VA_ARGS__) -// clang-format on - -#define _z_closure_overloader(callback, droper, ctx, ...) \ - { .context = (void*)ctx, .call = callback, .drop = droper } -#define z_closure(...) _z_closure_overloader(__VA_ARGS__, NULL, NULL) -#define z_move(x) (&x) + _Generic((x), \ + z_owned_closure_hello_t : z_closure_hello_call, \ + z_owned_closure_owned_query_t : z_closure_owned_query_call, \ + z_owned_closure_query_t : z_closure_query_call, \ + z_owned_closure_reply_t : z_closure_reply_call, \ + z_owned_closure_sample_t : z_closure_sample_call, \ + z_owned_closure_zid_t : z_closure_zid_call, \ + z_owned_query_channel_closure_t : z_query_channel_closure_call, \ + z_owned_reply_channel_closure_t : z_reply_channel_closure_call, \ + zcu_owned_closure_matching_status_t : zcu_closure_matching_status_call \ + )(&x, __VA_ARGS__) +#define z_closure(x, callback, dropper, ctx) \ + _Generic((x), \ + z_owned_closure_hello_t * : { x->context = (void*)ctx; x->call = callback; x->drop = droper; }, \ + z_owned_closure_owned_query_t * : { x->context = (void*)ctx; x->call = callback; x->drop = droper; }, \ + z_owned_closure_query_t * : { x->context = (void*)ctx; x->call = callback; x->drop = droper; }, \ + z_owned_closure_reply_t * : { x->context = (void*)ctx; x->call = callback; x->drop = droper; }, \ + z_owned_closure_sample_t * : { x->context = (void*)ctx; x->call = callback; x->drop = droper; }, \ + z_owned_closure_zid_t * : { x->context = (void*)ctx; x->call = callback; x->drop = droper; }, \ + z_owned_query_channel_closure_t * : { x->context = (void*)ctx; x->call = callback; x->drop = droper; }, \ + z_owned_reply_channel_closure_t * : { x->context = (void*)ctx; x->call = callback; x->drop = droper; }, \ + zcu_owned_closure_matching_status_t * : { x->context = (void*)ctx; x->call = callback; x->drop = droper; } \ + ) #else // #ifndef __cplusplus -// clang-format off -template struct zenoh_loan_type { typedef T type; }; -template inline typename zenoh_loan_type::type z_loan(const T&); -template<> struct zenoh_loan_type{ typedef z_session_t type; }; -template<> struct zenoh_loan_type{ typedef z_keyexpr_t type; }; -template<> struct zenoh_loan_type{ typedef z_config_t type; }; -template<> struct zenoh_loan_type{ typedef z_publisher_t type; }; -template<> struct zenoh_loan_type{ typedef z_subscriber_t type; }; -template<> struct zenoh_loan_type{ typedef z_query_t type; }; -template<> struct zenoh_loan_type{ typedef z_pull_subscriber_t type; }; -template<> struct zenoh_loan_type{ typedef z_encoding_t type; }; -template<> struct zenoh_loan_type{ typedef z_hello_t type; }; -template<> struct zenoh_loan_type{ typedef const char* type; }; -template<> struct zenoh_loan_type{ typedef ze_querying_subscriber_t type; }; -template<> inline z_session_t z_loan(const z_owned_session_t& x) { return z_session_loan(&x); } -template<> inline z_keyexpr_t z_loan(const z_owned_keyexpr_t& x) { return z_keyexpr_loan(&x); } -template<> inline z_config_t z_loan(const z_owned_config_t& x) { return z_config_loan(&x); } -template<> inline z_publisher_t z_loan(const z_owned_publisher_t& x) { return z_publisher_loan(&x); } -template<> inline z_subscriber_t z_loan(const z_owned_subscriber_t& x) { return z_subscriber_loan(&x); } -template<> inline z_pull_subscriber_t z_loan(const z_owned_pull_subscriber_t& x) { return z_pull_subscriber_loan(&x); } -template<> inline z_encoding_t z_loan(const z_owned_encoding_t& x) { return z_encoding_loan(&x); } -template<> inline z_hello_t z_loan(const z_owned_hello_t& x) { return z_hello_loan(&x); } -template<> inline z_query_t z_loan(const z_owned_query_t& x) { return z_query_loan(&x); } -template<> inline const char* z_loan(const z_owned_str_t& x) { return z_str_loan(&x); } -template<> inline ze_querying_subscriber_t z_loan(const ze_owned_querying_subscriber_t& x) { return ze_querying_subscriber_loan(&x); } +inline const z_loaned_bytes_t* z_loan(const z_owned_bytes_t* payload) { return z_bytes_loan(payload); }; +inline const z_loaned_bytes_reader_t* z_loan(const z_owned_bytes_reader_t* reader) { return z_bytes_reader_loan(reader); }; +inline const z_loaned_condvar_t* z_loan(const z_owned_condvar_t* this_) { return z_condvar_loan(this_); }; +inline const z_loaned_config_t* z_loan(const z_owned_config_t* this_) { return z_config_loan(this_); }; +inline const z_loaned_encoding_t* z_loan(const z_owned_encoding_t* encoding) { return z_encoding_loan(encoding); }; +inline const z_hello_t* z_loan(const z_owned_hello_t* hello) { return z_hello_loan(hello); }; +inline const z_loaned_keyexpr_t* z_loan(const z_owned_keyexpr_t* key_expr) { return z_keyexpr_loan(key_expr); }; +inline const z_loaned_publisher_t* z_loan(const z_owned_publisher_t* this_) { return z_publisher_loan(this_); }; +inline const z_loaned_query_t* z_loan(const z_owned_query_t* this_) { return z_query_loan(this_); }; +inline const z_loaned_sample_t* z_loan(const z_owned_sample_t* sample) { return z_sample_loan(sample); }; +inline const z_loaned_session_t* z_loan(const z_owned_session_t* this_) { return z_session_loan(this_); }; +inline const z_loaned_slice_t* z_loan(const z_owned_slice_t* this_) { return z_slice_loan(this_); }; +inline const z_loaned_slice_map_t* z_loan(const z_owned_slice_map_t* this_) { return z_slice_map_loan(this_); }; +inline const z_str_array_t* z_loan(const z_owned_str_array_t* strs) { return z_str_array_loan(strs); }; +inline const z_loaned_str_t* z_loan(const z_owned_str_t* this_) { return z_str_loan(this_); }; +inline const z_loaned_subscriber_t* z_loan(const z_owned_subscriber_t* this_) { return z_subscriber_loan(this_); }; +inline const z_loaned_keyexpr_t* z_loan(const z_view_keyexpr_t* key_expr) { return z_view_keyexpr_loan(key_expr); }; +inline const z_loaned_slice_t* z_loan(const z_view_slice_t* this_) { return z_view_slice_loan(this_); }; +inline const z_loaned_str_t* z_loan(const z_view_str_t* this_) { return z_view_str_loan(this_); }; +inline const ze_loaned_querying_subscriber_t* z_loan(const ze_owned_querying_subscriber_t* this_) { return ze_querying_subscriber_loan(this_); }; + + +inline z_loaned_bytes_reader_t* z_loan_mut( z_owned_bytes_reader_t& reader) { return z_bytes_reader_loan_mut(&reader); }; +inline z_loaned_condvar_t* z_loan_mut( z_owned_condvar_t& this_) { return z_condvar_loan_mut(&this_); }; +inline z_loaned_config_t* z_loan_mut( z_owned_config_t& this_) { return z_config_loan_mut(&this_); }; +inline z_loaned_mutex_t* z_loan_mut( z_owned_mutex_t& this_) { return z_mutex_loan_mut(&this_); }; +inline z_loaned_slice_map_t* z_loan_mut( z_owned_slice_map_t& this_) { return z_slice_map_loan_mut(&this_); }; + + +inline void z_drop(const z_owned_bytes_t* this_) { return z_bytes_drop(this_); }; +inline void z_drop(const z_owned_bytes_reader_t* this_) { return z_bytes_reader_drop(this_); }; +inline void z_drop(const z_owned_closure_hello_t* closure) { return z_closure_hello_drop(closure); }; +inline void z_drop(const z_owned_closure_owned_query_t* closure) { return z_closure_owned_query_drop(closure); }; +inline void z_drop(const z_owned_closure_query_t* closure) { return z_closure_query_drop(closure); }; +inline void z_drop(const z_owned_closure_reply_t* closure) { return z_closure_reply_drop(closure); }; +inline void z_drop(const z_owned_closure_sample_t* closure) { return z_closure_sample_drop(closure); }; +inline void z_drop(const z_owned_closure_zid_t* closure) { return z_closure_zid_drop(closure); }; +inline void z_drop(const z_owned_condvar_t* this_) { return z_condvar_drop(this_); }; +inline void z_drop(const z_owned_config_t* config) { return z_config_drop(config); }; +inline void z_drop(const z_owned_encoding_t* encoding) { return z_encoding_drop(encoding); }; +inline void z_drop(const z_owned_hello_t* hello) { return z_hello_drop(hello); }; +inline void z_drop(const z_owned_keyexpr_t* keyexpr) { return z_keyexpr_drop(keyexpr); }; +inline void z_drop(const z_owned_mutex_t* this_) { return z_mutex_drop(this_); }; +inline void z_drop(const z_owned_query_channel_closure_t* closure) { return z_query_channel_closure_drop(closure); }; +inline void z_drop(const z_owned_query_channel_t* channel) { return z_query_channel_drop(channel); }; +inline void z_drop(const z_owned_query_t* this_) { return z_query_drop(this_); }; +inline void z_drop(const z_owned_reply_channel_closure_t* closure) { return z_reply_channel_closure_drop(closure); }; +inline void z_drop(const z_owned_reply_channel_t* channel) { return z_reply_channel_drop(channel); }; +inline void z_drop(const z_owned_reply_t* this_) { return z_reply_drop(this_); }; +inline void z_drop(const z_owned_sample_t* sample) { return z_sample_drop(sample); }; +inline void z_drop(const z_owned_scouting_config_t* config) { return z_scouting_config_drop(config); }; +inline void z_drop(const z_owned_slice_t* this_) { return z_slice_drop(this_); }; +inline void z_drop(const z_owned_slice_map_t* this_) { return z_slice_map_drop(this_); }; +inline void z_drop(const z_owned_str_array_t* strs) { return z_str_array_drop(strs); }; +inline void z_drop(const z_owned_str_t* this_) { return z_str_drop(this_); }; +inline void z_drop(const zc_owned_shm_manager_t* manager) { return zc_shm_manager_drop(manager); }; +inline void z_drop(const zc_owned_shmbuf_t* buf) { return zc_shmbuf_drop(buf); }; +inline void z_drop(const zcu_owned_closure_matching_status_t* closure) { return zcu_closure_matching_status_drop(closure); }; -template struct zenoh_drop_type { typedef T type; }; -template inline typename zenoh_drop_type::type z_drop(T*); -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef void type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; -template<> struct zenoh_drop_type { typedef int8_t type; }; +inline void z_null( z_owned_bytes_t* this_) { return z_bytes_null(this_); }; +inline void z_null( z_owned_bytes_reader_t* this_) { return z_bytes_reader_null(this_); }; +inline void z_null( z_owned_condvar_t* this_) { return z_condvar_null(this_); }; +inline void z_null( z_owned_config_t* this_) { return z_config_null(this_); }; +inline void z_null( z_owned_encoding_t* encoding) { return z_encoding_null(encoding); }; +inline void z_null( z_owned_hello_t* this_) { return z_hello_null(this_); }; +inline void z_null( z_owned_keyexpr_t* this_) { return z_keyexpr_null(this_); }; +inline void z_null( z_owned_mutex_t* this_) { return z_mutex_null(this_); }; +inline void z_null( z_owned_publisher_t* this_) { return z_publisher_null(this_); }; +inline void z_null( z_owned_query_t* this_) { return z_query_null(this_); }; +inline void z_null( z_owned_queryable_t* this_) { return z_queryable_null(this_); }; +inline void z_null( z_owned_reply_t* this_) { return z_reply_null(this_); }; +inline void z_null( z_owned_sample_t* sample) { return z_sample_null(sample); }; +inline void z_null( z_owned_scouting_config_t* this_) { return z_scouting_config_null(this_); }; +inline void z_null( z_owned_session_t* this_) { return z_session_null(this_); }; +inline void z_null( z_owned_slice_map_t* this_) { return z_slice_map_null(this_); }; +inline void z_null( z_owned_slice_t* this_) { return z_slice_null(this_); }; +inline void z_null( z_owned_str_t* this_) { return z_str_null(this_); }; +inline void z_null( z_owned_subscriber_t* this_) { return z_subscriber_null(this_); }; +inline void z_null( z_owned_task_t* this_) { return z_task_null(this_); }; +inline void z_null( z_view_keyexpr_t* this_) { return z_view_keyexpr_null(this_); }; +inline void z_null( z_view_slice_t* this_) { return z_view_slice_null(this_); }; +inline void z_null( z_view_str_t* this_) { return z_view_str_null(this_); }; +inline void z_null( zc_owned_liveliness_token_t* this_) { return zc_liveliness_token_null(this_); }; +inline void z_null( ze_owned_publication_cache_t* this_) { return ze_publication_cache_null(this_); }; +inline void z_null( ze_owned_querying_subscriber_t* this_) { return ze_querying_subscriber_null(this_); }; -template<> inline int8_t z_drop(z_owned_session_t* v) { return z_close(v); } -template<> inline int8_t z_drop(z_owned_publisher_t* v) { return z_undeclare_publisher(v); } -template<> inline void z_drop(z_owned_keyexpr_t* v) { z_keyexpr_drop(v); } -template<> inline void z_drop(z_owned_config_t* v) { z_config_drop(v); } -template<> inline void z_drop(z_owned_scouting_config_t* v) { z_scouting_config_drop(v); } -template<> inline int8_t z_drop(z_owned_pull_subscriber_t* v) { return z_undeclare_pull_subscriber(v); } -template<> inline int8_t z_drop(z_owned_subscriber_t* v) { return z_undeclare_subscriber(v); } -template<> inline int8_t z_drop(z_owned_queryable_t* v) { return z_undeclare_queryable(v); } -template<> inline void z_drop(z_owned_encoding_t* v) { z_encoding_drop(v); } -template<> inline void z_drop(z_owned_reply_t* v) { z_reply_drop(v); } -template<> inline void z_drop(z_owned_hello_t* v) { z_hello_drop(v); } -template<> inline void z_drop(z_owned_query_t* v) { z_query_drop(v); } -template<> inline void z_drop(z_owned_str_t* v) { z_str_drop(v); } -template<> inline void z_drop(zc_owned_payload_t* v) { zc_payload_drop(v); } -template<> inline void z_drop(zc_owned_shmbuf_t* v) { zc_shmbuf_drop(v); } -template<> inline void z_drop(zc_owned_shm_manager_t* v) { zc_shm_manager_drop(v); } -template<> inline void z_drop(z_owned_closure_sample_t* v) { z_closure_sample_drop(v); } -template<> inline void z_drop(z_owned_closure_query_t* v) { z_closure_query_drop(v); } -template<> inline void z_drop(z_owned_closure_reply_t* v) { z_closure_reply_drop(v); } -template<> inline void z_drop(z_owned_closure_hello_t* v) { z_closure_hello_drop(v); } -template<> inline void z_drop(z_owned_closure_zid_t* v) { z_closure_zid_drop(v); } -template<> inline void z_drop(zcu_owned_closure_matching_status_t* v) { zcu_closure_matching_status_drop(v); } -template<> inline void z_drop(z_owned_reply_channel_closure_t* v) { z_reply_channel_closure_drop(v); } -template<> inline void z_drop(z_owned_reply_channel_t* v) { z_reply_channel_drop(v); } -template<> inline void z_drop(z_owned_bytes_map_t* v) { z_bytes_map_drop(v); } -template<> inline void z_drop(zc_owned_liveliness_token_t* v) { zc_liveliness_undeclare_token(v); } -template<> inline int8_t z_drop(ze_owned_publication_cache_t* v) { return ze_undeclare_publication_cache(v); } -template<> inline int8_t z_drop(ze_owned_querying_subscriber_t* v) { return ze_undeclare_querying_subscriber(v); } -inline void z_null(z_owned_session_t& v) { v = z_session_null(); } -inline void z_null(z_owned_publisher_t& v) { v = z_publisher_null(); } -inline void z_null(z_owned_keyexpr_t& v) { v = z_keyexpr_null(); } -inline void z_null(z_owned_config_t& v) { v = z_config_null(); } -inline void z_null(z_owned_scouting_config_t& v) { v = z_scouting_config_null(); } -inline void z_null(z_owned_pull_subscriber_t& v) { v = z_pull_subscriber_null(); } -inline void z_null(z_owned_subscriber_t& v) { v = z_subscriber_null(); } -inline void z_null(z_owned_queryable_t& v) { v = z_queryable_null(); } -inline void z_null(z_owned_encoding_t& v) { v = z_encoding_null(); } -inline void z_null(z_owned_reply_t& v) { v = z_reply_null(); } -inline void z_null(z_owned_hello_t& v) { v = z_hello_null(); } -inline void z_null(z_owned_query_t& v) { v = z_query_null(); } -inline void z_null(z_owned_str_t& v) { v = z_str_null(); } -inline void z_null(zc_owned_payload_t& v) { v = zc_payload_null(); } -inline void z_null(zc_owned_shmbuf_t& v) { v = zc_shmbuf_null(); } -inline void z_null(zc_owned_shm_manager_t& v) { v = zc_shm_manager_null(); } -inline void z_null(z_owned_closure_sample_t& v) { v = z_closure_sample_null(); } -inline void z_null(z_owned_closure_query_t& v) { v = z_closure_query_null(); } -inline void z_null(z_owned_closure_reply_t& v) { v = z_closure_reply_null(); } -inline void z_null(z_owned_closure_hello_t& v) { v = z_closure_hello_null(); } -inline void z_null(z_owned_closure_zid_t& v) { v = z_closure_zid_null(); } -inline void z_null(zcu_owned_closure_matching_status_t& v) { v = zcu_closure_matching_status_null(); } -inline void z_null(z_owned_reply_channel_closure_t& v) { v = z_reply_channel_closure_null(); } -inline void z_null(z_owned_reply_channel_t& v) { v = z_reply_channel_null(); } -inline void z_null(z_owned_bytes_map_t& v) { v = z_bytes_map_null(); } -inline void z_null(zc_owned_liveliness_token_t& v) { v = zc_liveliness_token_null(); } -inline void z_null(ze_owned_publication_cache_t& v) { v = ze_publication_cache_null(); } -inline void z_null(ze_owned_querying_subscriber_t& v) { v = ze_querying_subscriber_null(); } +inline bool z_check(const z_owned_bytes_t& payload) { return z_bytes_check(&payload); }; +inline bool z_check(const z_owned_bytes_reader_t& this_) { return z_bytes_reader_check(&this_); }; +inline bool z_check(const z_owned_condvar_t& this_) { return z_condvar_check(&this_); }; +inline bool z_check(const z_owned_config_t& config) { return z_config_check(&config); }; +inline bool z_check(const z_owned_encoding_t& encoding) { return z_encoding_check(&encoding); }; +inline bool z_check(const z_owned_hello_t& hello) { return z_hello_check(&hello); }; +inline bool z_check(const z_owned_keyexpr_t& keyexpr) { return z_keyexpr_check(&keyexpr); }; +inline bool z_check(const z_owned_mutex_t& this_) { return z_mutex_check(&this_); }; +inline bool z_check(const z_owned_slice_t& this_) { return z_owned_slice_check(&this_); }; +inline bool z_check(const z_owned_publisher_t& this_) { return z_publisher_check(&this_); }; +inline bool z_check(const z_owned_query_t& query) { return z_query_check(&query); }; +inline bool z_check(const z_owned_queryable_t& qable) { return z_queryable_check(&qable); }; +inline bool z_check(const z_owned_reply_t& this_) { return z_reply_check(&this_); }; +inline bool z_check(const z_owned_sample_t& sample) { return z_sample_check(&sample); }; +inline bool z_check(const z_owned_scouting_config_t& config) { return z_scouting_config_check(&config); }; +inline bool z_check(const z_owned_session_t& this_) { return z_session_check(&this_); }; +inline bool z_check(const z_owned_slice_map_t& map) { return z_slice_map_check(&map); }; +inline bool z_check(const z_owned_str_array_t& strs) { return z_str_array_check(&strs); }; +inline bool z_check(const z_owned_str_t& this_) { return z_str_check(&this_); }; +inline bool z_check(const z_owned_subscriber_t& subscriber) { return z_subscriber_check(&subscriber); }; +inline bool z_check(const z_owned_task_t& this_) { return z_task_check(&this_); }; +inline bool z_check(const z_view_keyexpr_t& keyexpr) { return z_view_keyexpr_check(&keyexpr); }; +inline bool z_check(const z_view_slice_t& this_) { return z_view_slice_check(&this_); }; +inline bool z_check(const zc_owned_liveliness_token_t& this_) { return zc_liveliness_token_check(&this_); }; +inline bool z_check(const zc_owned_shm_manager_t& manager) { return zc_shm_manager_check(&manager); }; +inline bool z_check(const zc_owned_shmbuf_t& buf) { return zc_shmbuf_check(&buf); }; +inline bool z_check(const ze_owned_publication_cache_t& this_) { return ze_publication_cache_check(&this_); }; +inline bool z_check(const ze_owned_querying_subscriber_t& this_) { return ze_querying_subscriber_check(&this_); }; -inline bool z_check(const z_owned_session_t& v) { return z_session_check(&v); } -inline bool z_check(const z_owned_publisher_t& v) { return z_publisher_check(&v); } -inline bool z_check(const z_owned_keyexpr_t& v) { return z_keyexpr_check(&v); } -inline bool z_check(const z_keyexpr_t& v) { return z_keyexpr_is_initialized(&v); } -inline bool z_check(const z_owned_config_t& v) { return z_config_check(&v); } -inline bool z_check(const z_owned_scouting_config_t& v) { return z_scouting_config_check(&v); } -inline bool z_check(const z_bytes_t& v) { return z_bytes_check(&v); } -inline bool z_check(const zc_owned_payload_t& v) { return zc_payload_check(&v); } -inline bool z_check(const zc_owned_shmbuf_t& v) { return zc_shmbuf_check(&v); } -inline bool z_check(const zc_owned_shm_manager_t& v) { return zc_shm_manager_check(&v); } -inline bool z_check(const z_owned_subscriber_t& v) { return z_subscriber_check(&v); } -inline bool z_check(const z_owned_pull_subscriber_t& v) { return z_pull_subscriber_check(&v); } -inline bool z_check(const z_owned_queryable_t& v) { return z_queryable_check(&v); } -inline bool z_check(const z_owned_encoding_t& v) { return z_encoding_check(&v); } -inline bool z_check(const z_owned_reply_t& v) { return z_reply_check(&v); } -inline bool z_check(const z_owned_hello_t& v) { return z_hello_check(&v); } -inline bool z_check(const z_owned_query_t& v) { return z_query_check(&v); } -inline bool z_check(const z_owned_str_t& v) { return z_str_check(&v); } -inline bool z_check(const z_owned_bytes_map_t& v) { return z_bytes_map_check(&v); } -inline bool z_check(const z_attachment_t& v) { return z_attachment_check(&v); } -inline bool z_check(const zc_owned_liveliness_token_t& v) { return zc_liveliness_token_check(&v); } -inline bool z_check(const ze_owned_publication_cache_t& v) { return ze_publication_cache_check(&v); } -inline bool z_check(const ze_owned_querying_subscriber_t& v) { return ze_querying_subscriber_check(&v); } -inline void z_call(const struct z_owned_closure_sample_t &closure, const struct z_sample_t *sample) - { z_closure_sample_call(&closure, sample); } -inline void z_call(const struct z_owned_closure_query_t &closure, const struct z_query_t *query) - { z_closure_query_call(&closure, query); } -inline void z_call(const struct z_owned_closure_reply_t &closure, struct z_owned_reply_t *sample) - { z_closure_reply_call(&closure, sample); } -inline void z_call(const struct z_owned_closure_hello_t &closure, struct z_owned_hello_t *hello) - { z_closure_hello_call(&closure, hello); } -inline void z_call(const struct z_owned_closure_zid_t &closure, const struct z_id_t *zid) - { z_closure_zid_call(&closure, zid); } -inline void z_call(const struct zcu_owned_closure_matching_status_t &closure, const struct zcu_matching_status_t *matching_status) - { zcu_closure_matching_status_call(&closure, matching_status); } -inline bool z_call(const struct z_owned_reply_channel_closure_t &closure, struct z_owned_reply_t *sample) - { return z_reply_channel_closure_call(&closure, sample); } -// clang-format on +inline void z_call(const z_owned_closure_hello_t& closure, z_owned_hello_t* hello) { + return z_closure_hello_call(&closure, hello); +}; +inline void z_call(const z_owned_closure_owned_query_t& closure, z_owned_query_t* query) { + return z_closure_owned_query_call(&closure, query); +}; +inline void z_call(const z_owned_closure_query_t& closure, const z_loaned_query_t* query) { + return z_closure_query_call(&closure, query); +}; +inline void z_call(const z_owned_closure_reply_t& closure, const z_loaned_reply_t* reply) { + return z_closure_reply_call(&closure, reply); +}; +inline void z_call(const z_owned_closure_sample_t& closure, const z_loaned_sample_t* sample) { + return z_closure_sample_call(&closure, sample); +}; +inline void z_call(const z_owned_closure_zid_t& closure, const z_id_t* sample) { + return z_closure_zid_call(&closure, sample); +}; +inline bool z_call(const z_owned_query_channel_closure_t& closure, z_owned_query_t* query) { + return z_query_channel_closure_call(&closure, query); +}; +inline bool z_call(const z_owned_reply_channel_closure_t& closure, z_owned_reply_t* reply) { + return z_reply_channel_closure_call(&closure, reply); +}; +inline void z_call(const zcu_owned_closure_matching_status_t& closure, const zcu_matching_status_t* sample) { + return zcu_closure_matching_status_call(&closure, sample); +}; -#define _z_closure_overloader(callback, droper, ctx, ...) \ - { .context = const_cast(static_cast(ctx)), .call = callback, .drop = droper } -#define z_closure(...) _z_closure_overloader(__VA_ARGS__, NULL, NULL) -#define z_move(x) (&x) -#endif // #ifndef __cplusplus +inline void z_closure( + z_owned_closure_hello_t* closure, + void (*call)( z_owned_hello_t*, void*), + void (*drop)(void*), + void *context) { + closure->context = context; + closure->drop = drop; + closure->call = call; +}; +inline void z_closure( + z_owned_closure_owned_query_t* closure, + void (*call)( z_owned_query_t*, void*), + void (*drop)(void*), + void *context) { + closure->context = context; + closure->drop = drop; + closure->call = call; +}; +inline void z_closure( + z_owned_closure_query_t* closure, + void (*call)(const z_loaned_query_t*, void*), + void (*drop)(void*), + void *context) { + closure->context = context; + closure->drop = drop; + closure->call = call; +}; +inline void z_closure( + z_owned_closure_reply_t* closure, + void (*call)(const z_loaned_reply_t*, void*), + void (*drop)(void*), + void *context) { + closure->context = context; + closure->drop = drop; + closure->call = call; +}; +inline void z_closure( + z_owned_closure_sample_t* closure, + void (*call)(const z_loaned_sample_t*, void*), + void (*drop)(void*), + void *context) { + closure->context = context; + closure->drop = drop; + closure->call = call; +}; +inline void z_closure( + z_owned_closure_zid_t* closure, + void (*call)(const z_id_t*, void*), + void (*drop)(void*), + void *context) { + closure->context = context; + closure->drop = drop; + closure->call = call; +}; +inline void z_closure( + z_owned_query_channel_closure_t* closure, + bool (*call)( z_owned_query_t*, void*), + void (*drop)(void*), + void *context) { + closure->context = context; + closure->drop = drop; + closure->call = call; +}; +inline void z_closure( + z_owned_reply_channel_closure_t* closure, + bool (*call)( z_owned_reply_t*, void*), + void (*drop)(void*), + void *context) { + closure->context = context; + closure->drop = drop; + closure->call = call; +}; +inline void z_closure( + zcu_owned_closure_matching_status_t* closure, + void (*call)(const zcu_matching_status_t*, void*), + void (*drop)(void*), + void *context) { + closure->context = context; + closure->drop = drop; + closure->call = call; +}; +#endif // #ifndef __cplusplus \ No newline at end of file diff --git a/splitguide.yaml b/splitguide.yaml index 4cb19de82..6614c0356 100644 --- a/splitguide.yaml +++ b/splitguide.yaml @@ -7,8 +7,7 @@ zenoh_concrete.h: - :includes - :defines - z_owned_session_t! - - z_session_t! + - z_loaned_session_t! - z_owned_subscriber_t! - - z_owned_pull_subscriber_t! - - z_query_t! + - z_loaned_query_t! - z_owned_queryable_t! diff --git a/src/attachment.rs b/src/attachment.rs deleted file mode 100644 index 5b327fe66..000000000 --- a/src/attachment.rs +++ /dev/null @@ -1,414 +0,0 @@ -use std::{borrow::Cow, cell::UnsafeCell, collections::HashMap}; - -use libc::c_void; - -use crate::{impl_guarded_transmute, z_bytes_null, z_bytes_t}; - -use zenoh::sample::{Attachment, AttachmentBuilder}; - -/// The body of a loop over an attachment's key-value pairs. -/// -/// `key` and `value` are loaned to the body for the duration of a single call. -/// `context` is passed transparently through the iteration driver. -/// -/// Returning `0` is treated as `continue`. -/// Returning any other value is treated as `break`. -pub type z_attachment_iter_body_t = - extern "C" fn(key: z_bytes_t, value: z_bytes_t, context: *mut c_void) -> i8; - -/// The driver of a loop over an attachment's key-value pairs. -/// -/// This function is expected to call `loop_body` once for each key-value pair -/// within `iterator`, passing `context`, and returning any non-zero value immediately (breaking iteration). -pub type z_attachment_iter_driver_t = Option< - extern "C" fn( - iterator: *const c_void, - loop_body: z_attachment_iter_body_t, - context: *mut c_void, - ) -> i8, ->; - -/// A iteration based map of byte slice to byte slice. -/// -/// `iteration_driver == NULL` marks the gravestone value, as this type is often optional. -/// Users are encouraged to use `z_attachment_null` and `z_attachment_check` to interact. -#[repr(C)] -#[derive(Clone, Copy)] -pub struct z_attachment_t { - pub data: *const c_void, - pub iteration_driver: z_attachment_iter_driver_t, -} - -/// Returns the gravestone value for `z_attachment_t`. -#[no_mangle] -pub extern "C" fn z_attachment_check(this: &z_attachment_t) -> bool { - this.iteration_driver.is_some() -} - -/// Returns the gravestone value for `z_attachment_t`. -#[no_mangle] -pub extern "C" fn z_attachment_null() -> z_attachment_t { - z_attachment_t { - data: core::ptr::null_mut(), - iteration_driver: None, - } -} - -/// Iterate over `this`'s key-value pairs, breaking if `body` returns a non-zero -/// value for a key-value pair, and returning the latest return value. -/// -/// `context` is passed to `body` to allow stateful closures. -/// -/// This function takes no ownership whatsoever. -#[no_mangle] -pub extern "C" fn z_attachment_iterate( - this: z_attachment_t, - body: z_attachment_iter_body_t, - context: *mut c_void, -) -> i8 { - if let Some(driver) = this.iteration_driver { - return driver(this.data, body, context); - } - log::error!("Invalid iteration_driver"); - i8::MIN -} - -/// Returns the value associated with the key. -#[no_mangle] -pub extern "C" fn z_attachment_get(this: z_attachment_t, key: z_bytes_t) -> z_bytes_t { - struct attachment_get_iterator_context { - key: z_bytes_t, - value: z_bytes_t, - } - - extern "C" fn attachment_get_iterator( - key: z_bytes_t, - value: z_bytes_t, - context: *mut c_void, - ) -> i8 { - unsafe { - let context = &mut *(context as *mut attachment_get_iterator_context); - if context.key.as_slice() == key.as_slice() { - context.value = value; - 1 - } else { - 0 - } - } - } - - let mut context = attachment_get_iterator_context { - key, - value: z_bytes_null(), - }; - - if this.iteration_driver.map_or(false, |iteration_driver| { - (iteration_driver)( - this.data, - attachment_get_iterator, - &mut context as *mut _ as *mut c_void, - ) != 0 - }) { - context.value - } else { - z_bytes_null() - } -} - -fn _z_attachment_len(this: z_attachment_t, check_if_non_empty: bool) -> usize { - match this.iteration_driver.as_ref() { - None => 0, - Some(iteration_driver) => { - struct count_context_t { - count: usize, - stop_if_not_empty: bool, - } - - extern "C" fn attachment_count_iterator( - _key: z_bytes_t, - _value: z_bytes_t, - context: *mut c_void, - ) -> i8 { - unsafe { - let context = &mut *(context as *mut count_context_t); - context.count += 1; - if context.stop_if_not_empty { - 1 - } else { - 0 - } - } - } - let mut count_context = count_context_t { - count: 0, - stop_if_not_empty: check_if_non_empty, - }; - (iteration_driver)( - this.data, - attachment_count_iterator, - &mut count_context as *mut _ as *mut c_void, - ); - count_context.count - } - } -} - -/// Returns number of key-value pairs for `z_attachment_t`. -/// -/// Does so by iterating over all existing key-value pairs. -#[no_mangle] -pub extern "C" fn z_attachment_len(this: z_attachment_t) -> usize { - _z_attachment_len(this, false) -} - -/// Returns true if `z_attachment_t` contains no key-value pairs, false otherwise. -#[no_mangle] -pub extern "C" fn z_attachment_is_empty(this: z_attachment_t) -> bool { - _z_attachment_len(this, true) == 0 -} - -/// A map of maybe-owned vector of bytes to owned vector of bytes. -/// -/// In Zenoh C, this map is backed by Rust's standard HashMap, with a DoS-resistant hasher -#[repr(C)] -pub struct z_owned_bytes_map_t { - _0: [u64; 2], - _1: [usize; 4], -} - -impl_guarded_transmute!(noderefs - Option, Cow<'static, [u8]>>>, - z_owned_bytes_map_t -); - -impl core::ops::Deref for z_owned_bytes_map_t { - type Target = UnsafeCell, Cow<'static, [u8]>>>>; - fn deref(&self) -> &Self::Target { - unsafe { core::mem::transmute(self) } - } -} - -/// Constructs a new map. -#[no_mangle] -pub extern "C" fn z_bytes_map_new() -> z_owned_bytes_map_t { - unsafe { core::mem::transmute(Some(HashMap::, Cow<[u8]>>::new())) } -} - -/// Constructs the gravestone value for `z_owned_bytes_map_t` -#[no_mangle] -pub extern "C" fn z_bytes_map_null() -> z_owned_bytes_map_t { - unsafe { core::mem::transmute(None::, Cow<[u8]>>>) } -} - -/// Returns `true` if the map is not in its gravestone state -#[no_mangle] -pub extern "C" fn z_bytes_map_check(this: &z_owned_bytes_map_t) -> bool { - unsafe { &*this.get() }.is_some() -} -/// Destroys the map, resetting `this` to its gravestone value. -/// -/// This function is double-free safe, passing a pointer to the gravestone value will have no effect. -#[no_mangle] -pub extern "C" fn z_bytes_map_drop(this: &mut z_owned_bytes_map_t) { - let this = unsafe { &mut *this.get() }; - this.take(); -} - -/// Returns number of key-value pairs in the map. -#[no_mangle] -pub extern "C" fn z_bytes_map_len(this: &mut z_owned_bytes_map_t) -> usize { - let this = unsafe { &*this.get() }; - this.as_ref().map(|m| m.len()).unwrap_or(0) -} - -/// Returns true if the map is empty, false otherwise. -#[no_mangle] -pub extern "C" fn z_bytes_map_is_empty(this: &mut z_owned_bytes_map_t) -> bool { - let this = unsafe { &*this.get() }; - this.as_ref().map(|m| m.is_empty()).unwrap_or(true) -} - -/// Returns the value associated with `key`, returning a gravestone value if: -/// - `this` or `key` is in gravestone state. -/// - `this` has no value associated to `key` -#[no_mangle] -pub extern "C" fn z_bytes_map_get(this: &z_owned_bytes_map_t, key: z_bytes_t) -> z_bytes_t { - let this = unsafe { &*this.get() }; - let (Some(this), Some(key)) = (this.as_ref(), key.as_slice()) else { - return z_bytes_null(); - }; - if let Some(value) = this.get(key) { - value.as_ref().into() - } else { - z_bytes_null() - } -} - -/// Associates `value` to `key` in the map, copying them to obtain ownership: `key` and `value` are not aliased past the function's return. -/// -/// Calling this with `NULL` or the gravestone value is undefined behaviour. -#[no_mangle] -pub extern "C" fn z_bytes_map_insert_by_copy( - this: &z_owned_bytes_map_t, - key: z_bytes_t, - value: z_bytes_t, -) { - let this = unsafe { &mut *this.get() }; - if let (Some(this), Some(key), Some(value)) = (this.as_mut(), key.as_slice(), value.as_slice()) - { - this.insert(Cow::Owned(key.to_owned()), Cow::Owned(value.to_owned())); - } -} - -/// Associates `value` to `key` in the map, aliasing them. -/// -/// Note that once `key` is aliased, reinserting at the same key may alias the previous instance, or the new instance of `key`. -/// -/// Calling this with `NULL` or the gravestone value is undefined behaviour. -#[no_mangle] -pub extern "C" fn z_bytes_map_insert_by_alias( - this: &z_owned_bytes_map_t, - key: z_bytes_t, - value: z_bytes_t, -) { - let this = unsafe { &mut *this.get() }; - if let (Some(this), Some(key), Some(value)) = (this.as_mut(), key.as_slice(), value.as_slice()) - { - unsafe { - this.insert( - Cow::Borrowed(core::mem::transmute(key)), - Cow::Borrowed(core::mem::transmute(value)), - ) - }; - } -} - -/// Iterates over the key-value pairs in the map. -/// -/// `body` will be called once per pair, with `ctx` as its last argument. -/// If `body` returns a non-zero value, the iteration will stop immediately and the value will be returned. -/// Otherwise, this will return 0 once all pairs have been visited. -/// `body` is not given ownership of the key nor value, which alias the pairs in the map. -/// It is safe to keep these aliases until existing keys are modified/removed, or the map is destroyed. -/// Note that this map is unordered. -/// -/// Calling this with `NULL` or the gravestone value is undefined behaviour. -#[no_mangle] -pub extern "C" fn z_bytes_map_iter( - this: &z_owned_bytes_map_t, - body: z_attachment_iter_body_t, - ctx: *mut c_void, -) -> i8 { - let this = unsafe { &*this.get() }; - if let Some(this) = this.as_ref() { - for (key, value) in this.iter() { - let result = body(key.as_ref().into(), value.as_ref().into(), ctx); - if result != 0 { - return result; - } - } - } - 0 -} - -const Z_BYTES_MAP_ITERATION_DRIVER: z_attachment_iter_driver_t = - Some(unsafe { core::mem::transmute(z_bytes_map_iter as extern "C" fn(_, _, _) -> i8) }); - -pub(crate) extern "C" fn insert_in_attachment_builder( - key: z_bytes_t, - value: z_bytes_t, - ctx: *mut c_void, -) -> i8 { - let attachment_builder_ref: &mut AttachmentBuilder = - unsafe { &mut *(ctx as *mut AttachmentBuilder) }; - attachment_builder_ref.insert(key.as_slice().unwrap(), value.as_slice().unwrap()); - 0 -} - -pub(crate) extern "C" fn attachment_iteration_driver( - this: *const c_void, - body: z_attachment_iter_body_t, - ctx: *mut c_void, -) -> i8 { - let attachments_ref: &Attachment = unsafe { &*(this as *mut Attachment) }; - for (key, value) in attachments_ref.iter() { - let result = body(key.as_ref().into(), value.as_ref().into(), ctx); - if result != 0 { - return result; - } - } - 0 -} - -/// Aliases `this` into a generic `z_attachment_t`, allowing it to be passed to corresponding APIs. -#[no_mangle] -pub extern "C" fn z_bytes_map_as_attachment(this: &z_owned_bytes_map_t) -> z_attachment_t { - if z_bytes_map_check(this) { - z_attachment_t { - data: this as *const z_owned_bytes_map_t as *mut _, - iteration_driver: Z_BYTES_MAP_ITERATION_DRIVER, - } - } else { - z_attachment_t { - data: core::ptr::null_mut(), - iteration_driver: None, - } - } -} - -extern "C" fn bytes_map_from_attachment_iterator( - key: z_bytes_t, - value: z_bytes_t, - ctx: *mut c_void, -) -> i8 { - let map = unsafe { &*ctx.cast::() }; - z_bytes_map_insert_by_copy(map, key, value); - 0 -} -extern "C" fn bytes_map_from_attachment_iterator_by_alias( - key: z_bytes_t, - value: z_bytes_t, - ctx: *mut c_void, -) -> i8 { - let map = unsafe { &*ctx.cast::() }; - z_bytes_map_insert_by_alias(map, key, value); - 0 -} - -/// Constructs a map from the provided attachment, copying keys and values. -/// -/// If `this` is at gravestone value, the returned value will also be at gravestone value. -#[no_mangle] -pub extern "C" fn z_bytes_map_from_attachment(this: z_attachment_t) -> z_owned_bytes_map_t { - if z_attachment_check(&this) { - let mut map = z_bytes_map_new(); - z_attachment_iterate( - this, - bytes_map_from_attachment_iterator, - &mut map as *mut _ as *mut _, - ); - map - } else { - z_bytes_map_null() - } -} - -/// Constructs a map from the provided attachment, aliasing the attachment's keys and values. -/// -/// If `this` is at gravestone value, the returned value will also be at gravestone value. -#[no_mangle] -pub extern "C" fn z_bytes_map_from_attachment_aliasing( - this: z_attachment_t, -) -> z_owned_bytes_map_t { - if z_attachment_check(&this) { - let mut map = z_bytes_map_new(); - z_attachment_iterate( - this, - bytes_map_from_attachment_iterator_by_alias, - &mut map as *mut _ as *mut _, - ); - map - } else { - z_bytes_map_null() - } -} diff --git a/src/closures/query_channel.rs b/src/closures/query_channel.rs index b7a51c9c0..c4bf36a2a 100644 --- a/src/closures/query_channel.rs +++ b/src/closures/query_channel.rs @@ -1,6 +1,12 @@ -use crate::{z_closure_owned_query_drop, z_owned_closure_owned_query_t, z_owned_query_t}; +use crate::{ + z_closure_query_drop, z_loaned_query_t, z_owned_closure_query_t, z_owned_query_t, + z_query_clone, z_query_null, +}; use libc::c_void; -use std::sync::mpsc::TryRecvError; +use std::{ + mem::MaybeUninit, + sync::mpsc::{Receiver, TryRecvError}, +}; /// A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks: /// - `this` is a pointer to an arbitrary state. @@ -16,49 +22,40 @@ use std::sync::mpsc::TryRecvError; #[repr(C)] pub struct z_owned_query_channel_closure_t { context: *mut c_void, - call: Option bool>, + call: Option, *mut c_void) -> bool>, drop: Option, } /// A pair of closures #[repr(C)] pub struct z_owned_query_channel_t { - pub send: z_owned_closure_owned_query_t, + pub send: z_owned_closure_query_t, pub recv: z_owned_query_channel_closure_t, } #[no_mangle] pub extern "C" fn z_query_channel_drop(channel: &mut z_owned_query_channel_t) { - z_closure_owned_query_drop(&mut channel.send); + z_closure_query_drop(&mut channel.send); z_query_channel_closure_drop(&mut channel.recv); } /// Constructs a null safe-to-drop value of 'z_owned_query_channel_t' type #[no_mangle] pub extern "C" fn z_query_channel_null() -> z_owned_query_channel_t { z_owned_query_channel_t { - send: z_owned_closure_owned_query_t::empty(), + send: z_owned_closure_query_t::empty(), recv: z_owned_query_channel_closure_t::empty(), } } -/// Creates a new blocking fifo channel, returned as a pair of closures. -/// -/// If `bound` is different from 0, that channel will be bound and apply back-pressure when full. -/// -/// The `send` end should be passed as callback to a `z_get` call. -/// -/// The `recv` end is a synchronous closure that will block until either a `z_owned_query_t` is available, -/// which it will then return; or until the `send` closure is dropped and all queries have been consumed, -/// at which point it will return an invalidated `z_owned_query_t`, and so will further calls. -#[no_mangle] -pub extern "C" fn zc_query_fifo_new(bound: usize) -> z_owned_query_channel_t { - let (send, rx) = if bound == 0 { +unsafe fn get_send_recv_ends(bound: usize) -> (z_owned_closure_query_t, Receiver) { + if bound == 0 { let (tx, rx) = std::sync::mpsc::channel(); ( - From::from(move |query: &mut z_owned_query_t| { - if let Some(query) = query.take() { - if let Err(e) = tx.send(query) { - log::error!("Attempted to push onto a closed query_fifo: {}", e) - } + From::from(move |query: &z_loaned_query_t| { + let mut this = MaybeUninit::::uninit(); + z_query_clone(query, &mut this as *mut MaybeUninit); + let this = this.assume_init(); + if let Err(e) = tx.send(this) { + log::error!("Attempted to push onto a closed reply_fifo: {}", e); } }), rx, @@ -66,23 +63,40 @@ pub extern "C" fn zc_query_fifo_new(bound: usize) -> z_owned_query_channel_t { } else { let (tx, rx) = std::sync::mpsc::sync_channel(bound); ( - From::from(move |query: &mut z_owned_query_t| { - if let Some(query) = query.take() { - if let Err(e) = tx.send(query) { - log::error!("Attempted to push onto a closed query_fifo: {}", e) - } + From::from(move |query: &z_loaned_query_t| { + let mut this = MaybeUninit::::uninit(); + z_query_clone(query, &mut this as *mut MaybeUninit); + let this = this.assume_init(); + if let Err(e) = tx.send(this) { + log::error!("Attempted to push onto a closed reply_fifo: {}", e); } }), rx, ) - }; + } +} + +/// Creates a new blocking fifo channel, returned as a pair of closures. +/// +/// If `bound` is different from 0, that channel will be bound and apply back-pressure when full. +/// +/// The `send` end should be passed as callback to a `z_get` call. +/// +/// The `recv` end is a synchronous closure that will block until either a `z_owned_query_t` is available, +/// which it will then return; or until the `send` closure is dropped and all queries have been consumed, +/// at which point it will return an invalidated `z_owned_query_t`, and so will further calls. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_query_fifo_new(bound: usize) -> z_owned_query_channel_t { + let (send, rx) = get_send_recv_ends(bound); z_owned_query_channel_t { send, - recv: From::from(move |receptacle: &mut z_owned_query_t| { - *receptacle = match rx.recv() { - Ok(val) => val.into(), - Err(_) => None.into(), - }; + recv: From::from(move |this: *mut MaybeUninit| { + if let Ok(val) = rx.recv() { + (*this).write(val); + } else { + z_query_null(this); + } true }), } @@ -98,47 +112,23 @@ pub extern "C" fn zc_query_fifo_new(bound: usize) -> z_owned_query_channel_t { /// which it will then return; or until the `send` closure is dropped and all queries have been consumed, /// at which point it will return an invalidated `z_owned_query_t`, and so will further calls. #[no_mangle] -pub extern "C" fn zc_query_non_blocking_fifo_new(bound: usize) -> z_owned_query_channel_t { - let (send, rx) = if bound == 0 { - let (tx, rx) = std::sync::mpsc::channel(); - ( - From::from(move |query: &mut z_owned_query_t| { - if let Some(query) = query.take() { - if let Err(e) = tx.send(query) { - log::error!("Attempted to push onto a closed query_fifo: {}", e) - } - } - }), - rx, - ) - } else { - let (tx, rx) = std::sync::mpsc::sync_channel(bound); - ( - From::from(move |query: &mut z_owned_query_t| { - if let Some(query) = query.take() { - if let Err(e) = tx.send(query) { - log::error!("Attempted to push onto a closed query_fifo: {}", e) - } - } - }), - rx, - ) - }; +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_query_non_blocking_fifo_new(bound: usize) -> z_owned_query_channel_t { + let (send, rx) = get_send_recv_ends(bound); z_owned_query_channel_t { send, recv: From::from( - move |receptacle: &mut z_owned_query_t| match rx.try_recv() { + move |this: *mut MaybeUninit| match rx.try_recv() { Ok(val) => { - let mut tmp = z_owned_query_t::from(val); - std::mem::swap(&mut tmp, receptacle); + (*this).write(val); true } Err(TryRecvError::Disconnected) => { - receptacle.take(); + z_query_null(this); true } Err(TryRecvError::Empty) => { - receptacle.take(); + z_query_null(this); false } }, @@ -175,10 +165,10 @@ pub extern "C" fn z_query_channel_closure_null() -> z_owned_query_channel_closur #[no_mangle] pub extern "C" fn z_query_channel_closure_call( closure: &z_owned_query_channel_closure_t, - sample: &mut z_owned_query_t, + query: *mut MaybeUninit, ) -> bool { match closure.call { - Some(call) => call(sample, closure.context), + Some(call) => call(query, closure.context), None => { log::error!("Attempted to call an uninitialized closure!"); true @@ -191,11 +181,11 @@ pub extern "C" fn z_query_channel_closure_drop(closure: &mut z_owned_query_chann let mut empty_closure = z_owned_query_channel_closure_t::empty(); std::mem::swap(&mut empty_closure, closure); } -impl bool> From for z_owned_query_channel_closure_t { +impl) -> bool> From for z_owned_query_channel_closure_t { fn from(f: F) -> Self { let this = Box::into_raw(Box::new(f)) as _; - extern "C" fn call bool>( - query: &mut z_owned_query_t, + extern "C" fn call) -> bool>( + query: *mut MaybeUninit, this: *mut c_void, ) -> bool { let this = unsafe { &*(this as *const F) }; diff --git a/src/closures/query_closure.rs b/src/closures/query_closure.rs index 22ad4bc28..98f774cd8 100644 --- a/src/closures/query_closure.rs +++ b/src/closures/query_closure.rs @@ -1,10 +1,10 @@ -use crate::{z_owned_query_t, z_query_t}; +use crate::{z_loaned_query_t, z_owned_query_t}; use libc::c_void; /// A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks: /// /// Members: /// void *context: a pointer to an arbitrary state. -/// void *call(const struct z_query_t*, const void *context): the typical callback function. `context` will be passed as its last argument. +/// void *call(z_loaned_query_t, const void *context): the typical callback function. `context` will be passed as its last argument. /// void *drop(void*): allows the callback's state to be freed. /// /// Closures are not guaranteed not to be called concurrently. @@ -17,7 +17,7 @@ use libc::c_void; #[repr(C)] pub struct z_owned_closure_query_t { context: *mut c_void, - call: Option, + call: Option, drop: Option, } impl z_owned_closure_query_t { @@ -45,7 +45,10 @@ pub extern "C" fn z_closure_query_null() -> z_owned_closure_query_t { } /// Calls the closure. Calling an uninitialized closure is a no-op. #[no_mangle] -pub extern "C" fn z_closure_query_call(closure: &z_owned_closure_query_t, query: &z_query_t) { +pub extern "C" fn z_closure_query_call( + closure: &z_owned_closure_query_t, + query: &z_loaned_query_t, +) { match closure.call { Some(call) => call(query, closure.context), None => log::error!("Attempted to call an uninitialized closure!"), @@ -57,12 +60,15 @@ pub extern "C" fn z_closure_query_drop(closure: &mut z_owned_closure_query_t) { let mut empty_closure = z_owned_closure_query_t::empty(); std::mem::swap(&mut empty_closure, closure); } -impl From for z_owned_closure_query_t { +impl From for z_owned_closure_query_t { fn from(f: F) -> Self { let this = Box::into_raw(Box::new(f)) as _; - extern "C" fn call(sample: &z_query_t, this: *mut c_void) { + extern "C" fn call( + query: *const z_loaned_query_t, + this: *mut c_void, + ) { let this = unsafe { &*(this as *const F) }; - this(sample) + unsafe { this(query.as_ref().unwrap()) } } extern "C" fn drop(this: *mut c_void) { std::mem::drop(unsafe { Box::from_raw(this as *mut F) }) @@ -79,7 +85,7 @@ impl From for z_owned_closure_query_t { /// /// Members: /// void *context: a pointer to an arbitrary state. -/// void *call(const struct z_query_t*, const void *context): the typical callback function. `context` will be passed as its last argument. +/// void *call(const struct z_loaned_query_t*, const void *context): the typical callback function. `context` will be passed as its last argument. /// void *drop(void*): allows the callback's state to be freed. /// /// Closures are not guaranteed not to be called concurrently. diff --git a/src/closures/reply_closure.rs b/src/closures/reply_closure.rs index 1aa8a9b44..d41c6580a 100644 --- a/src/closures/reply_closure.rs +++ b/src/closures/reply_closure.rs @@ -1,4 +1,4 @@ -use crate::z_owned_reply_t; +use crate::z_loaned_reply_t; use libc::c_void; /// A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks: /// @@ -17,7 +17,7 @@ use libc::c_void; #[repr(C)] pub struct z_owned_closure_reply_t { context: *mut c_void, - call: Option, + call: Option, drop: Option, } @@ -48,10 +48,10 @@ pub extern "C" fn z_closure_reply_null() -> z_owned_closure_reply_t { #[no_mangle] pub extern "C" fn z_closure_reply_call( closure: &z_owned_closure_reply_t, - sample: &mut z_owned_reply_t, + reply: &z_loaned_reply_t, ) { match closure.call { - Some(call) => call(sample, closure.context), + Some(call) => call(reply, closure.context), None => { log::error!("Attempted to call an uninitialized closure!"); } @@ -63,15 +63,15 @@ pub extern "C" fn z_closure_reply_drop(closure: &mut z_owned_closure_reply_t) { let mut empty_closure = z_owned_closure_reply_t::empty(); std::mem::swap(&mut empty_closure, closure); } -impl From for z_owned_closure_reply_t { +impl From for z_owned_closure_reply_t { fn from(f: F) -> Self { let this = Box::into_raw(Box::new(f)) as _; - extern "C" fn call( - response: &mut z_owned_reply_t, + extern "C" fn call( + response: *const z_loaned_reply_t, this: *mut c_void, ) { let this = unsafe { &*(this as *const F) }; - this(response) + unsafe { this(response.as_ref().unwrap()) } } extern "C" fn drop(this: *mut c_void) { std::mem::drop(unsafe { Box::from_raw(this as *mut F) }) diff --git a/src/closures/response_channel.rs b/src/closures/response_channel.rs index 0ea046d5d..4b0d52123 100644 --- a/src/closures/response_channel.rs +++ b/src/closures/response_channel.rs @@ -1,6 +1,12 @@ -use crate::{z_closure_reply_drop, z_owned_closure_reply_t, z_owned_reply_t}; +use crate::{ + z_closure_reply_drop, z_loaned_reply_t, z_owned_closure_reply_t, z_owned_reply_t, + z_reply_clone, z_reply_null, +}; use libc::c_void; -use std::sync::mpsc::TryRecvError; +use std::{ + mem::MaybeUninit, + sync::mpsc::{Receiver, TryRecvError}, +}; /// A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks: /// - `this` is a pointer to an arbitrary state. /// - `call` is the typical callback function. `this` will be passed as its last argument. @@ -15,7 +21,7 @@ use std::sync::mpsc::TryRecvError; #[repr(C)] pub struct z_owned_reply_channel_closure_t { context: *mut c_void, - call: Option bool>, + call: Option, *mut c_void) -> bool>, drop: Option, } @@ -39,25 +45,16 @@ pub extern "C" fn z_reply_channel_null() -> z_owned_reply_channel_t { } } -/// Creates a new blocking fifo channel, returned as a pair of closures. -/// -/// If `bound` is different from 0, that channel will be bound and apply back-pressure when full. -/// -/// The `send` end should be passed as callback to a `z_get` call. -/// -/// The `recv` end is a synchronous closure that will block until either a `z_owned_reply_t` is available, -/// which it will then return; or until the `send` closure is dropped and all replies have been consumed, -/// at which point it will return an invalidated `z_owned_reply_t`, and so will further calls. -#[no_mangle] -pub extern "C" fn zc_reply_fifo_new(bound: usize) -> z_owned_reply_channel_t { - let (send, rx) = if bound == 0 { +unsafe fn get_send_recv_ends(bound: usize) -> (z_owned_closure_reply_t, Receiver) { + if bound == 0 { let (tx, rx) = std::sync::mpsc::channel(); ( - From::from(move |reply: &mut z_owned_reply_t| { - if let Some(reply) = reply.take() { - if let Err(e) = tx.send(reply) { - log::error!("Attempted to push onto a closed reply_fifo: {}", e) - } + From::from(move |reply: &z_loaned_reply_t| { + let mut this = MaybeUninit::::uninit(); + z_reply_clone(&mut this as *mut MaybeUninit, reply); + let this = this.assume_init(); + if let Err(e) = tx.send(this) { + log::error!("Attempted to push onto a closed reply_fifo: {}", e); } }), rx, @@ -65,23 +62,39 @@ pub extern "C" fn zc_reply_fifo_new(bound: usize) -> z_owned_reply_channel_t { } else { let (tx, rx) = std::sync::mpsc::sync_channel(bound); ( - From::from(move |reply: &mut z_owned_reply_t| { - if let Some(reply) = reply.take() { - if let Err(e) = tx.send(reply) { - log::error!("Attempted to push onto a closed reply_fifo: {}", e) - } + From::from(move |reply: &z_loaned_reply_t| { + let mut this = MaybeUninit::::uninit(); + z_reply_clone(&mut this as *mut MaybeUninit, reply); + let this = this.assume_init(); + if let Err(e) = tx.send(this) { + log::error!("Attempted to push onto a closed reply_fifo: {}", e); } }), rx, ) - }; + } +} +/// Creates a new blocking fifo channel, returned as a pair of closures. +/// +/// If `bound` is different from 0, that channel will be bound and apply back-pressure when full. +/// +/// The `send` end should be passed as callback to a `z_get` call. +/// +/// The `recv` end is a synchronous closure that will block until either a `z_owned_reply_t` is available, +/// which it will then return; or until the `send` closure is dropped and all replies have been consumed, +/// at which point it will return an invalidated `z_owned_reply_t`, and so will further calls. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_reply_fifo_new(bound: usize) -> z_owned_reply_channel_t { + let (send, rx) = get_send_recv_ends(bound); z_owned_reply_channel_t { send, - recv: From::from(move |receptacle: &mut z_owned_reply_t| { - *receptacle = match rx.recv() { - Ok(val) => val.into(), - Err(_) => None.into(), - }; + recv: From::from(move |this: *mut MaybeUninit| { + if let Ok(val) = rx.recv() { + (*this).write(val); + } else { + z_reply_null(this); + } true }), } @@ -97,48 +110,23 @@ pub extern "C" fn zc_reply_fifo_new(bound: usize) -> z_owned_reply_channel_t { /// which it will then return; or until the `send` closure is dropped and all replies have been consumed, /// at which point it will return an invalidated `z_owned_reply_t`, and so will further calls. #[no_mangle] -pub extern "C" fn zc_reply_non_blocking_fifo_new(bound: usize) -> z_owned_reply_channel_t { - let (send, rx) = if bound == 0 { - let (tx, rx) = std::sync::mpsc::channel(); - ( - From::from(move |reply: &mut z_owned_reply_t| { - if let Some(reply) = reply.take() { - if let Err(e) = tx.send(reply) { - log::error!("Attempted to push onto a closed reply_fifo: {}", e) - } - } - }), - rx, - ) - } else { - let (tx, rx) = std::sync::mpsc::sync_channel(bound); - ( - From::from(move |reply: &mut z_owned_reply_t| { - if let Some(reply) = reply.take() { - if let Err(e) = tx.send(reply) { - log::error!("Attempted to push onto a closed reply_fifo: {}", e) - } - } - }), - rx, - ) - }; - +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_reply_non_blocking_fifo_new(bound: usize) -> z_owned_reply_channel_t { + let (send, rx) = get_send_recv_ends(bound); z_owned_reply_channel_t { send, recv: From::from( - move |receptacle: &mut z_owned_reply_t| match rx.try_recv() { + move |this: *mut MaybeUninit| match rx.try_recv() { Ok(val) => { - let mut tmp = z_owned_reply_t::from(val); - std::mem::swap(&mut tmp, receptacle); + (*this).write(val); true } Err(TryRecvError::Disconnected) => { - receptacle.take(); + z_reply_null(this); true } Err(TryRecvError::Empty) => { - receptacle.take(); + z_reply_null(this); false } }, @@ -175,10 +163,10 @@ pub extern "C" fn z_reply_channel_closure_null() -> z_owned_reply_channel_closur #[no_mangle] pub extern "C" fn z_reply_channel_closure_call( closure: &z_owned_reply_channel_closure_t, - sample: &mut z_owned_reply_t, + reply: *mut MaybeUninit, ) -> bool { match closure.call { - Some(call) => call(sample, closure.context), + Some(call) => call(reply, closure.context), None => { log::error!("Attempted to call an uninitialized closure!"); true @@ -191,11 +179,11 @@ pub extern "C" fn z_reply_channel_closure_drop(closure: &mut z_owned_reply_chann let mut empty_closure = z_owned_reply_channel_closure_t::empty(); std::mem::swap(&mut empty_closure, closure); } -impl bool> From for z_owned_reply_channel_closure_t { +impl) -> bool> From for z_owned_reply_channel_closure_t { fn from(f: F) -> Self { let this = Box::into_raw(Box::new(f)) as _; - extern "C" fn call bool>( - response: &mut z_owned_reply_t, + extern "C" fn call) -> bool>( + response: *mut MaybeUninit, this: *mut c_void, ) -> bool { let this = unsafe { &*(this as *const F) }; diff --git a/src/closures/sample_closure.rs b/src/closures/sample_closure.rs index 6f0e55707..e706b0b7a 100644 --- a/src/closures/sample_closure.rs +++ b/src/closures/sample_closure.rs @@ -1,10 +1,10 @@ -use crate::z_sample_t; +use crate::z_loaned_sample_t; use libc::c_void; /// A closure is a structure that contains all the elements for stateful, memory-leak-free callbacks. /// /// Members: /// void *context: a pointer to an arbitrary state. -/// void *call(const struct z_sample_t*, const void *context): the typical callback function. `context` will be passed as its last argument. +/// void *call(struct z_loaned_sample_t, const void *context): the typical callback function. `context` will be passed as its last argument. /// void *drop(void*): allows the callback's state to be freed. /// /// Closures are not guaranteed not to be called concurrently. @@ -17,7 +17,7 @@ use libc::c_void; #[repr(C)] pub struct z_owned_closure_sample_t { context: *mut c_void, - call: Option, + call: Option, drop: Option, } impl z_owned_closure_sample_t { @@ -47,7 +47,10 @@ pub extern "C" fn z_closure_sample_null() -> z_owned_closure_sample_t { /// Calls the closure. Calling an uninitialized closure is a no-op. #[no_mangle] -pub extern "C" fn z_closure_sample_call(closure: &z_owned_closure_sample_t, sample: &z_sample_t) { +pub extern "C" fn z_closure_sample_call( + closure: &z_owned_closure_sample_t, + sample: &z_loaned_sample_t, +) { match closure.call { Some(call) => call(sample, closure.context), None => log::error!("Attempted to call an uninitialized closure!"), @@ -60,12 +63,15 @@ pub extern "C" fn z_closure_sample_drop(closure: &mut z_owned_closure_sample_t) let mut empty_closure = z_owned_closure_sample_t::empty(); std::mem::swap(&mut empty_closure, closure); } -impl From for z_owned_closure_sample_t { +impl From for z_owned_closure_sample_t { fn from(f: F) -> Self { let this = Box::into_raw(Box::new(f)) as _; - extern "C" fn call(sample: &z_sample_t, this: *mut c_void) { + extern "C" fn call( + sample: *const z_loaned_sample_t, + this: *mut c_void, + ) { let this = unsafe { &*(this as *const F) }; - this(sample) + unsafe { this(sample.as_ref().unwrap()) } } extern "C" fn drop(this: *mut c_void) { std::mem::drop(unsafe { Box::from_raw(this as *mut F) }) diff --git a/src/collections.rs b/src/collections.rs index 9fd0c3c16..395ee57e3 100644 --- a/src/collections.rs +++ b/src/collections.rs @@ -11,147 +11,442 @@ // Contributors: // ZettaScale Zenoh team, // -use libc::{c_char, size_t}; -use zenoh::prelude::ZenohId; -/// A contiguous view of bytes owned by some other entity. +use std::borrow::Cow; +use std::collections::HashMap; +use std::mem::MaybeUninit; +use std::ptr::null; +use std::slice::from_raw_parts; + +use libc::{c_char, c_void, strlen}; + +use crate::errors; +use crate::transmute::{ + unwrap_ref_unchecked, unwrap_ref_unchecked_mut, Inplace, TransmuteFromHandle, + TransmuteIntoHandle, TransmuteRef, TransmuteUninitPtr, +}; + +pub use crate::opaque_types::z_loaned_slice_t; +pub use crate::opaque_types::z_owned_slice_t; +pub use crate::opaque_types::z_view_slice_t; + +decl_transmute_owned!(Option>, z_owned_slice_t); +decl_transmute_owned!(Option<&'static [u8]>, z_view_slice_t); +decl_transmute_handle!(&'static [u8], z_loaned_slice_t); + +/// Returns an empty `z_view_slice_t` +#[no_mangle] +pub extern "C" fn z_view_slice_empty(this: *mut MaybeUninit) { + let slice: &'static [u8] = &[]; + Inplace::init(this.transmute_uninit_ptr(), Some(slice)) +} + +#[no_mangle] +pub extern "C" fn z_view_slice_null(this: *mut MaybeUninit) { + Inplace::empty(this.transmute_uninit_ptr()); +} + +/// Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). /// -/// `start` being `null` is considered a gravestone value, -/// and empty slices are represented using a possibly dangling pointer for `start`. -#[repr(C)] -#[derive(Clone, Copy, Debug)] -pub struct z_bytes_t { - pub len: size_t, - pub start: *const u8, -} - -impl z_bytes_t { - pub fn as_slice(&self) -> Option<&[u8]> { - if self.start.is_null() { - return None; - } - Some(unsafe { core::slice::from_raw_parts(self.start, self.len) }) +/// Calling this with `str == NULL` is equivalent to `z_view_slice_null`. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_view_slice_from_str( + this: *mut MaybeUninit, + str: *const c_char, +) { + if str.is_null() { + z_view_slice_null(this) + } else { + z_view_slice_wrap(this, str as *const u8, libc::strlen(str)) } - pub fn empty() -> Self { - z_bytes_t { - start: std::ptr::null(), - len: 0, - } +} + +/// Constructs a `len` bytes long view starting at `start`. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_view_slice_wrap( + this: *mut MaybeUninit, + start: *const u8, + len: usize, +) { + if len == 0 { + z_view_slice_empty(this) + } else if start.is_null() { + z_view_slice_null(this) + } else { + let slice: &'static [u8] = from_raw_parts(start, len); + Inplace::init(this.transmute_uninit_ptr(), Some(slice)) } } -impl Default for z_bytes_t { - fn default() -> Self { - Self::empty() +#[no_mangle] +pub extern "C" fn z_view_slice_loan(this: &z_view_slice_t) -> *const z_loaned_slice_t { + match this.transmute_ref() { + Some(s) => s.transmute_handle(), + None => null(), } } -/// Returns ``true`` if `b` is initialized. +/// Returns an empty `z_owned_slice_t` #[no_mangle] -pub extern "C" fn z_bytes_check(b: &z_bytes_t) -> bool { - !b.start.is_null() +pub extern "C" fn z_slice_empty(this: *mut MaybeUninit) { + let slice = Box::new([]); + Inplace::init(this.transmute_uninit_ptr(), Some(slice)) } -/// Returns the gravestone value for `z_bytes_t` #[no_mangle] -pub extern "C" fn z_bytes_null() -> z_bytes_t { - z_bytes_t { - len: 0, - start: core::ptr::null(), - } +pub extern "C" fn z_slice_null(this: *mut MaybeUninit) { + Inplace::empty(this.transmute_uninit_ptr()); } -/// Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). +/// Copies a string into `z_owned_slice_t` using `strlen` (this should therefore not be used with untrusted inputs). /// -/// `str == NULL` will cause this to return `z_bytes_null()` +/// Calling this with `str == NULL` is equivalent to `z_slice_null`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_bytes_from_str(str: *const c_char) -> z_bytes_t { +pub unsafe extern "C" fn z_slice_from_str( + this: *mut MaybeUninit, + str: *const c_char, +) { if str.is_null() { - z_bytes_null() + z_slice_null(this) } else { - let len = unsafe { libc::strlen(str) }; - z_bytes_t { - len, - start: str.cast(), - } + z_slice_wrap(this, str as *const u8, libc::strlen(str)) } } -#[deprecated = "Renamed to z_bytes_from_str"] -/// Deprecated in favor of `z_bytes_from_str`: Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). -/// -/// `str == NULL` will cause this to return `z_bytes_null()` +/// Constructs a `len` bytes long view starting at `start`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_bytes_new(str: *const c_char) -> z_bytes_t { - z_bytes_from_str(str) +pub unsafe extern "C" fn z_slice_wrap( + this: *mut MaybeUninit, + start: *const u8, + len: usize, +) { + if len == 0 { + z_slice_empty(this) + } else if start.is_null() { + z_slice_null(this) + } else { + let slice = from_raw_parts(start, len).to_owned().into_boxed_slice(); + Inplace::init(this.transmute_uninit_ptr(), Some(slice)) + } } -/// Constructs a `len` bytes long view starting at `start`. +/// Frees `this` and invalidates it for double-drop safety. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_bytes_wrap(start: *const u8, len: usize) -> z_bytes_t { - if start.is_null() { - z_bytes_null() - } else { - z_bytes_t { len, start } +pub unsafe extern "C" fn z_slice_drop(this: &mut z_owned_slice_t) { + let this = this.transmute_mut(); + Inplace::drop(this); +} + +#[no_mangle] +pub extern "C" fn z_slice_loan(this: &z_owned_slice_t) -> *const z_loaned_slice_t { + match this.transmute_ref() { + Some(s) => (&s.as_ref()) as *const &[u8] as *const z_loaned_slice_t, + None => null(), } } -/// Frees `b` and invalidates it for double-drop safety. +#[no_mangle] +pub extern "C" fn z_slice_clone(this: &z_loaned_slice_t, dst: *mut MaybeUninit) { + let slice = this.transmute_ref().to_vec().into_boxed_slice(); + Inplace::init(dst.transmute_uninit_ptr(), Some(slice)); +} + +/// Returns ``true`` if `this` is initialized. +#[no_mangle] +pub extern "C" fn z_owned_slice_check(this: &z_owned_slice_t) -> bool { + this.transmute_ref().is_some() +} + +/// Returns ``true`` if `this` is initialized. +#[no_mangle] +pub extern "C" fn z_view_slice_check(this: &z_view_slice_t) -> bool { + this.transmute_ref().is_some() +} + +#[no_mangle] +pub extern "C" fn z_slice_len(this: &z_loaned_slice_t) -> usize { + this.transmute_ref().len() +} + +#[no_mangle] +pub extern "C" fn z_slice_data(this: &z_loaned_slice_t) -> *const u8 { + this.transmute_ref().as_ptr() +} + +pub use crate::opaque_types::z_loaned_str_t; +pub use crate::opaque_types::z_owned_str_t; +pub use crate::opaque_types::z_view_str_t; + +decl_transmute_owned!(custom_inplace_init Option>, z_owned_str_t); +decl_transmute_owned!(custom_inplace_init Option<&'static [u8]>, z_view_str_t); +decl_transmute_handle!(&'static [u8], z_loaned_str_t); + +/// Frees `z_owned_str_t`, invalidating it for double-drop safety. +#[no_mangle] #[allow(clippy::missing_safety_doc)] -pub(crate) unsafe fn z_bytes_drop(b: &mut z_bytes_t) { - if !b.start.is_null() { - std::mem::drop(Box::from_raw( - core::ptr::slice_from_raw_parts(b.start, b.len).cast_mut(), - )); - b.start = std::ptr::null(); - } +pub unsafe extern "C" fn z_str_drop(this: &mut z_owned_str_t) { + z_slice_drop(this.transmute_mut().transmute_mut()); } -impl From for z_bytes_t { - #[inline] - fn from(pid: ZenohId) -> Self { - let pid = pid.to_le_bytes().to_vec().into_boxed_slice(); - let res = z_bytes_t { - start: pid.as_ptr(), - len: pid.len() as size_t, - }; - std::mem::forget(pid); - res - } +/// Returns ``true`` if `s` is a valid string +#[no_mangle] +pub extern "C" fn z_str_check(this: &z_owned_str_t) -> bool { + z_owned_slice_check(this.transmute_ref().transmute_ref()) +} + +/// Returns undefined `z_owned_str_t` +#[no_mangle] +pub extern "C" fn z_str_null(this: *mut MaybeUninit) { + z_slice_null(this as *mut _) +} + +/// Returns undefined `z_owned_str_t` +#[no_mangle] +pub extern "C" fn z_view_str_null(this: *mut MaybeUninit) { + z_slice_null(this as *mut _) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_str_empty(this: *mut MaybeUninit) { + z_slice_wrap(this as *mut _, [0u8].as_ptr(), 1) } -impl From> for z_bytes_t { - #[inline] - fn from(pid: Option) -> Self { - match pid { - Some(pid) => pid.into(), - None => z_bytes_t { - start: std::ptr::null(), - len: 0, - }, +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_view_str_empty(this: *mut MaybeUninit) { + z_view_slice_wrap(this as *mut _, [0u8].as_ptr(), 1) +} + +/// Returns :c:type:`z_loaned_str_t` structure loaned from :c:type:`z_owned_str_t`. +#[no_mangle] +pub extern "C" fn z_str_loan(this: &z_owned_str_t) -> *const z_loaned_str_t { + z_slice_loan(this.transmute_ref().transmute_ref()) as _ +} + +/// Returns :c:type:`z_loaned_str_t` structure loaned from :c:type:`z_view_str_t`. +#[no_mangle] +pub extern "C" fn z_view_str_loan(this: &z_view_str_t) -> *const z_loaned_str_t { + z_view_slice_loan(this.transmute_ref().transmute_ref()) as _ +} + +/// Copies a string into `z_owned_str_t` using `strlen` (this should therefore not be used with untrusted inputs). +/// +/// Calling this with `str == NULL` is equivalent to `z_str_null`. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_str_wrap( + this: *mut MaybeUninit, + str: *const libc::c_char, +) { + z_slice_wrap(this as *mut _, str as _, strlen(str) + 1) +} + +/// Copies a a substring of length `len`into `z_owned_str_t`. +/// +/// Calling this with `str == NULL` is equivalent to `z_str_null`. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_str_from_substring( + this: *mut MaybeUninit, + str: *const libc::c_char, + len: usize, +) { + let mut v = vec![0u8; len + 1]; + v[0..len].copy_from_slice(from_raw_parts(str as *const u8, len)); + let b = v.into_boxed_slice(); + Inplace::init(this.transmute_uninit_ptr(), Some(b)); +} + +/// Returns a view of `str` using `strlen` (this should therefore not be used with untrusted inputs). +/// +/// Calling this with `str == NULL` is equivalent to `z_view_str_null`. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_view_str_wrap( + this: *mut MaybeUninit, + str: *const libc::c_char, +) { + z_view_slice_wrap(this as *mut _, str as _, strlen(str) + 1) +} + +#[no_mangle] +pub extern "C" fn z_view_str_len(this: &z_loaned_str_t) -> usize { + z_slice_len(this.transmute_ref().transmute_handle()) - 1 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_view_str_data(this: &z_loaned_str_t) -> *const libc::c_char { + z_slice_data(this.transmute_ref().transmute_handle()) as _ +} + +#[no_mangle] +pub extern "C" fn z_str_clone(this: &z_loaned_str_t, dst: *mut MaybeUninit) { + let slice = this.transmute_ref().to_vec().into_boxed_slice(); + Inplace::init(dst.transmute_uninit_ptr(), Some(slice)); +} + +pub use crate::opaque_types::z_loaned_slice_map_t; +pub use crate::opaque_types::z_owned_slice_map_t; + +pub type ZHashMap = HashMap, Cow<'static, [u8]>>; +pub use crate::opaque_types::z_loaned_config_t; +decl_transmute_handle!( + HashMap, Cow<'static, [u8]>>, + z_loaned_slice_map_t +); + +pub use crate::opaque_types::z_owned_config_t; +decl_transmute_owned!( + Option, Cow<'static, [u8]>>>, + z_owned_slice_map_t +); + +/// Constructs a new empty map. +#[no_mangle] +pub extern "C" fn z_slice_map_new(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + let map = ZHashMap::new(); + Inplace::init(this, Some(map)); +} + +/// Constructs the gravestone value for `z_owned_slice_map_t` +#[no_mangle] +pub extern "C" fn z_slice_map_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); +} + +/// Returns `true` if the map is not in its gravestone state +#[no_mangle] +pub extern "C" fn z_slice_map_check(map: &z_owned_slice_map_t) -> bool { + let map = map.transmute_ref(); + map.as_ref().is_some() +} + +/// Destroys the map, resetting `this` to its gravestone value. +/// +/// This function is double-free safe, passing a pointer to the gravestone value will have no effect. +#[no_mangle] +pub extern "C" fn z_slice_map_drop(this: &mut z_owned_slice_map_t) { + let this = this.transmute_mut(); + Inplace::drop(this); +} + +#[no_mangle] +pub extern "C" fn z_slice_map_loan(this: &z_owned_slice_map_t) -> &z_loaned_slice_map_t { + let this = this.transmute_ref(); + let this = unwrap_ref_unchecked(this); + this.transmute_handle() +} + +#[no_mangle] +pub extern "C" fn z_slice_map_loan_mut( + this: &mut z_owned_slice_map_t, +) -> &mut z_loaned_slice_map_t { + let this = this.transmute_mut(); + let this = unwrap_ref_unchecked_mut(this); + this.transmute_handle_mut() +} + +/// Returns number of key-value pairs in the map. +#[no_mangle] +pub extern "C" fn z_slice_map_len(this: &z_loaned_slice_map_t) -> usize { + this.transmute_ref().len() +} + +/// Returns true if the map is empty, false otherwise. +#[no_mangle] +pub extern "C" fn z_slice_map_is_empty(this: &z_loaned_slice_map_t) -> bool { + z_slice_map_len(this) == 0 +} + +/// The body of a loop over a z_slice_map's key-value pairs. +/// +/// `key` and `value` are loaned to the body for the duration of a single call. +/// `context` is passed transparently through the iteration driver. +/// +/// Returning `true` is treated as `continue`. +#[allow(non_camel_case_types)] +pub type z_slice_map_iter_body_t = + extern "C" fn(key: &z_loaned_slice_t, value: &z_loaned_slice_t, context: *mut c_void) -> bool; + +#[no_mangle] +pub extern "C" fn z_slice_map_iterate( + this: &z_loaned_slice_map_t, + body: z_slice_map_iter_body_t, + context: *mut c_void, +) { + let this = this.transmute_ref(); + for (key, value) in this { + let key_slice = key.as_ref(); + let value_slice = value.as_ref(); + if !body( + key_slice.transmute_handle(), + value_slice.transmute_handle(), + context, + ) { + break; } } } -impl From for String { - fn from(s: z_bytes_t) -> Self { - unsafe { - String::from_utf8( - Box::from_raw(std::slice::from_raw_parts_mut(s.start as *mut u8, s.len)).into(), - ) - .unwrap() - } +/// Returns the value associated with `key`. +/// +/// Will return NULL if the key is not present in the map. +#[no_mangle] +pub extern "C" fn z_slice_map_get( + this: &z_loaned_slice_map_t, + key: &z_loaned_slice_t, +) -> *const z_loaned_slice_t { + let m = this.transmute_ref(); + let key = *key.transmute_ref(); + let k = Cow::Borrowed(key); + m.get(&k) + .map(|s| s.as_ref().transmute_handle() as *const _) + .unwrap_or(null()) +} + +/// Associates `value` to `key` in the map, copying them to obtain ownership: `key` and `value` are not aliased past the function's return. +/// +/// Returns 1 if there was already an entry associated with the key, 0 otherwise. +#[no_mangle] +pub extern "C" fn z_slice_map_insert_by_copy( + this: &mut z_loaned_slice_map_t, + key: &z_loaned_slice_t, + value: &z_loaned_slice_t, +) -> u8 { + let this = this.transmute_mut(); + let key = *key.transmute_ref(); + let value = *value.transmute_ref(); + match this.insert(Cow::Owned(key.to_owned()), Cow::Owned(value.to_owned())) { + Some(_) => 1, + None => 0, } } -impl From<&[u8]> for z_bytes_t { - fn from(s: &[u8]) -> Self { - z_bytes_t { - start: s.as_ptr(), - len: s.len(), - } +/// Associates `value` to `key` in the map, aliasing them. +/// +/// Note that once `key` is aliased, reinserting at the same key may alias the previous instance, or the new instance of `key`. +/// +/// Returns 1 if there was already an entry associated with the key, 0 otherwise. +#[no_mangle] +pub extern "C" fn z_slice_map_insert_by_alias( + this: &mut z_loaned_slice_map_t, + key: &z_loaned_slice_t, + value: &z_loaned_slice_t, +) -> errors::z_error_t { + let this = this.transmute_mut(); + let key = key.transmute_ref(); + let value = value.transmute_ref(); + match this.insert(Cow::Borrowed(key), Cow::Borrowed(value)) { + Some(_) => 1, + None => 0, } } diff --git a/src/commons.rs b/src/commons.rs index 7ddaba873..11a6a28b3 100644 --- a/src/commons.rs +++ b/src/commons.rs @@ -12,24 +12,35 @@ // ZettaScale Zenoh team, // -use crate::collections::*; -use crate::keyexpr::*; -use crate::z_congestion_control_t; +use std::ffi::CStr; +use std::mem::MaybeUninit; +use std::ptr::null; +use std::str::FromStr; + +use crate::transmute::unwrap_ref_unchecked; +use crate::transmute::Inplace; +use crate::transmute::TransmuteCopy; +use crate::transmute::TransmuteFromHandle; +use crate::transmute::TransmuteIntoHandle; +use crate::transmute::TransmuteRef; +use crate::transmute::TransmuteUninitPtr; use crate::z_id_t; -use crate::z_priority_t; -use crate::{impl_guarded_transmute, GuardedTransmute}; -use libc::c_void; +use crate::z_loaned_bytes_t; +use crate::z_loaned_keyexpr_t; use libc::{c_char, c_ulong}; -use zenoh::buffers::ZBuf; +use unwrap_infallible::UnwrapInfallible; +use zenoh::encoding::Encoding; use zenoh::prelude::SampleKind; -use zenoh::prelude::SplitBuffer; +use zenoh::publication::CongestionControl; +use zenoh::publication::Priority; +use zenoh::query::ConsolidationMode; +use zenoh::query::Mode; +use zenoh::query::QueryTarget; use zenoh::query::ReplyKeyExpr; use zenoh::sample::Locality; -use zenoh::sample::QoS; use zenoh::sample::Sample; -use zenoh_protocol::core::Timestamp; - -use crate::attachment::{attachment_iteration_driver, z_attachment_null, z_attachment_t}; +use zenoh::time::Timestamp; +use zenoh::value::Value; /// A zenoh unsigned integer #[allow(non_camel_case_types)] @@ -60,546 +71,215 @@ impl From for SampleKind { } } } +use crate::opaque_types::z_timestamp_t; +decl_transmute_copy!(Timestamp, z_timestamp_t); -#[repr(C)] -pub struct z_timestamp_t { - time: u64, - id: z_id_t, +#[no_mangle] +pub extern "C" fn z_timestamp_npt64_time(timestamp: &z_timestamp_t) -> u64 { + timestamp.transmute_copy().get_time().0 } -/// Returns ``true`` if `ts` is a valid timestamp #[no_mangle] -pub extern "C" fn z_timestamp_check(ts: z_timestamp_t) -> bool { - ts.id.id.iter().any(|byte| *byte != 0) -} -impl From> for z_timestamp_t { - fn from(ts: Option<&Timestamp>) -> Self { - if let Some(ts) = ts { - z_timestamp_t { - time: ts.get_time().as_u64(), - id: z_id_t { - id: ts.get_id().to_le_bytes(), - }, - } - } else { - z_timestamp_t { - time: 0, - id: z_id_t { id: [0u8; 16] }, - } - } - } +pub extern "C" fn z_timestamp_get_id(timestamp: &z_timestamp_t) -> z_id_t { + timestamp.transmute_copy().get_id().to_le_bytes().into() } -/// An owned payload, backed by a reference counted owner. +/// A data sample. /// -/// The `payload` field may be modified, and Zenoh will take the new values into account, -/// however, assuming `ostart` and `olen` are the respective values of `payload.start` and -/// `payload.len` when constructing the `zc_owned_payload_t payload` value was created, -/// then `payload.start` MUST remain within the `[ostart, ostart + olen[` interval, and -/// `payload.len` must remain within `[0, olen -(payload.start - ostart)]`. +/// A sample is the value associated to a given resource at a given point in time. +use crate::opaque_types::z_loaned_sample_t; +decl_transmute_handle!(Sample, z_loaned_sample_t); + +/// The Key Expression of the sample. /// -/// Should this invariant be broken when the payload is passed to one of zenoh's `put_owned` -/// functions, then the operation will fail (but the passed value will still be consumed). -#[allow(non_camel_case_types)] -#[repr(C)] -pub struct zc_owned_payload_t { - pub payload: z_bytes_t, - pub _owner: [usize; 5], -} -impl Default for zc_owned_payload_t { - fn default() -> Self { - zc_payload_null() - } -} -impl TryFrom for zc_owned_payload_t { - type Error = (); - fn try_from(buf: ZBuf) -> Result { - let std::borrow::Cow::Borrowed(payload) = buf.contiguous() else { - return Err(()); - }; - Ok(Self { - payload: payload.into(), - _owner: unsafe { std::mem::transmute(buf) }, - }) - } -} -impl zc_owned_payload_t { - pub fn take(&mut self) -> Option { - if !z_bytes_check(&self.payload) { - return None; - } - let start = std::mem::replace(&mut self.payload.start, std::ptr::null()); - let len = std::mem::replace(&mut self.payload.len, 0); - let mut buf: ZBuf = unsafe { std::mem::transmute(self._owner) }; - { - let mut slices = buf.zslices_mut(); - let slice = slices.next().unwrap(); - assert!( - slices.next().is_none(), - "A multi-slice buffer reached zenoh-c, which is definitely a bug, please report it." - ); - let start_offset = unsafe { start.offset_from(slice.as_slice().as_ptr()) }; - let Ok(start_offset) = start_offset.try_into() else { - return None; - }; - *slice = match slice.subslice(start_offset, start_offset + len) { - Some(s) => s, - None => return None, - }; - } - Some(buf) - } - fn owner(&self) -> Option<&ZBuf> { - if !z_bytes_check(&self.payload) { - return None; - } - unsafe { std::mem::transmute(&self._owner) } - } -} -impl Drop for zc_owned_payload_t { - fn drop(&mut self) { - self.take(); - } +/// `sample` is aliased by its return value. +#[no_mangle] +pub extern "C" fn z_sample_keyexpr(sample: &z_loaned_sample_t) -> &z_loaned_keyexpr_t { + let sample = sample.transmute_ref(); + sample.key_expr().transmute_handle() } - -/// Clones the `payload` by incrementing its reference counter. +/// The encoding of the payload. #[no_mangle] -pub extern "C" fn zc_payload_rcinc(payload: &zc_owned_payload_t) -> zc_owned_payload_t { - match payload.owner() { - None => Default::default(), - Some(payload) => payload.clone().try_into().unwrap_or_default(), - } +pub extern "C" fn z_sample_encoding(sample: &z_loaned_sample_t) -> &z_loaned_encoding_t { + let sample = sample.transmute_ref(); + sample.encoding().transmute_handle() } -/// Returns `false` if `payload` is the gravestone value. +/// The sample's data, the return value aliases the sample. +/// #[no_mangle] -pub extern "C" fn zc_payload_check(payload: &zc_owned_payload_t) -> bool { - !payload.payload.start.is_null() +pub extern "C" fn z_sample_payload(sample: &z_loaned_sample_t) -> &z_loaned_bytes_t { + let sample = sample.transmute_ref(); + sample.payload().transmute_handle() } -/// Decrements `payload`'s backing refcount, releasing the memory if appropriate. + +/// The sample's kind (put or delete). #[no_mangle] -pub extern "C" fn zc_payload_drop(payload: &mut zc_owned_payload_t) { - unsafe { std::ptr::replace(payload, zc_payload_null()) }; +pub extern "C" fn z_sample_kind(sample: &z_loaned_sample_t) -> z_sample_kind_t { + let sample = sample.transmute_ref(); + sample.kind().into() } -/// Constructs `zc_owned_payload_t`'s gravestone value. +/// The samples timestamp +/// +/// Returns true if Sample contains timestamp, false otherwise. In the latter case the timestamp_out value is not altered. #[no_mangle] -pub extern "C" fn zc_payload_null() -> zc_owned_payload_t { - zc_owned_payload_t { - payload: z_bytes_t { - len: 0, - start: std::ptr::null(), - }, - _owner: unsafe { core::mem::MaybeUninit::zeroed().assume_init() }, +pub extern "C" fn z_loaned_sample_timestamp( + sample: &z_loaned_sample_t, + timestamp_out: &mut z_timestamp_t, +) -> bool { + let sample = sample.transmute_ref(); + if let Some(t) = sample.timestamp() { + *timestamp_out = t.transmute_copy(); + true + } else { + false } } +/// The qos with which the sample was received. +/// TODO: split to methods (priority, congestion_control, express) -/// QoS settings of zenoh message. +/// Gets sample's attachment. /// -#[repr(C)] -pub struct z_qos_t(u8); - -impl_guarded_transmute!(QoS, z_qos_t); -/// Returns message priority. +/// Returns NULL if sample does not contain an attachement. #[no_mangle] -pub extern "C" fn z_qos_get_priority(qos: z_qos_t) -> z_priority_t { - qos.transmute().priority().into() +pub extern "C" fn z_sample_attachment(sample: &z_loaned_sample_t) -> *const z_loaned_bytes_t { + let sample = sample.transmute_ref(); + match sample.attachment() { + Some(attachment) => attachment.transmute_handle() as *const _, + None => null(), + } } -/// Returns message congestion control. + +pub use crate::opaque_types::z_owned_sample_t; +decl_transmute_owned!(Option, z_owned_sample_t); + +/// Clone a sample in the cheapest way available. #[no_mangle] -pub extern "C" fn z_qos_get_congestion_control(qos: z_qos_t) -> z_congestion_control_t { - qos.transmute().congestion_control().into() +pub extern "C" fn z_sample_clone(src: &z_loaned_sample_t, dst: *mut MaybeUninit) { + let src = src.transmute_ref(); + let src = src.clone(); + let dst = dst.transmute_uninit_ptr(); + Inplace::init(dst, Some(src)); } -/// Returns message express flag. If set to true, the message is not batched to reduce the latency. + #[no_mangle] -pub extern "C" fn z_qos_get_express(qos: z_qos_t) -> bool { - qos.transmute().express() +pub extern "C" fn z_sample_priority(sample: &z_loaned_sample_t) -> z_priority_t { + let sample = sample.transmute_ref(); + sample.priority().into() } -/// Returns default qos settings. + #[no_mangle] -pub extern "C" fn z_qos_default() -> z_qos_t { - QoS::default().transmute() +pub extern "C" fn z_sample_express(sample: &z_loaned_sample_t) -> bool { + let sample = sample.transmute_ref(); + sample.express() } -/// A data sample. -/// -/// A sample is the value associated to a given resource at a given point in time. -/// -/// Members: -/// z_keyexpr_t keyexpr: The resource key of this data sample. -/// z_bytes_t payload: The value of this data sample. -/// z_encoding_t encoding: The encoding of the value of this data sample. -/// z_sample_kind_t kind: The kind of this data sample (PUT or DELETE). -/// z_timestamp_t timestamp: The timestamp of this data sample. -/// z_attachment_t attachment: The attachment of this data sample. -#[repr(C)] -pub struct z_sample_t<'a> { - pub keyexpr: z_keyexpr_t, - pub payload: z_bytes_t, - pub encoding: z_encoding_t, - pub _zc_buf: &'a c_void, - pub kind: z_sample_kind_t, - pub timestamp: z_timestamp_t, - pub qos: z_qos_t, - pub attachment: z_attachment_t, -} - -impl<'a> z_sample_t<'a> { - pub fn new(sample: &'a Sample, owner: &'a ZBuf) -> Self { - let std::borrow::Cow::Borrowed(payload) = owner.contiguous() else { - panic!("Attempted to construct z_sample_t from discontiguous buffer, this is definitely a bug in zenoh-c, please report it.") - }; - z_sample_t { - keyexpr: (&sample.key_expr).into(), - payload: z_bytes_t::from(payload), - encoding: (&sample.encoding).into(), - _zc_buf: unsafe { std::mem::transmute(owner) }, - kind: sample.kind.into(), - timestamp: sample.timestamp.as_ref().into(), - qos: sample.qos.into(), - attachment: match &sample.attachment { - Some(attachment) => z_attachment_t { - data: attachment as *const _ as *mut c_void, - iteration_driver: Some(attachment_iteration_driver), - }, - None => z_attachment_null(), - }, - } - } +#[no_mangle] +pub extern "C" fn z_sample_congestion_control( + sample: &z_loaned_sample_t, +) -> z_congestion_control_t { + let sample = sample.transmute_ref(); + sample.congestion_control().into() } -/// Clones the sample's payload by incrementing its backing refcount (this doesn't imply any copies). +/// Returns `true` if `sample` is valid. +/// +/// Note that there exist no fallinle constructors for `z_owned_sample_t`, so validity is always guaranteed +/// unless the value has been dropped already. #[no_mangle] -pub extern "C" fn zc_sample_payload_rcinc(sample: Option<&z_sample_t>) -> zc_owned_payload_t { - let Some(sample) = sample else { - return zc_payload_null(); - }; - let buf = unsafe { std::mem::transmute::<_, &ZBuf>(sample._zc_buf).clone() }; - zc_owned_payload_t { - payload: sample.payload, - _owner: unsafe { std::mem::transmute(buf) }, - } +pub extern "C" fn z_sample_check(sample: &z_owned_sample_t) -> bool { + let sample = sample.transmute_ref(); + sample.is_some() } -/// A :c:type:`z_encoding_t` integer `prefix`. +/// Borrow the sample, allowing calling its accessor methods. /// -/// - **Z_ENCODING_PREFIX_EMPTY** -/// - **Z_ENCODING_PREFIX_APP_OCTET_STREAM** -/// - **Z_ENCODING_PREFIX_APP_CUSTOM** -/// - **Z_ENCODING_PREFIX_TEXT_PLAIN** -/// - **Z_ENCODING_PREFIX_APP_PROPERTIES** -/// - **Z_ENCODING_PREFIX_APP_JSON** -/// - **Z_ENCODING_PREFIX_APP_SQL** -/// - **Z_ENCODING_PREFIX_APP_INTEGER** -/// - **Z_ENCODING_PREFIX_APP_FLOAT** -/// - **Z_ENCODING_PREFIX_APP_XML** -/// - **Z_ENCODING_PREFIX_APP_XHTML_XML** -/// - **Z_ENCODING_PREFIX_APP_X_WWW_FORM_URLENCODED** -/// - **Z_ENCODING_PREFIX_TEXT_JSON** -/// - **Z_ENCODING_PREFIX_TEXT_HTML** -/// - **Z_ENCODING_PREFIX_TEXT_XML** -/// - **Z_ENCODING_PREFIX_TEXT_CSS** -/// - **Z_ENCODING_PREFIX_TEXT_CSV** -/// - **Z_ENCODING_PREFIX_TEXT_JAVASCRIPT** -/// - **Z_ENCODING_PREFIX_IMAGE_JPEG** -/// - **Z_ENCODING_PREFIX_IMAGE_PNG** -/// - **Z_ENCODING_PREFIX_IMAGE_GIF** -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -#[repr(C)] -pub enum z_encoding_prefix_t { - Empty = 0, - AppOctetStream = 1, - AppCustom = 2, - TextPlain = 3, - AppProperties = 4, - AppJson = 5, - AppSql = 6, - AppInteger = 7, - AppFloat = 8, - AppXml = 9, - AppXhtmlXml = 10, - AppXWwwFormUrlencoded = 11, - TextJson = 12, - TextHtml = 13, - TextXml = 14, - TextCss = 15, - TextCsv = 16, - TextJavascript = 17, - ImageJpeg = 18, - ImagePng = 19, - ImageGif = 20, -} - -impl From for zenoh_protocol::core::KnownEncoding { - fn from(val: z_encoding_prefix_t) -> Self { - if cfg!(debug_assertions) { - match val { - z_encoding_prefix_t::Empty => zenoh_protocol::core::KnownEncoding::Empty, - z_encoding_prefix_t::AppOctetStream => { - zenoh_protocol::core::KnownEncoding::AppOctetStream - } - z_encoding_prefix_t::AppCustom => zenoh_protocol::core::KnownEncoding::AppCustom, - z_encoding_prefix_t::TextPlain => zenoh_protocol::core::KnownEncoding::TextPlain, - z_encoding_prefix_t::AppProperties => { - zenoh_protocol::core::KnownEncoding::AppProperties - } - z_encoding_prefix_t::AppJson => zenoh_protocol::core::KnownEncoding::AppJson, - z_encoding_prefix_t::AppSql => zenoh_protocol::core::KnownEncoding::AppSql, - z_encoding_prefix_t::AppInteger => zenoh_protocol::core::KnownEncoding::AppInteger, - z_encoding_prefix_t::AppFloat => zenoh_protocol::core::KnownEncoding::AppFloat, - z_encoding_prefix_t::AppXml => zenoh_protocol::core::KnownEncoding::AppXml, - z_encoding_prefix_t::AppXhtmlXml => { - zenoh_protocol::core::KnownEncoding::AppXhtmlXml - } - z_encoding_prefix_t::AppXWwwFormUrlencoded => { - zenoh_protocol::core::KnownEncoding::AppXWwwFormUrlencoded - } - z_encoding_prefix_t::TextJson => zenoh_protocol::core::KnownEncoding::TextJson, - z_encoding_prefix_t::TextHtml => zenoh_protocol::core::KnownEncoding::TextHtml, - z_encoding_prefix_t::TextXml => zenoh_protocol::core::KnownEncoding::TextXml, - z_encoding_prefix_t::TextCss => zenoh_protocol::core::KnownEncoding::TextCss, - z_encoding_prefix_t::TextCsv => zenoh_protocol::core::KnownEncoding::TextCsv, - z_encoding_prefix_t::TextJavascript => { - zenoh_protocol::core::KnownEncoding::TextJavascript - } - z_encoding_prefix_t::ImageJpeg => zenoh_protocol::core::KnownEncoding::ImageJpeg, - z_encoding_prefix_t::ImagePng => zenoh_protocol::core::KnownEncoding::ImagePng, - z_encoding_prefix_t::ImageGif => zenoh_protocol::core::KnownEncoding::ImageGif, - } - } else { - unsafe { std::mem::transmute(val as u8) } - } - } +/// Calling this function using a dropped sample is undefined behaviour. +#[no_mangle] +pub extern "C" fn z_sample_loan(sample: &z_owned_sample_t) -> &z_loaned_sample_t { + unwrap_ref_unchecked(sample.transmute_ref()).transmute_handle() } -impl From for z_encoding_prefix_t { - fn from(val: zenoh_protocol::core::KnownEncoding) -> Self { - if cfg!(debug_assertions) { - match val { - zenoh_protocol::core::KnownEncoding::Empty => z_encoding_prefix_t::Empty, - zenoh_protocol::core::KnownEncoding::AppOctetStream => { - z_encoding_prefix_t::AppOctetStream - } - zenoh_protocol::core::KnownEncoding::AppCustom => z_encoding_prefix_t::AppCustom, - zenoh_protocol::core::KnownEncoding::TextPlain => z_encoding_prefix_t::TextPlain, - zenoh_protocol::core::KnownEncoding::AppProperties => { - z_encoding_prefix_t::AppProperties - } - zenoh_protocol::core::KnownEncoding::AppJson => z_encoding_prefix_t::AppJson, - zenoh_protocol::core::KnownEncoding::AppSql => z_encoding_prefix_t::AppSql, - zenoh_protocol::core::KnownEncoding::AppInteger => z_encoding_prefix_t::AppInteger, - zenoh_protocol::core::KnownEncoding::AppFloat => z_encoding_prefix_t::AppFloat, - zenoh_protocol::core::KnownEncoding::AppXml => z_encoding_prefix_t::AppXml, - zenoh_protocol::core::KnownEncoding::AppXhtmlXml => { - z_encoding_prefix_t::AppXhtmlXml - } - zenoh_protocol::core::KnownEncoding::AppXWwwFormUrlencoded => { - z_encoding_prefix_t::AppXWwwFormUrlencoded - } - zenoh_protocol::core::KnownEncoding::TextJson => z_encoding_prefix_t::TextJson, - zenoh_protocol::core::KnownEncoding::TextHtml => z_encoding_prefix_t::TextHtml, - zenoh_protocol::core::KnownEncoding::TextXml => z_encoding_prefix_t::TextXml, - zenoh_protocol::core::KnownEncoding::TextCss => z_encoding_prefix_t::TextCss, - zenoh_protocol::core::KnownEncoding::TextCsv => z_encoding_prefix_t::TextCsv, - zenoh_protocol::core::KnownEncoding::TextJavascript => { - z_encoding_prefix_t::TextJavascript - } - zenoh_protocol::core::KnownEncoding::ImageJpeg => z_encoding_prefix_t::ImageJpeg, - zenoh_protocol::core::KnownEncoding::ImagePng => z_encoding_prefix_t::ImagePng, - zenoh_protocol::core::KnownEncoding::ImageGif => z_encoding_prefix_t::ImageGif, - } - } else { - unsafe { std::mem::transmute(val as u32) } - } - } +/// Destroy the sample. +#[no_mangle] +pub extern "C" fn z_sample_drop(sample: &mut z_owned_sample_t) { + Inplace::drop(sample.transmute_mut()); } -/// The encoding of a payload, in a MIME-like format. -/// -/// For wire and matching efficiency, common MIME types are represented using an integer as `prefix`, and a `suffix` may be used to either provide more detail, or in combination with the `Empty` prefix to write arbitrary MIME types. -/// -/// Members: -/// z_encoding_prefix_t prefix: The integer prefix of this encoding. -/// z_bytes_t suffix: The suffix of this encoding. `suffix` MUST be a valid UTF-8 string. -#[repr(C)] -#[derive(Clone, Copy, Debug)] -pub struct z_encoding_t { - pub prefix: z_encoding_prefix_t, - pub suffix: z_bytes_t, -} - -impl From for zenoh_protocol::core::Encoding { - fn from(enc: z_encoding_t) -> Self { - if enc.suffix.len == 0 { - zenoh_protocol::core::Encoding::Exact(enc.prefix.into()) - } else { - let suffix = unsafe { - let slice: &'static [u8] = - std::slice::from_raw_parts(enc.suffix.start, enc.suffix.len); - std::str::from_utf8_unchecked(slice) - }; - zenoh_protocol::core::Encoding::WithSuffix(enc.prefix.into(), suffix.into()) - } - } +#[no_mangle] +pub extern "C" fn z_sample_null(sample: *mut MaybeUninit) { + Inplace::empty(sample.transmute_uninit_ptr()); } -impl From<&zenoh_protocol::core::Encoding> for z_encoding_t { - fn from(val: &zenoh_protocol::core::Encoding) -> Self { - let suffix = val.suffix(); - z_encoding_t { - prefix: (*val.prefix()).into(), - suffix: z_bytes_t { - start: suffix.as_ptr(), - len: suffix.len(), - }, - } - } -} +pub use crate::opaque_types::z_loaned_encoding_t; +decl_transmute_handle!(Encoding, z_loaned_encoding_t); /// An owned payload encoding. /// -/// Members: -/// z_encoding_prefix_t prefix: The integer prefix of this encoding. -/// z_bytes_t suffix: The suffix of this encoding. `suffix` MUST be a valid UTF-8 string. -/// /// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. /// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. /// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. /// /// To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. -#[repr(C)] -pub struct z_owned_encoding_t { - pub prefix: z_encoding_prefix_t, - pub suffix: z_bytes_t, - pub _dropped: bool, -} - -impl z_owned_encoding_t { - pub fn null() -> Self { - z_owned_encoding_t { - prefix: z_encoding_prefix_t::Empty, - suffix: z_bytes_t::default(), - _dropped: true, - } - } -} +pub use crate::opaque_types::z_owned_encoding_t; +decl_transmute_owned!(Encoding, z_owned_encoding_t); /// Constructs a null safe-to-drop value of 'z_owned_encoding_t' type #[no_mangle] -pub extern "C" fn z_encoding_null() -> z_owned_encoding_t { - z_owned_encoding_t::null() +pub extern "C" fn z_encoding_null(encoding: *mut MaybeUninit) { + Inplace::empty(encoding.transmute_uninit_ptr()); } -/// Constructs a specific :c:type:`z_encoding_t`. +/// Constructs a specific :c:type:`z_loaned_encoding_t`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_encoding( - prefix: z_encoding_prefix_t, - suffix: *const c_char, -) -> z_encoding_t { - let suffix = if suffix.is_null() { - z_bytes_t::empty() +pub unsafe extern "C" fn z_encoding_from_str( + encoding: *mut MaybeUninit, + s: *const c_char, +) -> i8 { + let encoding = encoding.transmute_uninit_ptr(); + if s.is_null() { + Inplace::empty(encoding); + 0 } else { - z_bytes_t { - start: suffix as *const u8, - len: libc::strlen(suffix), - } - }; - z_encoding_t { prefix, suffix } + let s = CStr::from_ptr(s).to_string_lossy(); + let value = Encoding::from_str(s.as_ref()).unwrap_infallible(); + Inplace::init(encoding, value); + 0 + } } -/// Constructs a default :c:type:`z_encoding_t`. +/// Constructs a default :c:type:`z_loaned_encoding_t`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_encoding_default() -> z_encoding_t { - (&zenoh_protocol::core::Encoding::default()).into() +pub extern "C" fn z_encoding_default() -> &'static z_loaned_encoding_t { + Encoding::ZENOH_BYTES.transmute_handle() } /// Frees `encoding`, invalidating it for double-drop safety. #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn z_encoding_drop(encoding: &mut z_owned_encoding_t) { - z_bytes_drop(&mut encoding.suffix); - encoding._dropped = true + Inplace::drop(encoding.transmute_mut()); } /// Returns ``true`` if `encoding` is valid. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_encoding_check(encoding: &z_owned_encoding_t) -> bool { - !encoding._dropped -} - -/// Returns a :c:type:`z_encoding_t` loaned from `encoding`. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_encoding_loan(encoding: &z_owned_encoding_t) -> z_encoding_t { - z_encoding_t { - prefix: encoding.prefix, - suffix: encoding.suffix, - } +pub extern "C" fn z_encoding_check(encoding: &'static z_owned_encoding_t) -> bool { + *encoding.transmute_ref() != Encoding::default() } -impl From for z_owned_encoding_t { - fn from(val: z_encoding_t) -> Self { - z_owned_encoding_t { - prefix: val.prefix, - suffix: val.suffix, - _dropped: false, - } - } -} - -/// The wrapper type for null-terminated string values allocated by zenoh. The instances of `z_owned_str_t` -/// should be released with `z_drop` macro or with `z_str_drop` function and checked to validity with -/// `z_check` and `z_str_check` correspondently -#[repr(C)] -pub struct z_owned_str_t { - pub _cstr: *mut libc::c_char, -} - -impl From<&[u8]> for z_owned_str_t { - fn from(value: &[u8]) -> Self { - unsafe { - let cstr = libc::malloc(value.len() + 1) as *mut libc::c_char; - std::ptr::copy_nonoverlapping(value.as_ptr(), cstr as _, value.len()); - *cstr.add(value.len()) = 0; - z_owned_str_t { _cstr: cstr } - } - } -} - -impl Drop for z_owned_str_t { - fn drop(&mut self) { - unsafe { z_str_drop(self) } - } -} - -/// Frees `z_owned_str_t`, invalidating it for double-drop safety. +/// Returns a :c:type:`z_loaned_encoding_t` loaned from `encoding`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_str_drop(s: &mut z_owned_str_t) { - libc::free(std::mem::transmute(s._cstr)); - s._cstr = std::ptr::null_mut(); -} - -/// Returns ``true`` if `s` is a valid string -#[no_mangle] -pub extern "C" fn z_str_check(s: &z_owned_str_t) -> bool { - !s._cstr.is_null() -} - -/// Returns undefined `z_owned_str_t` -#[no_mangle] -pub extern "C" fn z_str_null() -> z_owned_str_t { - z_owned_str_t { - _cstr: std::ptr::null_mut(), - } +pub extern "C" fn z_encoding_loan(encoding: &z_owned_encoding_t) -> &z_loaned_encoding_t { + encoding.transmute_ref().transmute_handle() } -/// Returns :c:type:`z_str_t` structure loaned from :c:type:`z_owned_str_t`. -#[no_mangle] -pub extern "C" fn z_str_loan(s: &z_owned_str_t) -> *const libc::c_char { - s._cstr -} +pub use crate::opaque_types::z_owned_value_t; +decl_transmute_owned!(Value, z_owned_value_t); +pub use crate::opaque_types::z_loaned_value_t; +decl_transmute_handle!(Value, z_loaned_value_t); #[repr(C)] #[derive(Clone, Copy, Debug)] @@ -663,3 +343,181 @@ impl From for ReplyKeyExpr { pub extern "C" fn zcu_reply_keyexpr_default() -> zcu_reply_keyexpr_t { ReplyKeyExpr::default().into() } + +/// The Queryables that should be target of a :c:func:`z_get`. +/// +/// - **BEST_MATCHING**: The nearest complete queryable if any else all matching queryables. +/// - **ALL_COMPLETE**: All complete queryables. +/// - **ALL**: All matching queryables. +#[allow(non_camel_case_types)] +#[repr(C)] +#[derive(Clone, Copy)] +pub enum z_loaned_query_target_t { + BEST_MATCHING, + ALL, + ALL_COMPLETE, +} + +impl From for z_loaned_query_target_t { + #[inline] + fn from(t: QueryTarget) -> Self { + match t { + QueryTarget::BestMatching => z_loaned_query_target_t::BEST_MATCHING, + QueryTarget::All => z_loaned_query_target_t::ALL, + QueryTarget::AllComplete => z_loaned_query_target_t::ALL_COMPLETE, + } + } +} + +impl From for QueryTarget { + #[inline] + fn from(val: z_loaned_query_target_t) -> Self { + match val { + z_loaned_query_target_t::BEST_MATCHING => QueryTarget::BestMatching, + z_loaned_query_target_t::ALL => QueryTarget::All, + z_loaned_query_target_t::ALL_COMPLETE => QueryTarget::AllComplete, + } + } +} + +/// Create a default :c:type:`z_loaned_query_target_t`. +#[no_mangle] +pub extern "C" fn z_loaned_query_target_default() -> z_loaned_query_target_t { + QueryTarget::default().into() +} + +/// Consolidation mode values. +/// +/// - **Z_CONSOLIDATION_MODE_AUTO**: Let Zenoh decide the best consolidation mode depending on the query selector +/// If the selector contains time range properties, consolidation mode `NONE` is used. +/// Otherwise the `LATEST` consolidation mode is used. +/// - **Z_CONSOLIDATION_MODE_NONE**: No consolidation is applied. Replies may come in any order and any number. +/// - **Z_CONSOLIDATION_MODE_MONOTONIC**: It guarantees that any reply for a given key expression will be monotonic in time +/// w.r.t. the previous received replies for the same key expression. I.e., for the same key expression multiple +/// replies may be received. It is guaranteed that two replies received at t1 and t2 will have timestamp +/// ts2 > ts1. It optimizes latency. +/// - **Z_CONSOLIDATION_MODE_LATEST**: It guarantees unicity of replies for the same key expression. +/// It optimizes bandwidth. +#[repr(C)] +#[derive(Clone, Copy, Default)] +pub enum z_consolidation_mode_t { + AUTO = -1, + #[default] + NONE = 0, + MONOTONIC = 1, + LATEST = 2, +} + +impl From> for z_consolidation_mode_t { + #[inline] + fn from(cm: Mode) -> Self { + match cm { + Mode::Manual(cm) => Self::from(cm), + Mode::Auto => z_consolidation_mode_t::AUTO, + } + } +} + +impl From for z_consolidation_mode_t { + #[inline] + fn from(cm: ConsolidationMode) -> Self { + match cm { + ConsolidationMode::Auto => z_consolidation_mode_t::AUTO, + ConsolidationMode::None => z_consolidation_mode_t::NONE, + ConsolidationMode::Monotonic => z_consolidation_mode_t::MONOTONIC, + ConsolidationMode::Latest => z_consolidation_mode_t::LATEST, + } + } +} + +impl From for Mode { + #[inline] + fn from(val: z_consolidation_mode_t) -> Self { + match val { + z_consolidation_mode_t::AUTO => Mode::Auto, + z_consolidation_mode_t::NONE => Mode::Manual(ConsolidationMode::None), + z_consolidation_mode_t::MONOTONIC => Mode::Manual(ConsolidationMode::Monotonic), + z_consolidation_mode_t::LATEST => Mode::Manual(ConsolidationMode::Latest), + } + } +} + +/// The priority of zenoh messages. +/// +/// - **REAL_TIME** +/// - **INTERACTIVE_HIGH** +/// - **INTERACTIVE_LOW** +/// - **DATA_HIGH** +/// - **DATA** +/// - **DATA_LOW** +/// - **BACKGROUND** +#[allow(non_camel_case_types)] +#[repr(C)] +#[derive(Clone, Copy)] +pub enum z_priority_t { + REAL_TIME = 1, + INTERACTIVE_HIGH = 2, + INTERACTIVE_LOW = 3, + DATA_HIGH = 4, + DATA = 5, + DATA_LOW = 6, + BACKGROUND = 7, +} + +impl From for z_priority_t { + fn from(p: Priority) -> Self { + match p { + Priority::RealTime => z_priority_t::REAL_TIME, + Priority::InteractiveHigh => z_priority_t::INTERACTIVE_HIGH, + Priority::InteractiveLow => z_priority_t::INTERACTIVE_LOW, + Priority::DataHigh => z_priority_t::DATA_HIGH, + Priority::Data => z_priority_t::DATA, + Priority::DataLow => z_priority_t::DATA_LOW, + Priority::Background => z_priority_t::BACKGROUND, + } + } +} + +impl From for Priority { + fn from(p: z_priority_t) -> Self { + match p { + z_priority_t::REAL_TIME => Priority::RealTime, + z_priority_t::INTERACTIVE_HIGH => Priority::InteractiveHigh, + z_priority_t::INTERACTIVE_LOW => Priority::InteractiveLow, + z_priority_t::DATA_HIGH => Priority::DataHigh, + z_priority_t::DATA => Priority::Data, + z_priority_t::DATA_LOW => Priority::DataLow, + z_priority_t::BACKGROUND => Priority::Background, + } + } +} + +/// The kind of congestion control. +/// +/// - **BLOCK** +/// - **DROP** +#[allow(non_camel_case_types)] +#[repr(C)] +#[derive(Clone, Copy)] +pub enum z_congestion_control_t { + BLOCK, + DROP, +} + +impl From for z_congestion_control_t { + fn from(cc: CongestionControl) -> Self { + match cc { + CongestionControl::Block => z_congestion_control_t::BLOCK, + CongestionControl::Drop => z_congestion_control_t::DROP, + } + } +} + +impl From for CongestionControl { + fn from(cc: z_congestion_control_t) -> Self { + match cc { + z_congestion_control_t::BLOCK => CongestionControl::Block, + z_congestion_control_t::DROP => CongestionControl::Drop, + } + } +} diff --git a/src/config.rs b/src/config.rs index 80e3a38f1..2514d7f3d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -13,9 +13,15 @@ // use libc::{c_char, c_uint}; use std::ffi::CStr; +use std::mem::MaybeUninit; use zenoh::config::{Config, ValidatedMap, WhatAmI}; -use crate::{impl_guarded_transmute, z_owned_str_t, z_str_null}; +use crate::errors::z_error_t; +use crate::transmute::{ + unwrap_ref_unchecked, unwrap_ref_unchecked_mut, Inplace, TransmuteFromHandle, + TransmuteIntoHandle, TransmuteRef, TransmuteUninitPtr, +}; +use crate::{errors, z_owned_str_t, z_str_from_substring, z_str_null}; #[no_mangle] pub static Z_ROUTER: c_uint = WhatAmI::Router as c_uint; @@ -57,54 +63,26 @@ pub static Z_CONFIG_SCOUTING_DELAY_KEY: &c_char = pub static Z_CONFIG_ADD_TIMESTAMP_KEY: &c_char = unsafe { &*(b"timestamping/enabled\0".as_ptr() as *const c_char) }; -/// A loaned zenoh configuration. -#[repr(C)] -#[allow(non_camel_case_types)] -pub struct z_config_t(*const z_owned_config_t); +pub use crate::opaque_types::z_loaned_config_t; +decl_transmute_handle!(Config, z_loaned_config_t); -/// An owned zenoh configuration. -/// -/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. -/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. -/// -/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. -#[repr(C)] -pub struct z_owned_config_t(*mut ()); -impl_guarded_transmute!(Option>, z_owned_config_t); +pub use crate::opaque_types::z_owned_config_t; +decl_transmute_owned!(Option, z_owned_config_t); -/// Returns a :c:type:`z_config_t` loaned from `s`. +/// Returns a :c:type:`z_loaned_config_t` loaned from `s`. #[no_mangle] -pub extern "C" fn z_config_loan(s: &z_owned_config_t) -> z_config_t { - z_config_t(s) +pub extern "C" fn z_config_loan(this: &'static z_owned_config_t) -> &z_loaned_config_t { + let this = this.transmute_ref(); + let this = unwrap_ref_unchecked(this); + this.transmute_handle() } -impl AsRef>> for z_config_t { - fn as_ref(&self) -> &Option> { - unsafe { (*self.0).as_ref() } - } -} -impl AsMut>> for z_config_t { - fn as_mut(&mut self) -> &mut Option> { - unsafe { (*(self.0 as *mut z_owned_config_t)).as_mut() } - } -} -impl AsRef>> for z_owned_config_t { - fn as_ref(&self) -> &Option> { - unsafe { std::mem::transmute(self) } - } -} -impl AsMut>> for z_owned_config_t { - fn as_mut(&mut self) -> &mut Option> { - unsafe { std::mem::transmute(self) } - } -} -impl z_owned_config_t { - pub fn null() -> Self { - None.into() - } + +/// Returns a :c:type:`z_loaned_config_t` loaned from `s`. +#[no_mangle] +pub extern "C" fn z_config_loan_mut(this: &mut z_owned_config_t) -> &mut z_loaned_config_t { + let this = this.transmute_mut(); + let this = unwrap_ref_unchecked_mut(this); + this.transmute_handle_mut() } /// Return a new, zenoh-allocated, empty configuration. @@ -118,31 +96,55 @@ impl z_owned_config_t { /// /// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. #[no_mangle] -pub extern "C" fn z_config_new() -> z_owned_config_t { - let config: Box = Box::default(); - unsafe { z_owned_config_t(std::mem::transmute(Some(config))) } +pub extern "C" fn z_config_default(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + let config = Config::default(); + Inplace::init(this, Some(config)); } /// Constructs a null safe-to-drop value of 'z_owned_config_t' type #[no_mangle] -pub extern "C" fn z_config_null() -> z_owned_config_t { - z_owned_config_t::null() +pub extern "C" fn z_config_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); +} + +/// Clones the config. +#[no_mangle] +pub extern "C" fn z_config_clone(src: &z_loaned_config_t, dst: *mut MaybeUninit) { + let src = src.transmute_ref(); + let src = src.clone(); + let dst = dst.transmute_uninit_ptr(); + Inplace::init(dst, Some(src)); } /// Gets the property with the given path key from the configuration, returning an owned, null-terminated, JSON serialized string. /// Use `z_drop` to safely deallocate this string #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_config_get(config: z_config_t, key: *const c_char) -> z_owned_str_t { +pub unsafe extern "C" fn zc_config_get( + config: &z_loaned_config_t, + key: *const c_char, + value_string: *mut MaybeUninit, +) -> errors::z_error_t { + let config = config.transmute_ref(); let key = match CStr::from_ptr(key).to_str() { Ok(s) => s, - Err(_) => return z_str_null(), + Err(_) => { + z_str_null(value_string); + return errors::Z_EINVAL; + } }; - - let val = config.as_ref().as_ref().and_then(|c| c.get_json(key).ok()); + let val = config.get_json(key).ok(); match val { - Some(val) => val.as_bytes().into(), - None => z_str_null(), + Some(val) => { + z_str_from_substring(value_string, val.as_ptr() as *const libc::c_char, val.len()); + errors::Z_OK + } + None => { + z_str_null(value_string); + errors::Z_EUNAVAILABLE + } } } @@ -152,20 +154,16 @@ pub unsafe extern "C" fn zc_config_get(config: z_config_t, key: *const c_char) - #[no_mangle] #[allow(clippy::missing_safety_doc, unused_must_use)] pub unsafe extern "C" fn zc_config_insert_json( - mut config: z_config_t, + config: &mut z_loaned_config_t, key: *const c_char, value: *const c_char, -) -> i8 { +) -> errors::z_error_t { + let config = config.transmute_mut(); let key = CStr::from_ptr(key); let value = CStr::from_ptr(value); - match config - .as_mut() - .as_mut() - .expect("uninitialized config") - .insert_json5(&key.to_string_lossy(), &value.to_string_lossy()) - { + match config.insert_json5(&key.to_string_lossy(), &value.to_string_lossy()) { Ok(_) => 0, - Err(_) => i8::MIN, + Err(_) => errors::Z_EGENERIC, } } @@ -173,76 +171,96 @@ pub unsafe extern "C" fn zc_config_insert_json( #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn z_config_drop(config: &mut z_owned_config_t) { - std::mem::drop(config.as_mut().take()) + let config = config.transmute_mut(); + Inplace::drop(config); } /// Returns ``true`` if `config` is valid. #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn z_config_check(config: &z_owned_config_t) -> bool { + let config = config.transmute_ref(); config.as_ref().is_some() } -/// Creates a default, zenoh-allocated, configuration. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_config_default() -> z_owned_config_t { - z_config_new() -} - /// Reads a configuration from a JSON-serialized string, such as '{mode:"client",connect:{endpoints:["tcp/127.0.0.1:7447"]}}'. /// /// Passing a null-ptr will result in a gravestone value (`z_check(x) == false`). #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_config_from_str(s: *const c_char) -> z_owned_config_t { +pub unsafe extern "C" fn zc_config_from_str( + this: *mut MaybeUninit, + s: *const c_char, +) -> errors::z_error_t { + let mut res = errors::Z_OK; if s.is_null() { - z_config_null() + z_config_null(this); + res = errors::Z_EINVAL; } else { let conf_str = CStr::from_ptr(s); let props: Option = json5::from_str(&conf_str.to_string_lossy()).ok(); - z_owned_config_t(std::mem::transmute(props.map(Box::new))) + if props.is_none() { + res = errors::Z_EPARSE; + } + Inplace::init(this.transmute_uninit_ptr(), props); } + res } /// Converts `config` into a JSON-serialized string, such as '{"mode":"client","connect":{"endpoints":["tcp/127.0.0.1:7447"]}}'. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn zc_config_to_string(config: z_config_t) -> z_owned_str_t { - let config: &Config = match config.as_ref() { - Some(c) => c, - None => return z_str_null(), - }; +pub unsafe extern "C" fn zc_config_to_string( + config: &z_loaned_config_t, + config_string: *mut MaybeUninit, +) -> errors::z_error_t { + let config: &Config = config.transmute_ref(); match json5::to_string(config) { - Ok(s) => s.as_bytes().into(), - Err(_) => z_str_null(), + Ok(s) => { + unsafe { + z_str_from_substring(config_string, s.as_ptr() as *const libc::c_char, s.len()) + }; + errors::Z_OK + } + Err(_) => { + z_str_null(config_string); + errors::Z_EPARSE + } } } /// Constructs a configuration by parsing a file at `path`. Currently supported format is JSON5, a superset of JSON. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn zc_config_from_file(path: *const c_char) -> z_owned_config_t { +pub unsafe extern "C" fn zc_config_from_file( + this: *mut MaybeUninit, + path: *const c_char, +) -> errors::z_error_t { let path_str = CStr::from_ptr(path); - z_owned_config_t(std::mem::transmute(match path_str.to_str() { + let mut res = errors::Z_OK; + let config = match path_str.to_str() { Ok(path) => match zenoh::config::Config::from_file(path) { - Ok(c) => Some(Box::new(c)), + Ok(c) => Some(c), Err(e) => { log::error!("Couldn't read config from {}: {}", path, e); + res = errors::Z_EPARSE; None } }, Err(e) => { log::error!("Invalid path '{}': {}", path_str.to_string_lossy(), e); + res = errors::Z_EIO; None } - })) + }; + Inplace::init(this.transmute_uninit_ptr(), config); + res } /// Constructs a default, zenoh-allocated, peer mode configuration. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_config_peer() -> z_owned_config_t { - unsafe { z_owned_config_t(std::mem::transmute(Some(Box::new(zenoh::config::peer())))) } +pub extern "C" fn z_config_peer(this: *mut MaybeUninit) { + Inplace::init(this.transmute_uninit_ptr(), Some(zenoh::config::peer())); } /// Constructs a default, zenoh-allocated, client mode configuration. @@ -250,9 +268,11 @@ pub extern "C" fn z_config_peer() -> z_owned_config_t { #[allow(clippy::missing_safety_doc)] #[no_mangle] pub unsafe extern "C" fn z_config_client( + this: *mut MaybeUninit, peers: *const *const c_char, n_peers: usize, -) -> z_owned_config_t { +) -> z_error_t { + let mut res = errors::Z_OK; let locators = if peers.is_null() { Vec::new() } else if let Ok(locators) = std::slice::from_raw_parts(peers, n_peers) @@ -263,6 +283,7 @@ pub unsafe extern "C" fn z_config_client( |mut acc, it| match it { Err(e) => { log::error!("Error parsing peer address: {}", e); + res = errors::Z_EPARSE; Err(()) } Ok(loc) => { @@ -274,9 +295,12 @@ pub unsafe extern "C" fn z_config_client( { locators } else { - return z_owned_config_t(std::mem::transmute(None::>)); + z_config_null(this); + return res; }; - z_owned_config_t(std::mem::transmute(Some(Box::new(zenoh::config::client( - locators, - ))))) + Inplace::init( + this.transmute_uninit_ptr(), + Some(zenoh::config::client(locators)), + ); + res } diff --git a/src/context.rs b/src/context.rs new file mode 100644 index 000000000..2397b947e --- /dev/null +++ b/src/context.rs @@ -0,0 +1,117 @@ +// +// Copyright (c) 2017, 2022 ZettaScale Technology. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh team, +// + +use std::fmt::Debug; + +use libc::c_void; + +use crate::{decl_rust_copy_type, impl_guarded_transmute}; + +/// A trait for implementing droppable contexts +pub trait DroppableContext: Debug { + fn get(&self) -> *mut c_void; +} + +/// A non-tread-safe droppable context. +/// Contexts are idiomatically used in C together with callback interfaces to deliver associated state +/// information to each callback. +/// +/// This is a non-thread-safe context - zenoh-c guarantees that associated callbacks that share the same +/// zc_context_t instance will never be executed concurrently. In other words, the context data is not +/// required to be thread-safe. +/// NOTE: Remember that the same callback interfaces associated with different zc_context_t instances can +/// still be executed concurrently. The exact behavior depends on user's application, but we strongly +/// discourage our users from pinning to some specific behavior unless they _really_ understand what they +/// are doing. +/// +/// Once moved to zenoh-c ownership, this context is guaranteed to execute delete_fn when deleted. The +/// delete_fn is guaranteed to be executed only once at some point of time after the last associated +/// callback call returns. +/// NOTE: if user doesn't pass the instance of this context to zenoh-c, the delete_fn callback won't +/// be executed. +#[derive(Debug)] +#[repr(C)] +pub struct zc_context_t { + context: *mut c_void, + delete_fn: unsafe extern "C" fn(*mut c_void), +} + +decl_rust_copy_type!( + zenoh:(Context), + c:(zc_context_t) +); + +#[derive(Debug)] +#[repr(transparent)] +pub struct Context(zc_context_t); +impl DroppableContext for Context { + fn get(&self) -> *mut c_void { + self.0.context + } +} +impl Drop for Context { + fn drop(&mut self) { + unsafe { + (self.0.delete_fn)(self.0.context); + } + } +} + +/// A tread-safe droppable context. +/// Contexts are idiomatically used in C together with callback interfaces to deliver associated state +/// information to each callback. +/// +/// This is a thread-safe context - the associated callbacks may be executed concurrently with the same +/// zc_context_t instance. In other words, the context data MUST be thread-safe. +/// +/// Once moved to zenoh-c ownership, this context is guaranteed to execute delete_fn when deleted.The +/// delete_fn is guaranteed to be executed only once at some point of time after the last associated +/// callback call returns. +/// NOTE: if user doesn't pass the instance of this context to zenoh-c, the delete_fn callback won't +/// be executed. +#[derive(Debug)] +#[repr(C)] +pub struct zc_threadsafe_context_t { + context: zc_threadsafe_context_data_t, + delete_fn: unsafe extern "C" fn(*mut c_void), +} + +#[derive(Debug)] +#[repr(C)] +pub struct zc_threadsafe_context_data_t { + ptr: *mut c_void, +} +unsafe impl Send for zc_threadsafe_context_data_t {} +unsafe impl Sync for zc_threadsafe_context_data_t {} + +decl_rust_copy_type!( + zenoh:(ThreadsafeContext), + c:(zc_threadsafe_context_t) +); + +#[derive(Debug)] +#[repr(transparent)] +pub struct ThreadsafeContext(zc_threadsafe_context_t); +impl DroppableContext for ThreadsafeContext { + fn get(&self) -> *mut c_void { + self.0.context.ptr + } +} +impl Drop for ThreadsafeContext { + fn drop(&mut self) { + unsafe { + (self.0.delete_fn)(self.0.context.ptr); + } + } +} diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 000000000..c2abfbff4 --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,14 @@ +pub type z_error_t = i8; +pub const Z_OK: z_error_t = 0; +pub const Z_EINVAL: z_error_t = -1; +pub const Z_EPARSE: z_error_t = -2; +pub const Z_EIO: z_error_t = -3; +pub const Z_ENETWORK: z_error_t = -4; +pub const Z_ENULL: z_error_t = -5; +pub const Z_EUNAVAILABLE: z_error_t = -6; +// negativ pthread error codes (due to convention to return negative values on error) +pub const Z_EBUSY_MUTEX: z_error_t = -16; +pub const Z_EINVAL_MUTEX: z_error_t = -22; +pub const Z_EAGAIN_MUTEX: z_error_t = -11; +pub const Z_EPOISON_MUTEX: z_error_t = -22; // same as Z_EINVAL_MUTEX +pub const Z_EGENERIC: z_error_t = i8::MIN; diff --git a/src/get.rs b/src/get.rs index f5b3c6590..d627a9075 100644 --- a/src/get.rs +++ b/src/get.rs @@ -13,130 +13,71 @@ // use libc::c_char; -use libc::c_void; -use std::{ - borrow::Cow, - convert::TryFrom, - ffi::CStr, - ops::{Deref, DerefMut}, -}; - -use zenoh::{ - prelude::{ConsolidationMode, KeyExpr, QueryTarget, SplitBuffer}, - query::{Mode, QueryConsolidation, Reply}, - sample::AttachmentBuilder, - value::Value, -}; -use zenoh_util::core::{zresult::ErrNo, SyncResolve}; - -use crate::attachment::{ - insert_in_attachment_builder, z_attachment_check, z_attachment_iterate, z_attachment_null, - z_attachment_t, -}; +use std::ffi::CStr; +use std::mem::MaybeUninit; +use std::ptr::null; +use std::ptr::null_mut; +use zenoh::sample::SampleBuilderTrait; +use zenoh::sample::ValueBuilderTrait; + +use zenoh::prelude::{ConsolidationMode, Mode, QueryConsolidation, QueryTarget, Reply}; + +use crate::errors; +use crate::transmute::unwrap_ref_unchecked; +use crate::transmute::Inplace; +use crate::transmute::TransmuteFromHandle; +use crate::transmute::TransmuteIntoHandle; +use crate::transmute::TransmuteRef; +use crate::transmute::TransmuteUninitPtr; +use crate::z_consolidation_mode_t; +use crate::z_loaned_query_target_t; +use crate::z_loaned_sample_t; +use crate::z_loaned_value_t; +use crate::z_owned_bytes_t; +use crate::z_owned_encoding_t; use crate::{ - impl_guarded_transmute, z_bytes_t, z_closure_reply_call, z_encoding_default, z_encoding_t, - z_keyexpr_t, z_owned_closure_reply_t, z_sample_t, z_session_t, GuardedTransmute, - LOG_INVALID_SESSION, + z_closure_reply_call, z_loaned_keyexpr_t, z_loaned_session_t, z_owned_closure_reply_t, }; +use zenoh::prelude::SyncResolve; -type ReplyInner = Option; - -/// An owned reply to a :c:func:`z_get`. -/// -/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. -#[cfg(not(target_arch = "arm"))] -#[repr(C, align(8))] -pub struct z_owned_reply_t([u64; 30]); - -#[cfg(target_arch = "arm")] -#[repr(C, align(8))] -pub struct z_owned_reply_t([u64; 19]); +pub use crate::opaque_types::z_owned_reply_t; +decl_transmute_owned!(Option, z_owned_reply_t); +pub use crate::opaque_types::z_loaned_reply_t; +decl_transmute_handle!(Reply, z_loaned_reply_t); -impl_guarded_transmute!(noderefs ReplyInner, z_owned_reply_t); - -impl From for z_owned_reply_t { - fn from(mut val: ReplyInner) -> Self { - if let Some(val) = &mut val { - match &mut val.sample { - Ok(inner) => inner.payload = inner.payload.contiguous().into_owned().into(), - Err(inner) => inner.payload = inner.payload.contiguous().into_owned().into(), - }; - } - val.transmute() - } -} -impl From for z_owned_reply_t { - fn from(val: Reply) -> z_owned_reply_t { - Some(val).into() - } -} -impl Deref for z_owned_reply_t { - type Target = ReplyInner; - fn deref(&self) -> &Self::Target { - unsafe { std::mem::transmute::<&Self, &Self::Target>(self) } - } -} -impl DerefMut for z_owned_reply_t { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { std::mem::transmute::<&mut Self, &mut Self::Target>(self) } - } -} /// Returns ``true`` if the queryable answered with an OK, which allows this value to be treated as a sample. /// /// If this returns ``false``, you should use :c:func:`z_check` before trying to use :c:func:`z_reply_err` if you want to process the error that may be here. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_reply_is_ok(reply: &z_owned_reply_t) -> bool { - reply.as_ref().map(|r| r.sample.is_ok()).unwrap_or(false) +pub unsafe extern "C" fn z_reply_is_ok(reply: &z_loaned_reply_t) -> bool { + let reply = reply.transmute_ref(); + reply.result().is_ok() } /// Yields the contents of the reply by asserting it indicates a success. /// -/// You should always make sure that :c:func:`z_reply_is_ok` returns ``true`` before calling this function. +/// Returns null if reply does not contains a sample (i. e. if :c:func:`z_reply_is_ok` returns ``false``). #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_reply_ok(reply: &z_owned_reply_t) -> z_sample_t { - if let Some(sample) = reply.as_ref().and_then(|s| s.sample.as_ref().ok()) { - if let Cow::Owned(_) = sample.payload.contiguous() { - unreachable!("z_reply_ok found a payload that wasn't contiguous by the time it was reached, which breaks some crate assertions. This is definitely a bug with zenoh, please contact us.") - } - z_sample_t::new(sample, &sample.payload) - } else { - panic!("Assertion failed: tried to treat `z_owned_reply_t` as Ok despite that not being the case") +pub unsafe extern "C" fn z_reply_ok(reply: &z_loaned_reply_t) -> *const z_loaned_sample_t { + let reply = reply.transmute_ref(); + match reply.result() { + Ok(sample) => sample.transmute_handle(), + Err(_) => null(), } } -/// A zenoh value. -/// -/// Members: -/// z_bytes_t payload: The payload of this zenoh value. -/// z_encoding_t encoding: The encoding of this zenoh value `payload`. -#[repr(C)] -pub struct z_value_t { - pub payload: z_bytes_t, - pub encoding: z_encoding_t, -} - /// Yields the contents of the reply by asserting it indicates a failure. /// -/// You should always make sure that :c:func:`z_reply_is_ok` returns ``false`` before calling this function. +/// Returns null if reply does not contain a error (i. e. if :c:func:`z_reply_is_ok` returns ``true``). #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_reply_err(reply: &z_owned_reply_t) -> z_value_t { - if let Some(inner) = reply.as_ref().and_then(|s| s.sample.as_ref().err()) { - z_value_t { - payload: match &inner.payload.contiguous() { - Cow::Borrowed(payload) => crate::z_bytes_t { start: payload.as_ptr(), len: payload.len() }, - Cow::Owned(_) => unreachable!("z_reply_err found a payload that wasn't contiguous by the time it was reached, which breaks some crate assertions."), - }, - encoding: (&inner.encoding).into(), - } - } else { - panic!("Assertion failed: tried to treat `z_owned_reply_t` as Err despite that not being the case") +pub unsafe extern "C" fn z_reply_err(reply: &z_loaned_reply_t) -> *const z_loaned_value_t { + let reply = reply.transmute_ref(); + match reply.result() { + Ok(_) => null(), + Err(v) => v.transmute_handle(), } } @@ -148,41 +89,45 @@ pub unsafe extern "C" fn z_reply_err(reply: &z_owned_reply_t) -> z_value_t { /// - overwrite the pointee with this function's return value, /// - you are now responsible for dropping your copy of the reply. #[no_mangle] -#[allow(improper_ctypes_definitions)] -pub extern "C" fn z_reply_null() -> z_owned_reply_t { - None.into() +pub extern "C" fn z_reply_null(this: *mut MaybeUninit) { + Inplace::empty(this.transmute_uninit_ptr()); +} + +#[no_mangle] +pub extern "C" fn z_reply_clone(this: *mut MaybeUninit, reply: &z_loaned_reply_t) { + Inplace::init( + this.transmute_uninit_ptr(), + Some(reply.transmute_ref().clone()), + ); } /// Options passed to the :c:func:`z_get` function. /// /// Members: -/// z_query_target_t target: The Queryables that should be target of the query. +/// z_loaned_query_target_t target: The Queryables that should be target of the query. /// z_query_consolidation_t consolidation: The replies consolidation strategy to apply on replies to the query. -/// z_value_t value: An optional value to attach to the query. -/// z_attachment_t attachment: The attachment to attach to the query. +/// z_loaned_value_t value: An optional value to attach to the query. +/// z_loaned_bytes_t attachment: The attachment to attach to the query. /// uint64_t timeout: The timeout for the query in milliseconds. 0 means default query timeout from zenoh configuration. #[repr(C)] pub struct z_get_options_t { - pub target: z_query_target_t, + pub target: z_loaned_query_target_t, pub consolidation: z_query_consolidation_t, - pub value: z_value_t, - pub attachment: z_attachment_t, + pub payload: *mut z_owned_bytes_t, + pub encoding: *mut z_owned_encoding_t, + pub attachment: *mut z_owned_bytes_t, pub timeout_ms: u64, } #[no_mangle] -pub extern "C" fn z_get_options_default() -> z_get_options_t { - z_get_options_t { +pub extern "C" fn z_get_options_default(this: &mut z_get_options_t) { + *this = z_get_options_t { target: QueryTarget::default().into(), consolidation: QueryConsolidation::default().into(), timeout_ms: 0, - value: { - z_value_t { - payload: z_bytes_t::empty(), - encoding: z_encoding_default(), - } - }, - attachment: z_attachment_null(), - } + payload: null_mut(), + encoding: null_mut(), + attachment: null_mut(), + }; } /// Query data from the matching queryables in the system. @@ -192,7 +137,7 @@ pub extern "C" fn z_get_options_default() -> z_get_options_t { /// /// Parameters: /// session: The zenoh session. -/// keyexpr: The key expression matching resources to query. +/// key_expr: The key expression matching resources to query. /// parameters: The query's parameters, similar to a url's query segment. /// callback: The callback function that will be called on reception of replies for this query. /// Note that the `reply` parameter of the callback is passed by mutable reference, @@ -202,12 +147,12 @@ pub extern "C" fn z_get_options_default() -> z_get_options_t { #[allow(clippy::missing_safety_doc)] #[no_mangle] pub unsafe extern "C" fn z_get( - session: z_session_t, - keyexpr: z_keyexpr_t, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, parameters: *const c_char, callback: &mut z_owned_closure_reply_t, - options: Option<&z_get_options_t>, -) -> i8 { + options: Option<&mut z_get_options_t>, +) -> errors::z_error_t { let mut closure = z_owned_closure_reply_t::empty(); std::mem::swap(callback, &mut closure); let p = if parameters.is_null() { @@ -215,180 +160,58 @@ pub unsafe extern "C" fn z_get( } else { CStr::from_ptr(parameters).to_str().unwrap() }; - let Some(s) = session.upgrade() else { - log::error!("{LOG_INVALID_SESSION}"); - return i8::MIN; - }; - let mut q = s.get(KeyExpr::try_from(keyexpr).unwrap().with_parameters(p)); + let session = session.transmute_ref(); + let key_expr = key_expr.transmute_ref(); + + let mut get = session.get(key_expr.clone().with_parameters(p)); if let Some(options) = options { - q = q - .consolidation(options.consolidation) - .target(options.target.into()) - .with_value(&options.value); - if options.timeout_ms != 0 { - q = q.timeout(std::time::Duration::from_millis(options.timeout_ms)); + if !options.payload.is_null() { + if let Some(payload) = unsafe { *options.payload }.transmute_mut().extract() { + get = get.payload(payload); + } + } + if !options.encoding.is_null() { + let encoding = unsafe { *options.encoding }.transmute_mut().extract(); + get = get.encoding(encoding); + } + if !options.attachment.is_null() { + let attachment = unsafe { *options.payload }.transmute_mut().extract(); + get = get.attachment(attachment); } - if z_attachment_check(&options.attachment) { - let mut attachment_builder = AttachmentBuilder::new(); - z_attachment_iterate( - options.attachment, - insert_in_attachment_builder, - &mut attachment_builder as *mut AttachmentBuilder as *mut c_void, - ); - q = q.with_attachment(attachment_builder.build()); - }; + + get = get + .consolidation(options.consolidation) + .timeout(std::time::Duration::from_millis(options.timeout_ms)) + .target(options.target.into()); } - match q - .callback(move |response| z_closure_reply_call(&closure, &mut response.into())) + match get + .callback(move |response| z_closure_reply_call(&closure, response.transmute_handle())) .res_sync() { - Ok(()) => 0, + Ok(()) => errors::Z_OK, Err(e) => { log::error!("{}", e); - e.errno().get() + errors::Z_EGENERIC } } } -/// Frees `reply_data`, invalidating it for double-drop safety. +/// Frees `reply`, invalidating it for double-drop safety. #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_reply_drop(reply_data: &mut z_owned_reply_t) { - std::mem::drop(reply_data.take()); +pub extern "C" fn z_reply_drop(this: &mut z_owned_reply_t) { + Inplace::drop(this.transmute_mut()) } -/// Returns ``true`` if `reply_data` is valid. +/// Returns ``true`` if `reply` is valid. #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_reply_check(reply_data: &z_owned_reply_t) -> bool { - reply_data.is_some() -} - -/// The Queryables that should be target of a :c:func:`z_get`. -/// -/// - **BEST_MATCHING**: The nearest complete queryable if any else all matching queryables. -/// - **ALL_COMPLETE**: All complete queryables. -/// - **ALL**: All matching queryables. -#[allow(non_camel_case_types)] -#[repr(C)] -#[derive(Clone, Copy)] -pub enum z_query_target_t { - BEST_MATCHING, - ALL, - ALL_COMPLETE, -} - -impl From for z_query_target_t { - #[inline] - fn from(t: QueryTarget) -> Self { - match t { - QueryTarget::BestMatching => z_query_target_t::BEST_MATCHING, - QueryTarget::All => z_query_target_t::ALL, - QueryTarget::AllComplete => z_query_target_t::ALL_COMPLETE, - } - } +pub extern "C" fn z_reply_check(this: &z_owned_reply_t) -> bool { + this.transmute_ref().is_some() } -impl From for QueryTarget { - #[inline] - fn from(val: z_query_target_t) -> Self { - match val { - z_query_target_t::BEST_MATCHING => QueryTarget::BestMatching, - z_query_target_t::ALL => QueryTarget::All, - z_query_target_t::ALL_COMPLETE => QueryTarget::AllComplete, - } - } -} - -impl From<&z_value_t> for Value { - #[inline] - fn from(val: &z_value_t) -> Value { - unsafe { - let value: Value = - std::slice::from_raw_parts(val.payload.start, val.payload.len).into(); - let encoding = std::str::from_utf8(std::slice::from_raw_parts( - val.encoding.suffix.start, - val.encoding.suffix.len, - )) - .expect("encodings must be UTF8"); - value.encoding( - zenoh::prelude::Encoding::new(val.encoding.prefix as u8, encoding).unwrap(), - ) - } - } -} - -impl From<&Value> for z_value_t { - #[inline] - fn from(val: &Value) -> z_value_t { - let std::borrow::Cow::Borrowed(payload) = val.payload.contiguous() else { - panic!("Would have returned a reference to a temporary, make sure you the Value's payload is contiguous BEFORE calling this constructor.") - }; - z_value_t { - encoding: (&val.encoding).into(), - payload: payload.into(), - } - } -} - -/// Create a default :c:type:`z_query_target_t`. #[no_mangle] -pub extern "C" fn z_query_target_default() -> z_query_target_t { - QueryTarget::default().into() -} - -/// Consolidation mode values. -/// -/// - **Z_CONSOLIDATION_MODE_AUTO**: Let Zenoh decide the best consolidation mode depending on the query selector -/// If the selector contains time range properties, consolidation mode `NONE` is used. -/// Otherwise the `LATEST` consolidation mode is used. -/// - **Z_CONSOLIDATION_MODE_NONE**: No consolidation is applied. Replies may come in any order and any number. -/// - **Z_CONSOLIDATION_MODE_MONOTONIC**: It guarantees that any reply for a given key expression will be monotonic in time -/// w.r.t. the previous received replies for the same key expression. I.e., for the same key expression multiple -/// replies may be received. It is guaranteed that two replies received at t1 and t2 will have timestamp -/// ts2 > ts1. It optimizes latency. -/// - **Z_CONSOLIDATION_MODE_LATEST**: It guarantees unicity of replies for the same key expression. -/// It optimizes bandwidth. -#[repr(C)] -#[derive(Clone, Copy, Default)] -pub enum z_consolidation_mode_t { - AUTO = -1, - #[default] - NONE = 0, - MONOTONIC = 1, - LATEST = 2, -} - -impl From> for z_consolidation_mode_t { - #[inline] - fn from(cm: Mode) -> Self { - match cm { - Mode::Manual(cm) => Self::from(cm), - Mode::Auto => z_consolidation_mode_t::AUTO, - } - } -} - -impl From for z_consolidation_mode_t { - #[inline] - fn from(cm: ConsolidationMode) -> Self { - match cm { - ConsolidationMode::None => z_consolidation_mode_t::NONE, - ConsolidationMode::Monotonic => z_consolidation_mode_t::MONOTONIC, - ConsolidationMode::Latest => z_consolidation_mode_t::LATEST, - } - } -} - -impl From for Mode { - #[inline] - fn from(val: z_consolidation_mode_t) -> Self { - match val { - z_consolidation_mode_t::AUTO => Mode::Auto, - z_consolidation_mode_t::NONE => Mode::Manual(ConsolidationMode::None), - z_consolidation_mode_t::MONOTONIC => Mode::Manual(ConsolidationMode::Monotonic), - z_consolidation_mode_t::LATEST => Mode::Manual(ConsolidationMode::Latest), - } - } +pub extern "C" fn z_reply_loan(this: &mut z_owned_reply_t) -> &z_loaned_reply_t { + let this = this.transmute_ref(); + let this = unwrap_ref_unchecked(this); + this.transmute_handle() } /// The replies consolidation strategy to apply on replies to a :c:func:`z_get`. diff --git a/src/info.rs b/src/info.rs index 326b468bb..a7a23131e 100644 --- a/src/info.rs +++ b/src/info.rs @@ -1,3 +1,4 @@ +use crate::transmute::{TransmuteCopy, TransmuteFromHandle}; // // Copyright (c) 2017, 2022 ZettaScale Technology. // @@ -11,18 +12,19 @@ // Contributors: // ZettaScale Zenoh team, // -use crate::{session::*, z_closure_zid_call, z_owned_closure_zid_t}; +use crate::{errors, z_closure_zid_call, z_loaned_session_t, z_owned_closure_zid_t}; +use std::mem::MaybeUninit; +use zenoh::config::ZenohId; use zenoh::prelude::sync::SyncResolve; -use zenoh::SessionDeclarations; -use zenoh_protocol::core::ZenohId; +use zenoh::session::SessionDeclarations; -/// Represents a Zenoh ID. -/// -/// In general, valid Zenoh IDs are LSB-first 128bit unsigned and non-zero integers. -#[repr(C)] -#[derive(Debug, Clone, Copy)] -pub struct z_id_t { - pub id: [u8; 16], +pub use crate::opaque_types::z_id_t; +decl_transmute_copy!(ZenohId, z_id_t); + +impl From<[u8; 16]> for z_id_t { + fn from(value: [u8; 16]) -> Self { + unsafe { std::mem::transmute(value) } + } } /// Returns the local Zenoh ID. @@ -32,11 +34,9 @@ pub struct z_id_t { /// to pass it a valid session. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_info_zid(session: z_session_t) -> z_id_t { - match session.upgrade() { - Some(s) => std::mem::transmute::(s.info().zid().res_sync()), - None => z_id_t { id: [0; 16] }, - } +pub unsafe extern "C" fn z_info_zid(session: z_loaned_session_t) -> z_id_t { + let session = session.transmute_ref(); + session.info().zid().res_sync().transmute_copy() } /// Fetches the Zenoh IDs of all connected peers. @@ -48,20 +48,16 @@ pub unsafe extern "C" fn z_info_zid(session: z_session_t) -> z_id_t { #[allow(clippy::missing_safety_doc)] #[no_mangle] pub unsafe extern "C" fn z_info_peers_zid( - session: z_session_t, + session: z_loaned_session_t, callback: &mut z_owned_closure_zid_t, -) -> i8 { +) -> errors::z_error_t { let mut closure = z_owned_closure_zid_t::empty(); std::mem::swap(&mut closure, callback); - match session.upgrade() { - Some(s) => { - for id in s.info().peers_zid().res_sync() { - z_closure_zid_call(&closure, &std::mem::transmute(id)); - } - 0 - } - None => i8::MIN, + let session = session.transmute_ref(); + for id in session.info().peers_zid().res_sync() { + z_closure_zid_call(&closure, &id.transmute_copy()); } + errors::Z_OK } /// Fetches the Zenoh IDs of all connected routers. @@ -73,18 +69,14 @@ pub unsafe extern "C" fn z_info_peers_zid( #[allow(clippy::missing_safety_doc)] #[no_mangle] pub unsafe extern "C" fn z_info_routers_zid( - session: z_session_t, + session: z_loaned_session_t, callback: &mut z_owned_closure_zid_t, -) -> i8 { +) -> errors::z_error_t { let mut closure = z_owned_closure_zid_t::empty(); std::mem::swap(&mut closure, callback); - match session.upgrade() { - Some(s) => { - for id in s.info().routers_zid().res_sync() { - z_closure_zid_call(&closure, &std::mem::transmute(id)); - } - 0 - } - None => i8::MIN, + let session = session.transmute_ref(); + for id in session.info().routers_zid().res_sync() { + z_closure_zid_call(&closure, &id.transmute_copy()); } + errors::Z_OK } diff --git a/src/keyexpr.rs b/src/keyexpr.rs index 7742b3948..4c2e75494 100644 --- a/src/keyexpr.rs +++ b/src/keyexpr.rs @@ -12,142 +12,165 @@ // ZettaScale Zenoh team, // -use std::convert::TryFrom; -use std::ops::Deref; -use std::ops::DerefMut; - -use crate::impl_guarded_transmute; -use crate::session::*; -use crate::z_bytes_t; +use std::mem::MaybeUninit; + +use crate::errors; +use crate::errors::z_error_t; +use crate::errors::Z_OK; +use crate::transmute::unwrap_ref_unchecked; +use crate::transmute::Inplace; +use crate::transmute::TransmuteFromHandle; +use crate::transmute::TransmuteIntoHandle; +use crate::transmute::TransmuteRef; +use crate::transmute::TransmuteUninitPtr; +use crate::z_loaned_session_t; use crate::z_owned_str_t; -use crate::z_str_null; -use crate::GuardedTransmute; -use crate::LOG_INVALID_SESSION; +use crate::z_str_from_substring; +use crate::z_view_slice_t; +use crate::z_view_slice_wrap; use libc::c_char; +use std::error::Error; +use zenoh::core::SyncResolve; use zenoh::key_expr::SetIntersectionLevel; use zenoh::prelude::keyexpr; -use zenoh::prelude::sync::SyncResolve; use zenoh::prelude::KeyExpr; -use zenoh_util::core::zresult::ErrNo; +use zenoh_protocol::core::key_expr::canon::Canonizable; -/// A zenoh-allocated key expression. -/// -/// Key expressions can identify a single key or a set of keys. -/// -/// Examples : -/// - ``"key/expression"``. -/// - ``"key/ex*"``. -/// -/// Key expressions can be mapped to numerical ids through :c:func:`z_declare_expr` -/// for wire and computation efficiency. -/// -/// A `key expression `_ can be either: -/// - A plain string expression. -/// - A pure numerical id. -/// - The combination of a numerical prefix and a string suffix. -/// -/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. -/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. -/// -/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. -#[cfg(not(target_arch = "arm"))] -#[repr(C, align(8))] -pub struct z_owned_keyexpr_t([u64; 4]); -#[cfg(target_arch = "arm")] -#[repr(C, align(4))] -pub struct z_owned_keyexpr_t([u32; 5]); - -impl_guarded_transmute!(Option>, z_owned_keyexpr_t); - -impl From> for z_owned_keyexpr_t { - fn from(val: KeyExpr<'static>) -> Self { - Some(val).into() - } -} -impl z_owned_keyexpr_t { - pub fn null() -> Self { - None::.into() - } -} +pub use crate::opaque_types::z_owned_keyexpr_t; +pub use crate::opaque_types::z_view_keyexpr_t; +decl_transmute_owned!(Option>, z_owned_keyexpr_t); +decl_transmute_owned!(custom_inplace_init Option>, z_view_keyexpr_t); /// Constructs a null safe-to-drop value of 'z_owned_keyexpr_t' type #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_keyexpr_null() -> z_owned_keyexpr_t { - z_owned_keyexpr_t::null() +pub extern "C" fn z_keyexpr_null(this: *mut MaybeUninit) { + Inplace::empty(this.transmute_uninit_ptr()); } -/// Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string. -#[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_keyexpr_new(name: *const c_char) -> z_owned_keyexpr_t { - if name.is_null() { - return z_owned_keyexpr_t::null(); +pub extern "C" fn z_view_keyexpr_null(this: *mut MaybeUninit) { + Inplace::empty(this.transmute_uninit_ptr()); +} + +fn keyexpr_create_inner( + mut name: &'static mut str, + should_auto_canonize: bool, + should_copy: bool, +) -> Result, Box> { + if should_copy { + let s = name.to_string(); + match should_auto_canonize { + true => KeyExpr::<'static>::autocanonize(s), + false => KeyExpr::<'static>::try_from(s), + } + } else { + if should_auto_canonize { + name.canonize(); + } + return keyexpr::new(name).map(|k| k.into()); } - let name = std::slice::from_raw_parts(name as _, libc::strlen(name)); - match std::str::from_utf8(name) { - Ok(name) => match KeyExpr::try_from(name) { - Ok(v) => v.into_owned().into(), +} + +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +unsafe fn keyexpr_create( + name: &'static mut [u8], + should_auto_canonize: bool, + should_copy: bool, +) -> Result, errors::z_error_t> { + match std::str::from_utf8_mut(name) { + Ok(name) => match keyexpr_create_inner(name, should_auto_canonize, should_copy) { + Ok(v) => Ok(v), Err(e) => { - log::error!("Couldn't construct a keyexpr from {:02x?}: {}", name, e); - z_owned_keyexpr_t::null() + log::error!("Couldn't construct a keyexpr: {}", e); + Err(errors::Z_EINVAL) } }, Err(e) => { log::error!("{}", e); - z_owned_keyexpr_t::null() + Err(errors::Z_EPARSE) } } } -/// Constructs a :c:type:`z_keyexpr_t` departing from a string, copying the passed string. The copied string is canonized. +/// Constructs a :c:type:`z_owned_keyexpr_t` departing from a string, copying the passed string. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_keyexpr_new_autocanonize(name: *const c_char) -> z_owned_keyexpr_t { +pub unsafe extern "C" fn z_keyexpr_new( + name: *const c_char, + this: *mut MaybeUninit, +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); if name.is_null() { - return z_owned_keyexpr_t::null(); + Inplace::empty(this); + return errors::Z_EINVAL; + } + let name = std::slice::from_raw_parts_mut(name as _, libc::strlen(name)); + match keyexpr_create(name, false, true) { + Ok(ke) => { + Inplace::init(this, Some(ke)); + errors::Z_OK + } + Err(e) => { + Inplace::empty(this); + e + } } - let name = std::slice::from_raw_parts(name as _, libc::strlen(name)); - match std::str::from_utf8(name) { - Ok(name) => { - let name_owned = name.to_owned(); - match KeyExpr::autocanonize(name_owned) { - Ok(v) => v.into_owned().into(), - Err(e) => { - log::error!("Couldn't construct a keyexpr from {:02x?}: {}", name, e); - z_owned_keyexpr_t::null() - } - } +} + +/// Constructs a :c:type:`z_owned_keyexpr_t` departing from a string, copying the passed string. The copied string is canonized. +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +pub unsafe extern "C" fn z_keyexpr_new_autocanonize( + name: *const c_char, + this: *mut MaybeUninit, +) -> z_error_t { + let this = this.transmute_uninit_ptr(); + if name.is_null() { + Inplace::empty(this); + return errors::Z_EINVAL; + } + let name = std::slice::from_raw_parts_mut(name as _, libc::strlen(name)); + match keyexpr_create(name, true, true) { + Ok(ke) => { + Inplace::init(this, Some(ke)); + errors::Z_OK } Err(e) => { - log::error!("{}", e); - z_owned_keyexpr_t::null() + Inplace::empty(this); + e } } } -/// Returns a :c:type:`z_keyexpr_t` loaned from :c:type:`z_owned_keyexpr_t`. +/// Returns a :c:type:`z_loaned_keyexpr_t` loaned from :c:type:`z_owned_keyexpr_t`. #[no_mangle] -pub extern "C" fn z_keyexpr_loan(keyexpr: &z_owned_keyexpr_t) -> z_keyexpr_t { - keyexpr.as_ref().map(|k| k.borrowing_clone()).into() +pub extern "C" fn z_keyexpr_loan(key_expr: &z_owned_keyexpr_t) -> &z_loaned_keyexpr_t { + unwrap_ref_unchecked(key_expr.transmute_ref()).transmute_handle() +} + +/// Returns a :c:type:`z_loaned_keyexpr_t` loaned from :c:type:`z_owned_keyexpr_t`. +#[no_mangle] +pub extern "C" fn z_view_keyexpr_loan(key_expr: &z_view_keyexpr_t) -> &z_loaned_keyexpr_t { + unwrap_ref_unchecked(key_expr.transmute_ref()).transmute_handle() } /// Frees `keyexpr` and invalidates it for double-drop safety. #[no_mangle] -#[allow(clippy::missing_safety_doc)] pub extern "C" fn z_keyexpr_drop(keyexpr: &mut z_owned_keyexpr_t) { - std::mem::drop(keyexpr.take()) + Inplace::drop(keyexpr.transmute_mut()); } /// Returns ``true`` if `keyexpr` is valid. #[no_mangle] -#[allow(clippy::missing_safety_doc)] pub extern "C" fn z_keyexpr_check(keyexpr: &z_owned_keyexpr_t) -> bool { - keyexpr.deref().is_some() + keyexpr.transmute_ref().is_some() +} + +/// Returns ``true`` if `keyexpr` is valid. +#[no_mangle] +pub extern "C" fn z_view_keyexpr_check(keyexpr: &z_view_keyexpr_t) -> bool { + keyexpr.transmute_ref().is_some() } /// A loaned key expression. @@ -160,94 +183,18 @@ pub extern "C" fn z_keyexpr_check(keyexpr: &z_owned_keyexpr_t) -> bool { /// /// Using :c:func:`z_declare_keyexpr` allows zenoh to optimize a key expression, /// both for local processing and network-wise. -#[cfg(not(target_arch = "arm"))] -#[repr(C, align(8))] -pub struct z_keyexpr_t([u64; 4]); -#[cfg(target_arch = "arm")] -#[repr(C, align(4))] -pub struct z_keyexpr_t([u32; 5]); - -impl_guarded_transmute!(noderefs Option>, z_keyexpr_t); -impl_guarded_transmute!(noderefs z_keyexpr_t, z_owned_keyexpr_t); - -impl<'a> From> for z_keyexpr_t { - fn from(val: KeyExpr<'a>) -> Self { - Some(val).into() - } -} - -impl From for z_owned_keyexpr_t { - fn from(oke: z_keyexpr_t) -> Self { - oke.transmute() - } -} - -impl<'a> From>> for z_keyexpr_t { - fn from(val: Option>) -> Self { - val.transmute() - } -} -impl Deref for z_keyexpr_t { - type Target = Option>; - fn deref(&self) -> &Self::Target { - unsafe { std::mem::transmute(self) } - } -} -impl DerefMut for z_keyexpr_t { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { std::mem::transmute(self) } - } -} -impl z_keyexpr_t { - pub fn null() -> Self { - None.into() - } -} -#[derive(Debug, Clone, Copy)] -pub struct UninitializedKeyExprError; -impl std::fmt::Display for UninitializedKeyExprError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - f.write_str("Uninitialized Key Expression detected, make sure you use `z_keyexpr_check` or `z_loaned_keyexpr_check` after constructing your key expressions") - } -} -impl std::error::Error for UninitializedKeyExprError {} -impl<'a> TryFrom for KeyExpr<'a> { - type Error = UninitializedKeyExprError; - fn try_from(value: z_keyexpr_t) -> Result { - match value.as_ref() { - Some(ke) => { - Ok(unsafe { std::mem::transmute::>(ke.borrowing_clone()) }) - } - None => Err(UninitializedKeyExprError), - } - } -} - -/// Returns ``true`` if `keyexpr` is initialized. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_keyexpr_is_initialized(keyexpr: &z_keyexpr_t) -> bool { - keyexpr.deref().is_some() -} +pub use crate::opaque_types::z_loaned_keyexpr_t; +decl_transmute_handle!(KeyExpr<'static>, z_loaned_keyexpr_t); /// Returns ``0`` if the passed string is a valid (and canon) key expression. /// Otherwise returns error value #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_keyexpr_is_canon(start: *const c_char, len: usize) -> i8 { - let name = std::slice::from_raw_parts(start as _, len); - match std::str::from_utf8(name) { - Ok(name) => match keyexpr::new(name) { - Ok(_) => 0, - Err(e) => { - log::error!("Couldn't construct a keyexpr from `{}`: {}", name, e); - e.errno().get() - } - }, - Err(e) => { - log::error!("{:02x?} is not valid UTF8 {}", name, e); - i8::MIN - } +pub unsafe extern "C" fn z_keyexpr_is_canon(start: *const c_char, len: usize) -> z_error_t { + let name = std::slice::from_raw_parts_mut(start as _, len); + match keyexpr_create(name, false, false) { + Ok(_) => errors::Z_OK, + Err(e) => e, } } @@ -260,12 +207,12 @@ pub unsafe extern "C" fn z_keyexpr_is_canon(start: *const c_char, len: usize) -> /// May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_keyexpr_canonize_null_terminated(start: *mut c_char) -> i8 { +pub unsafe extern "C" fn z_keyexpr_canonize_null_terminated(start: *mut c_char) -> z_error_t { let mut len = libc::strlen(start); match z_keyexpr_canonize(start, &mut len) { - 0 => { + Z_OK => { *start.add(len) = 0; - 0 + Z_OK } err => err, } @@ -279,90 +226,113 @@ pub unsafe extern "C" fn z_keyexpr_canonize_null_terminated(start: *mut c_char) /// May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_keyexpr_canonize(start: *mut c_char, len: &mut usize) -> i8 { +pub unsafe extern "C" fn z_keyexpr_canonize(start: *mut c_char, len: &mut usize) -> z_error_t { let name = std::slice::from_raw_parts_mut(start as _, *len); - match std::str::from_utf8_mut(name) { - Ok(mut name) => match keyexpr::autocanonize(&mut name) { - Ok(k) => { - *len = k.len(); - 0 - } - Err(e) => { - log::error!("Canonization error: {e}"); - e.errno().get() - } - }, - Err(e) => { - log::error!("{:02x?} is not valid UTF8 {}", name, e); - i8::MIN + match keyexpr_create(name, true, false) { + Ok(ke) => { + *len = ke.len(); + errors::Z_OK } + Err(e) => e, } } -/// Constructs a :c:type:`z_keyexpr_t` departing from a string. -/// It is a loaned key expression that aliases `name`. +/// Constructs a :c:type:`z_loaned_keyexpr_t` by aliasing a string. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn zc_keyexpr_from_slice(name: *const c_char, len: usize) -> z_keyexpr_t { - let name = std::slice::from_raw_parts(name as _, len); - match std::str::from_utf8(name) { - Ok(name) => match KeyExpr::try_from(name) { - Ok(v) => v.into(), - Err(e) => { - log::error!("Couldn't construct a keyexpr from `{}`: {}", name, e); - z_keyexpr_t::null() - } - }, +pub unsafe extern "C" fn z_view_keyexpr_from_slice( + this: *mut MaybeUninit, + name: *const c_char, + len: usize, +) -> z_error_t { + let this = this.transmute_uninit_ptr(); + if name.is_null() { + Inplace::empty(this); + return errors::Z_EINVAL; + } + let name = std::slice::from_raw_parts_mut(name as _, len); + match keyexpr_create(name, false, false) { + Ok(ke) => { + Inplace::init(this, Some(ke)); + errors::Z_OK + } Err(e) => { - log::error!("{:02x?} is not valid UTF8 {}", name, e); - z_keyexpr_t::null() + Inplace::empty(this); + e } } } -/// Constructs a :c:type:`z_keyexpr_t` departing from a string. -/// It is a loaned key expression that aliases `name`. +/// Constructs a :c:type:`z_loaned_keyexpr_t` by aliasing a string. /// The string is canonized in-place before being passed to keyexpr. /// May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn zc_keyexpr_from_slice_autocanonize( +pub unsafe extern "C" fn z_view_keyexpr_from_slice_autocanonize( + this: *mut MaybeUninit, name: *mut c_char, len: &mut usize, -) -> z_keyexpr_t { - if z_keyexpr_canonize(name, len) < 0 { - return z_keyexpr_t::null(); +) -> z_error_t { + let this = this.transmute_uninit_ptr(); + if name.is_null() { + Inplace::empty(this); + return errors::Z_EINVAL; + } + let name = std::slice::from_raw_parts_mut(name as _, libc::strlen(name)); + + match keyexpr_create(name, true, false) { + Ok(ke) => { + *len = ke.len(); + Inplace::init(this, Some(ke)); + errors::Z_OK + } + Err(e) => { + Inplace::empty(this); + e + } } - zc_keyexpr_from_slice(name, *len) } -/// Constructs a :c:type:`z_keyexpr_t` departing from a string. +/// Constructs a :c:type:`z_loaned_keyexpr_t` departing from a string. /// It is a loaned key expression that aliases `name`. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_keyexpr(name: *const c_char) -> z_keyexpr_t { +pub unsafe extern "C" fn z_view_keyexpr( + this: *mut MaybeUninit, + name: *const c_char, +) -> z_error_t { if name.is_null() { - z_keyexpr_t::null() + Inplace::empty(this.transmute_uninit_ptr()); + errors::Z_EINVAL } else { - zc_keyexpr_from_slice(name, libc::strlen(name)) + let len = libc::strlen(name); + z_view_keyexpr_from_slice(this, name, len) } } -/// Constructs a :c:type:`z_keyexpr_t` departing from a string. -/// It is a loaned key expression that aliases `name`. +/// Constructs a :c:type:`z_loaned_keyexpr_t` by aliasing a string. /// The string is canonized in-place before being passed to keyexpr. /// May SEGFAULT if `start` is NULL or lies in read-only memory (as values initialized with string litterals do). #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_keyexpr_autocanonize(name: *mut c_char) -> z_keyexpr_t { - if name.is_null() || z_keyexpr_canonize_null_terminated(name) < 0 { - z_keyexpr_t::null() +pub unsafe extern "C" fn z_view_keyexpr_autocanonize( + this: *mut MaybeUninit, + name: *mut c_char, +) -> z_error_t { + if name.is_null() { + Inplace::empty(this.transmute_uninit_ptr()); + errors::Z_EINVAL } else { - z_keyexpr(name) + let mut len = libc::strlen(name); + let res = z_view_keyexpr_from_slice_autocanonize(this, name, &mut len); + if res == errors::Z_OK { + *name.add(len) = 0; + } + res } } -/// Constructs a :c:type:`z_keyexpr_t` departing from a string without checking any of `z_keyexpr_t`'s assertions: +/// Constructs a :c:type:`z_eyexpr_t` by aliasing a string without checking any of `z_loaned_keyexpr_t`'s assertions: /// - `name` MUST be valid UTF8. /// - `name` MUST follow the Key Expression specification, ie: /// - MUST NOT contain ``//``, MUST NOT start nor end with ``/``, MUST NOT contain any of the characters ``?#$``. @@ -372,17 +342,18 @@ pub unsafe extern "C" fn z_keyexpr_autocanonize(name: *mut c_char) -> z_keyexpr_ /// It is a loaned key expression that aliases `name`. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn zc_keyexpr_from_slice_unchecked( +pub unsafe extern "C" fn z_view_keyexpr_from_slice_unchecked( + this: *mut MaybeUninit, start: *const c_char, len: usize, -) -> z_keyexpr_t { +) { let name = std::slice::from_raw_parts(start as _, len); let name = std::str::from_utf8_unchecked(name); let name: KeyExpr = keyexpr::from_str_unchecked(name).into(); - name.into() + Inplace::init(this.transmute_uninit_ptr(), Some(name)) } -/// Constructs a :c:type:`z_keyexpr_t` departing from a string without checking any of `z_keyexpr_t`'s assertions: +/// Constructs a :c:type:`z_loaned_keyexpr_t` by aliasing a string without checking any of `z_loaned_keyexpr_t`'s assertions: /// /// - `name` MUST be valid UTF8. /// - `name` MUST follow the Key Expression specification, ie: @@ -394,19 +365,23 @@ pub unsafe extern "C" fn zc_keyexpr_from_slice_unchecked( /// It is a loaned key expression that aliases `name`. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_keyexpr_unchecked(name: *const c_char) -> z_keyexpr_t { - zc_keyexpr_from_slice_unchecked(name, libc::strlen(name)) +pub unsafe extern "C" fn z_keyexpr_unchecked( + this: *mut MaybeUninit, + name: *const c_char, +) { + z_view_keyexpr_from_slice_unchecked(this, name, libc::strlen(name)) } -/// Constructs a null-terminated string departing from a :c:type:`z_keyexpr_t`. +/// Constructs a null-terminated string departing from a :c:type:`z_loaned_keyexpr_t`. /// The user is responsible of droping the returned string using `z_drop` #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub unsafe extern "C" fn z_keyexpr_to_string(keyexpr: z_keyexpr_t) -> z_owned_str_t { - match keyexpr.as_ref() { - Some(ke) => ke.as_bytes().into(), - None => z_str_null(), - } +pub unsafe extern "C" fn z_loaned_keyexpr_to_string( + ke: &z_loaned_keyexpr_t, + s: *mut MaybeUninit, +) { + let ke = ke.transmute_ref(); + unsafe { z_str_from_substring(s, ke.as_bytes().as_ptr() as *const _, ke.as_bytes().len()) }; } /// Returns the key expression's internal string by aliasing it. @@ -414,138 +389,99 @@ pub unsafe extern "C" fn z_keyexpr_to_string(keyexpr: z_keyexpr_t) -> z_owned_st /// Currently exclusive to zenoh-c #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_keyexpr_as_bytes(keyexpr: z_keyexpr_t) -> z_bytes_t { - match keyexpr.as_ref() { - Some(ke) => z_bytes_t { - start: ke.as_ptr(), - len: ke.len(), - }, - None => z_bytes_t { - start: std::ptr::null(), - len: 0, - }, - } -} - -impl<'a> From<&'a z_owned_keyexpr_t> for z_keyexpr_t { - fn from(oke: &'a z_owned_keyexpr_t) -> Self { - unsafe { std::mem::transmute_copy(oke) } - } -} - -impl<'a> From<&'a KeyExpr<'a>> for z_keyexpr_t { - fn from(key: &'a KeyExpr<'a>) -> Self { - key.borrowing_clone().into() - } +pub unsafe extern "C" fn z_keyexpr_as_bytes( + ke: &z_loaned_keyexpr_t, + b: *mut MaybeUninit, +) { + let ke = ke.transmute_ref(); + unsafe { z_view_slice_wrap(b, ke.as_bytes().as_ptr() as *const _, ke.as_bytes().len()) }; } /**************************************/ /* DECLARATION */ /**************************************/ -/// Declare a key expression. The id is returned as a :c:type:`z_keyexpr_t` with a nullptr suffix. +/// Declare a key expression. The id is returned as a :c:type:`z_loaned_keyexpr_t` with a nullptr suffix. /// /// This numerical id will be used on the network to save bandwidth and /// ease the retrieval of the concerned resource in the routing tables. #[allow(clippy::missing_safety_doc)] #[no_mangle] pub extern "C" fn z_declare_keyexpr( - session: z_session_t, - keyexpr: z_keyexpr_t, -) -> z_owned_keyexpr_t { - let key_expr = match keyexpr.as_ref() { - Some(ke) => ke, - None => { - log::warn!("{}", UninitializedKeyExprError); - return z_owned_keyexpr_t::null(); + this: *mut MaybeUninit, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, +) -> z_error_t { + let this = this.transmute_uninit_ptr(); + let key_expr = key_expr.transmute_ref(); + let session = session.transmute_ref(); + match session.declare_keyexpr(key_expr).res_sync() { + Ok(id) => { + Inplace::init(this, Some(id.into_owned())); + errors::Z_OK } - }; - match session.upgrade() { - Some(s) => match s.declare_keyexpr(key_expr).res_sync() { - Ok(id) => id.into_owned().into(), - Err(e) => { - log::debug!("{}", e); - z_owned_keyexpr_t::null() - } - }, - None => { - log::debug!("{}", LOG_INVALID_SESSION); - z_owned_keyexpr_t::null() + Err(e) => { + log::debug!("{}", e); + Inplace::empty(this); + errors::Z_EGENERIC } } } /// Undeclare the key expression generated by a call to :c:func:`z_declare_keyexpr`. +/// The keyxpr is consumed. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_undeclare_keyexpr(session: z_session_t, kexpr: &mut z_owned_keyexpr_t) -> i8 { - let Some(kexpr) = kexpr.deref_mut().take() else { +pub extern "C" fn z_undeclare_keyexpr( + session: &z_loaned_session_t, + kexpr: &mut z_owned_keyexpr_t, +) -> errors::z_error_t { + let Some(kexpr) = kexpr.transmute_mut().take() else { log::debug!("Attempted to undeclare dropped keyexpr"); - return i8::MIN; + return errors::Z_EINVAL; }; - - match session.upgrade() { - Some(s) => match s.undeclare(kexpr).res() { - Ok(()) => 0, - Err(e) => { - log::debug!("{}", e); - e.errno().get() - } - }, - None => { - log::debug!("{}", LOG_INVALID_SESSION); - i8::MIN + let session = session.transmute_ref(); + match session.undeclare(kexpr).res() { + Ok(()) => errors::Z_OK, + Err(e) => { + log::debug!("{}", e); + errors::Z_EGENERIC } } } #[allow(clippy::missing_safety_doc)] #[no_mangle] -/// Returns ``0`` if both ``left`` and ``right`` are equal. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. -pub extern "C" fn z_keyexpr_equals(left: z_keyexpr_t, right: z_keyexpr_t) -> i8 { - match (&*left, &*right) { - (Some(l), Some(r)) => { - if *l == *r { - 0 - } else { - -1 - } - } - _ => i8::MIN, - } +/// Returns ``0`` if both ``left`` and ``right`` are equal. +pub extern "C" fn z_keyexpr_equals(left: &z_loaned_keyexpr_t, right: &z_loaned_keyexpr_t) -> bool { + let l = left.transmute_ref(); + let r = right.transmute_ref(); + *l == *r } #[allow(clippy::missing_safety_doc)] #[no_mangle] /// Returns ``0`` if the keyexprs intersect, i.e. there exists at least one key which is contained in both of the -/// sets defined by ``left`` and ``right``. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. -pub extern "C" fn z_keyexpr_intersects(left: z_keyexpr_t, right: z_keyexpr_t) -> i8 { - match (&*left, &*right) { - (Some(l), Some(r)) => { - if l.intersects(r) { - 0 - } else { - -1 - } - } - _ => i8::MIN, - } +/// sets defined by ``left`` and ``right``. +pub extern "C" fn z_keyexpr_intersects( + left: &z_loaned_keyexpr_t, + right: &z_loaned_keyexpr_t, +) -> bool { + let l = left.transmute_ref(); + let r = right.transmute_ref(); + l.intersects(r) } #[allow(clippy::missing_safety_doc)] #[no_mangle] /// Returns ``0`` if ``left`` includes ``right``, i.e. the set defined by ``left`` contains every key belonging to the set -/// defined by ``right``. Otherwise, it returns a ``-1``, or other ``negative value`` for errors. -pub extern "C" fn z_keyexpr_includes(left: z_keyexpr_t, right: z_keyexpr_t) -> i8 { - match (&*left, &*right) { - (Some(l), Some(r)) => { - if l.includes(r) { - 0 - } else { - -1 - } - } - _ => i8::MIN, - } +/// defined by ``right``. +pub extern "C" fn z_keyexpr_includes( + left: &z_loaned_keyexpr_t, + right: &z_loaned_keyexpr_t, +) -> bool { + let l = left.transmute_ref(); + let r = right.transmute_ref(); + l.includes(r) } #[allow(clippy::missing_safety_doc)] @@ -558,14 +494,13 @@ pub extern "C" fn z_keyexpr_includes(left: z_keyexpr_t, right: z_keyexpr_t) -> i /// To avoid odd behaviors, concatenating a key expression starting with `*` to one ending with `*` is forbidden by this operation, /// as this would extremely likely cause bugs. pub unsafe extern "C" fn z_keyexpr_concat( - left: z_keyexpr_t, + this: *mut MaybeUninit, + left: &z_loaned_keyexpr_t, right_start: *const c_char, right_len: usize, -) -> z_owned_keyexpr_t { - let left = match left.as_ref() { - Some(l) => l, - None => return z_owned_keyexpr_t::null(), - }; +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); + let left = left.transmute_ref(); let right = std::slice::from_raw_parts(right_start as _, right_len); let right = match std::str::from_utf8(right) { Ok(r) => r, @@ -576,14 +511,19 @@ pub unsafe extern "C" fn z_keyexpr_concat( left, e ); - return z_owned_keyexpr_t::null(); + Inplace::empty(this); + return errors::Z_EINVAL; } }; match left.concat(right) { - Ok(result) => result.into(), + Ok(result) => { + Inplace::init(this, Some(result)); + errors::Z_OK + } Err(e) => { log::error!("{}", e); - z_owned_keyexpr_t::null() + Inplace::empty(this); + errors::Z_EGENERIC } } } @@ -592,20 +532,23 @@ pub unsafe extern "C" fn z_keyexpr_concat( #[no_mangle] /// Performs path-joining (automatically inserting) and returns the result as a `z_owned_keyexpr_t`. /// In case of error, the return value will be set to its invalidated state. -pub extern "C" fn z_keyexpr_join(left: z_keyexpr_t, right: z_keyexpr_t) -> z_owned_keyexpr_t { - let left = match left.as_ref() { - Some(l) => l, - None => return z_owned_keyexpr_t::null(), - }; - let right = match right.as_ref() { - Some(r) => r, - None => return z_owned_keyexpr_t::null(), - }; +pub extern "C" fn z_keyexpr_join( + this: *mut MaybeUninit, + left: &z_loaned_keyexpr_t, + right: &z_loaned_keyexpr_t, +) -> errors::z_error_t { + let left = left.transmute_ref(); + let right = right.transmute_ref(); + let this = this.transmute_uninit_ptr(); match left.join(right.as_str()) { - Ok(result) => result.into(), + Ok(result) => { + Inplace::init(this, Some(result)); + errors::Z_OK + } Err(e) => { log::error!("{}", e); - z_owned_keyexpr_t::null() + Inplace::empty(this); + errors::Z_EGENERIC } } } @@ -641,11 +584,10 @@ impl From for z_keyexpr_intersection_level_t { /// /// Note that this is slower than `z_keyexpr_intersects` and `keyexpr_includes`, so you should favor these methods for most applications. pub extern "C" fn z_keyexpr_relation_to( - left: z_keyexpr_t, - right: z_keyexpr_t, + left: &z_loaned_keyexpr_t, + right: &z_loaned_keyexpr_t, ) -> z_keyexpr_intersection_level_t { - match (&*left, &*right) { - (Some(l), Some(r)) => l.relation_to(r).into(), - _ => z_keyexpr_intersection_level_t::DISJOINT, - } + let l = left.transmute_ref(); + let r = right.transmute_ref(); + l.relation_to(r).into() } diff --git a/src/lib.rs b/src/lib.rs index 5019a0713..0d87cbc43 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,15 +14,24 @@ #![allow(non_camel_case_types)] -mod collections; +use libc::c_void; use std::cmp::min; use std::slice; +#[macro_use] +mod transmute; +pub mod opaque_types; +pub use crate::opaque_types::*; + +mod collections; +pub mod errors; pub use crate::collections::*; mod config; pub use crate::config::*; mod commons; pub use crate::commons::*; +mod payload; +pub use crate::payload::*; mod keyexpr; pub use crate::keyexpr::*; mod info; @@ -39,109 +48,24 @@ mod session; pub use crate::session::*; mod subscriber; pub use crate::subscriber::*; -mod pull_subscriber; -pub use crate::pull_subscriber::*; +// // mod pull_subscriber; +// // pub use crate::pull_subscriber::*; mod publisher; pub use crate::publisher::*; mod closures; pub use closures::*; mod liveliness; -use libc::c_void; pub use liveliness::*; mod publication_cache; pub use publication_cache::*; mod querying_subscriber; -pub use querying_subscriber::*; -pub mod attachment; pub use platform::*; +pub use querying_subscriber::*; pub mod platform; -#[cfg(feature = "shared-memory")] -mod shm; - -trait GuardedTransmute { - fn transmute(self) -> D; -} - -/// For internal use only. -/// -/// This macro is used to establish the equivalence between a Rust type (first parameter) and a C layout (second parameter). -/// -/// It automatically implements `From`, `Deref` and `DerefMut` to make writing code around these equivalent types. -/// -/// Because carrying around the proper semantics of lifetimes is hard, this macro fails to produce working code when lifetimes are -/// present in either parameter. You may then call it with the `noderefs` prefix to avoid the offending implementations being defined. -#[macro_export] -macro_rules! impl_guarded_transmute { - ($src_type:ty, $dst_type:ty) => { - impl_guarded_transmute!(noderefs $src_type, $dst_type); - impl From<$src_type> for $dst_type { - fn from(value: $src_type) -> $dst_type { - unsafe { core::mem::transmute(value) } - } - } - impl core::ops::Deref for $dst_type { - type Target = $src_type; - fn deref(&self) -> &$src_type { - unsafe { core::mem::transmute(self) } - } - } - impl core::ops::DerefMut for $dst_type { - fn deref_mut(&mut self) -> &mut $src_type { - unsafe { core::mem::transmute(self) } - } - } - - }; - (noderefs $src_type:ty, $dst_type:ty) => { - const _: () = { - let src = std::mem::align_of::<$src_type>(); - let dst = std::mem::align_of::<$dst_type>(); - if src != dst { - let mut msg: [u8; 20] = *b"src: , dst: "; - let mut i = 0; - while i < 4 { - msg[i as usize + 5] = b'0' + ((src / 10u32.pow(3 - i) as usize) % 10) as u8; - msg[i as usize + 16] = b'0' + ((dst / 10u32.pow(3 - i) as usize) % 10) as u8; - i += 1; - } - panic!("{}", unsafe { - std::str::from_utf8_unchecked(msg.as_slice()) - }); - } - }; - impl $crate::GuardedTransmute<$dst_type> for $src_type { - fn transmute(self) -> $dst_type { - unsafe { std::mem::transmute::<$src_type, $dst_type>(self) } - } - } - }; - ($src_type:ty, $dst_type:ty, $($gen: tt)*) => { - impl<$($gen)*> $crate::GuardedTransmute<$dst_type> for $src_type { - fn transmute(self) -> $dst_type { - unsafe { std::mem::transmute::<$src_type, $dst_type>(self) } - } - } - impl<$($gen)*> From<$src_type> for $dst_type { - fn from(value: $src_type) -> $dst_type { - unsafe { core::mem::transmute(value) } - } - } - impl<$($gen)*> core::ops::Deref for $dst_type { - type Target = $src_type; - fn deref(&self) -> &$src_type { - unsafe { core::mem::transmute(self) } - } - } - impl<$($gen)*> core::ops::DerefMut for $dst_type { - fn deref_mut(&mut self) -> &mut $src_type { - unsafe { core::mem::transmute(self) } - } - } - - }; -} - -pub(crate) const LOG_INVALID_SESSION: &str = "Invalid session"; +#[cfg(all(feature = "unstable", feature = "shared-memory"))] +pub mod shm; +#[cfg(all(feature = "unstable", feature = "shared-memory"))] +pub use crate::shm::*; /// Initialises the zenoh runtime logger. /// diff --git a/src/liveliness.rs b/src/liveliness.rs index 0a7c689dd..ae48097e7 100644 --- a/src/liveliness.rs +++ b/src/liveliness.rs @@ -12,77 +12,54 @@ // ZettaScale Zenoh Team, // +use std::mem::MaybeUninit; +use zenoh::prelude::SyncResolve; use zenoh::{ liveliness::{Liveliness, LivelinessToken}, - prelude::{SessionDeclarations, SplitBuffer}, + prelude::SessionDeclarations, }; -use zenoh_util::core::{zresult::ErrNo, SyncResolve}; +use crate::transmute::TransmuteIntoHandle; use crate::{ - z_closure_reply_call, z_closure_sample_call, z_keyexpr_t, z_owned_closure_reply_t, - z_owned_closure_sample_t, z_owned_subscriber_t, z_sample_t, z_session_t, + errors, + transmute::{Inplace, TransmuteFromHandle, TransmuteRef, TransmuteUninitPtr}, + z_closure_reply_call, z_closure_sample_call, z_loaned_keyexpr_t, z_loaned_session_t, + z_owned_closure_reply_t, z_owned_closure_sample_t, z_owned_subscriber_t, }; -/// A liveliness token that can be used to provide the network with information about connectivity to its -/// declarer: when constructed, a PUT sample will be received by liveliness subscribers on intersecting key -/// expressions. -/// -/// A DELETE on the token's key expression will be received by subscribers if the token is destroyed, or if connectivity between the subscriber and the token's creator is lost. -#[repr(C)] -pub struct zc_owned_liveliness_token_t { - _inner: [usize; 4], -} +use crate::opaque_types::zc_loaned_liveliness_token_t; +use crate::opaque_types::zc_owned_liveliness_token_t; +decl_transmute_owned!( + Option>, + zc_owned_liveliness_token_t +); +decl_transmute_handle!(LivelinessToken<'static>, zc_loaned_liveliness_token_t); /// The gravestone value for liveliness tokens. #[no_mangle] -pub extern "C" fn zc_liveliness_token_null() -> zc_owned_liveliness_token_t { - zc_owned_liveliness_token_t { _inner: [0; 4] } +pub extern "C" fn zc_liveliness_token_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); } /// Returns `true` unless the token is at its gravestone value. #[no_mangle] -pub extern "C" fn zc_liveliness_token_check(token: &zc_owned_liveliness_token_t) -> bool { - token._inner.iter().any(|v| *v != 0) +pub extern "C" fn zc_liveliness_token_check(this: &zc_owned_liveliness_token_t) -> bool { + this.transmute_ref().is_some() } /// The options for `zc_liveliness_declare_token` #[repr(C)] -pub struct zc_owned_liveliness_declaration_options_t { - _inner: u8, -} -/// The gravestone value for `zc_owned_liveliness_declaration_options_t` -#[no_mangle] -pub extern "C" fn zc_liveliness_declaration_options_null( -) -> zc_owned_liveliness_declaration_options_t { - zc_owned_liveliness_declaration_options_t { _inner: 0 } -} -/// Returns `true` if the options are valid. -#[no_mangle] -pub extern "C" fn zc_liveliness_declaration_options_check( - _opts: &zc_owned_liveliness_declaration_options_t, -) -> bool { - true +pub struct zc_liveliness_declaration_options_t { + _dummy: u8, } -/// Destroys the options. + #[no_mangle] -pub extern "C" fn zc_liveliness_declaration_options_drop( - opts: &mut zc_owned_liveliness_declaration_options_t, +pub extern "C" fn zc_liveliness_declaration_options_default( + this: &mut zc_liveliness_declaration_options_t, ) { - *opts = zc_liveliness_declaration_options_null() -} -impl From> for zc_owned_liveliness_token_t { - fn from(value: LivelinessToken<'static>) -> Self { - unsafe { core::mem::transmute(value) } - } -} -impl From for Option> { - fn from(value: zc_owned_liveliness_token_t) -> Self { - if value._inner.iter().all(|v| *v == 0) { - None - } else { - Some(unsafe { core::mem::transmute(value) }) - } - } + *this = zc_liveliness_declaration_options_t { _dummy: 0 }; } + /// Constructs and declares a liveliness token on the network. /// /// Liveliness token subscribers on an intersecting key expression will receive a PUT sample when connectivity @@ -91,67 +68,60 @@ impl From for Option> { /// Passing `NULL` as options is valid and equivalent to a pointer to the default options. #[no_mangle] pub extern "C" fn zc_liveliness_declare_token( - session: z_session_t, - key: z_keyexpr_t, - _options: Option<&zc_owned_liveliness_declaration_options_t>, -) -> zc_owned_liveliness_token_t { - let Some(session) = session.upgrade() else { - log::error!("Failed to declare liveliness token: provided session was invalid"); - return zc_liveliness_token_null(); - }; - match session.liveliness().declare_token(key).res() { - Ok(token) => unsafe { core::mem::transmute(token) }, + this: *mut MaybeUninit, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, + _options: Option<&mut zc_liveliness_declaration_options_t>, +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); + let session = session.transmute_ref(); + let key_expr = key_expr.transmute_ref(); + match session.liveliness().declare_token(key_expr).res() { + Ok(token) => { + Inplace::init(this, Some(token)); + errors::Z_OK + } Err(e) => { - log::error!("Failed to declare liveliness token: {e}"); - zc_liveliness_token_null() + log::error!("Failed to undeclare token: {e}"); + Inplace::empty(this); + errors::Z_EGENERIC } } } /// Destroys a liveliness token, notifying subscribers of its destruction. #[no_mangle] -pub extern "C" fn zc_liveliness_undeclare_token(token: &mut zc_owned_liveliness_token_t) { - let Some(token): Option = - core::mem::replace(token, zc_liveliness_token_null()).into() - else { - return; - }; - if let Err(e) = token.undeclare().res() { - log::error!("Failed to undeclare token: {e}"); +pub extern "C" fn zc_liveliness_undeclare_token( + this: &mut zc_owned_liveliness_token_t, +) -> errors::z_error_t { + let this = this.transmute_mut(); + if let Some(token) = this.extract().take() { + if let Err(e) = token.undeclare().res() { + log::error!("Failed to undeclare token: {e}"); + return errors::Z_EGENERIC; + } } + errors::Z_OK } /// The options for :c:func:`zc_liveliness_declare_subscriber` #[repr(C)] -pub struct zc_owned_liveliness_declare_subscriber_options_t { - _inner: u8, -} -/// The gravestone value for `zc_owned_liveliness_declare_subscriber_options_t` -#[no_mangle] -pub extern "C" fn zc_liveliness_subscriber_options_null( -) -> zc_owned_liveliness_declare_subscriber_options_t { - zc_owned_liveliness_declare_subscriber_options_t { _inner: 0 } -} -/// Returns `true` if the options are valid. -#[no_mangle] -pub extern "C" fn zc_liveliness_subscriber_options_check( - _opts: &zc_owned_liveliness_declare_subscriber_options_t, -) -> bool { - true +pub struct zc_liveliness_declare_subscriber_options_t { + _dummy: u8, } -/// Destroys the options. + #[no_mangle] -pub extern "C" fn zc_liveliness_subscriber_options_drop( - opts: &mut zc_owned_liveliness_declare_subscriber_options_t, +pub extern "C" fn zc_liveliness_subscriber_options_default( + this: &mut zc_liveliness_declare_subscriber_options_t, ) { - *opts = zc_liveliness_subscriber_options_null() + *this = zc_liveliness_declare_subscriber_options_t { _dummy: 0 }; } /// Declares a subscriber on liveliness tokens that intersect `key`. /// /// Parameters: -/// z_session_t session: The zenoh session. -/// z_keyexpr_t keyexpr: The key expression to subscribe. +/// z_loaned_session_t session: The zenoh session. +/// z_loaned_keyexpr_t key_expr: The key expression to subscribe. /// z_owned_closure_sample_t callback: The callback function that will be called each time a /// liveliness token status changed. /// zc_owned_liveliness_declare_subscriber_options_t _options: The options to be passed to describe the options to be passed to the liveliness subscriber declaration. @@ -163,34 +133,33 @@ pub extern "C" fn zc_liveliness_subscriber_options_drop( /// you may use `z_subscriber_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. #[no_mangle] pub extern "C" fn zc_liveliness_declare_subscriber( - session: z_session_t, - key: z_keyexpr_t, + this: *mut MaybeUninit, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, callback: &mut z_owned_closure_sample_t, - _options: Option<&zc_owned_liveliness_declare_subscriber_options_t>, -) -> z_owned_subscriber_t { - let Some(session) = session.upgrade() else { - log::error!("Failed to declare liveliness token: provided session was invalid"); - return z_owned_subscriber_t::null(); - }; + _options: Option<&mut zc_liveliness_declare_subscriber_options_t>, +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); + let session = session.transmute_ref(); let callback = core::mem::replace(callback, z_owned_closure_sample_t::empty()); + let key_expr = key_expr.transmute_ref(); match session .liveliness() - .declare_subscriber(key) + .declare_subscriber(key_expr) .callback(move |sample| { - let payload = sample.payload.contiguous(); - let owner = match payload { - std::borrow::Cow::Owned(v) => zenoh::buffers::ZBuf::from(v), - _ => sample.payload.clone(), - }; - let sample = z_sample_t::new(&sample, &owner); - z_closure_sample_call(&callback, &sample) + let sample = sample.transmute_handle(); + z_closure_sample_call(&callback, sample) }) .res() { - Ok(token) => z_owned_subscriber_t::new(token), + Ok(subscriber) => { + Inplace::init(this, Some(subscriber)); + errors::Z_OK + } Err(e) => { log::error!("Failed to subscribe to liveliness: {e}"); - z_owned_subscriber_t::null() + Inplace::empty(this); + errors::Z_EGENERIC } } } @@ -200,25 +169,11 @@ pub extern "C" fn zc_liveliness_declare_subscriber( pub struct zc_liveliness_get_options_t { timeout_ms: u32, } + /// The gravestone value for `zc_liveliness_get_options_t` #[no_mangle] -pub extern "C" fn zc_liveliness_get_options_null() -> zc_liveliness_get_options_t { - zc_liveliness_get_options_t { timeout_ms: 0 } -} -/// The gravestone value for `zc_liveliness_get_options_t` -#[no_mangle] -pub extern "C" fn zc_liveliness_get_options_default() -> zc_liveliness_get_options_t { - zc_liveliness_get_options_t { timeout_ms: 10000 } -} -/// Returns `true` if the options are valid. -#[no_mangle] -pub extern "C" fn zc_liveliness_get_options_check(_opts: &zc_liveliness_get_options_t) -> bool { - true -} -/// Destroys the options. -#[no_mangle] -pub extern "C" fn zc_liveliness_get_options_drop(opts: &mut zc_liveliness_get_options_t) { - *opts = zc_liveliness_get_options_null() +pub extern "C" fn zc_liveliness_get_options_default(this: &mut zc_liveliness_get_options_t) { + *this = zc_liveliness_get_options_t { timeout_ms: 10000 }; } /// Queries liveliness tokens currently on the network with a key expression intersecting with `key`. @@ -228,28 +183,26 @@ pub extern "C" fn zc_liveliness_get_options_drop(opts: &mut zc_liveliness_get_op /// Passing `NULL` as options is valid and equivalent to passing a pointer to the default options. #[no_mangle] pub extern "C" fn zc_liveliness_get( - session: z_session_t, - key: z_keyexpr_t, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, callback: &mut z_owned_closure_reply_t, - options: Option<&zc_liveliness_get_options_t>, -) -> i8 { - let Some(session) = session.upgrade() else { - log::error!("Failed to declare liveliness token: provided session was invalid"); - return i8::MIN; - }; + options: Option<&mut zc_liveliness_get_options_t>, +) -> errors::z_error_t { + let session = session.transmute_ref(); + let key_expr = key_expr.transmute_ref(); let callback = core::mem::replace(callback, z_owned_closure_reply_t::empty()); let liveliness: Liveliness<'static> = session.liveliness(); let mut builder = liveliness - .get(key) - .callback(move |response| z_closure_reply_call(&callback, &mut response.into())); + .get(key_expr) + .callback(move |response| z_closure_reply_call(&callback, response.transmute_handle())); if let Some(options) = options { - builder = builder.timeout(core::time::Duration::from_millis(options.timeout_ms as u64)) + builder = builder.timeout(core::time::Duration::from_millis(options.timeout_ms as u64)); } match builder.res() { - Ok(()) => 0, + Ok(()) => errors::Z_OK, Err(e) => { log::error!("Failed to subscribe to liveliness: {e}"); - e.errno().get() + errors::Z_EGENERIC } } } diff --git a/src/opaque_types/.gitkeep b/src/opaque_types/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/src/opaque_types/mod.rs b/src/opaque_types/mod.rs new file mode 100644 index 000000000..7752df8bd --- /dev/null +++ b/src/opaque_types/mod.rs @@ -0,0 +1,403 @@ +#[rustfmt::skip] +#[allow(clippy::all)] +/// A split buffer that owns all of its data. +/// +/// To minimize copies and reallocations, Zenoh may provide you data in split buffers. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_bytes_t { + _0: [u8; 40], +} +/// A loaned payload. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_bytes_t { + _0: [u8; 40], +} +/// A contiguous view of bytes owned by some other entity. +/// +/// `start` being `null` is considered a gravestone value, +/// and empty slices are represented using a possibly dangling pointer for `start`. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_slice_t { + _0: [u8; 16], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_view_slice_t { + _0: [u8; 16], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_slice_t { + _0: [u8; 16], +} +/// The wrapper type for null-terminated string values allocated by zenoh. The instances of `z_owned_str_t` +/// should be released with `z_drop` macro or with `z_str_drop` function and checked to validity with +/// `z_check` and `z_str_check` correspondently +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_str_t { + _0: [u8; 16], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_view_str_t { + _0: [u8; 16], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_str_t { + _0: [u8; 16], +} +/// A map of maybe-owned vector of bytes to maybe-owned vector of bytes. +/// +/// In Zenoh C, this map is backed by Rust's standard HashMap, with a DoS-resistant hasher +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_slice_map_t { + _0: [u8; 48], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_slice_map_t { + _0: [u8; 48], +} +/// An owned sample. +/// +/// This is a read only type that can only be constructed by cloning a `z_loaned_sample_t`. +/// Like all owned types, its memory must be freed by passing a mutable reference to it to `z_sample_drop`. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_sample_t { + _0: [u8; 240], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_sample_t { + _0: [u8; 240], +} +/// A reader for payload data. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_bytes_reader_t { + _0: [u8; 24], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_bytes_reader_t { + _0: [u8; 24], +} +/// The encoding of a payload, in a MIME-like format. +/// +/// For wire and matching efficiency, common MIME types are represented using an integer as `prefix`, and a `suffix` may be used to either provide more detail, or in combination with the `Empty` prefix to write arbitrary MIME types. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_encoding_t { + _0: [u8; 48], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_encoding_t { + _0: [u8; 48], +} +/// An owned reply to a :c:func:`z_get`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_reply_t { + _0: [u8; 256], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_reply_t { + _0: [u8; 256], +} +/// A zenoh value. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_value_t { + _0: [u8; 88], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_value_t { + _0: [u8; 88], +} +/// +/// Queries are atomically reference-counted, letting you extract them from the callback that handed them to you by cloning. +/// `z_loaned_query_t`'s are valid as long as at least one corresponding `z_owned_query_t` exists, including the one owned by Zenoh until the callback returns. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_query_t { + _0: [u8; 16], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_query_t { + _0: [u8; 16], +} +/// An owned zenoh queryable. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_queryable_t { + _0: [u8; 32], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_queryable_t { + _0: [u8; 32], +} +/// An owned zenoh querying subscriber. Destroying the subscriber cancels the subscription. +/// +/// Like most `ze_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `ze_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct ze_owned_querying_subscriber_t { + _0: [u8; 64], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct ze_loaned_querying_subscriber_t { + _0: [u8; 64], +} +/// A zenoh-allocated key expression. +/// +/// Key expressions can identify a single key or a set of keys. +/// +/// Examples : +/// - ``"key/expression"``. +/// - ``"key/ex*"``. +/// +/// Key expressions can be mapped to numerical ids through :c:func:`z_declare_expr` +/// for wire and computation efficiency. +/// +/// A `key expression `_ can be either: +/// - A plain string expression. +/// - A pure numerical id. +/// - The combination of a numerical prefix and a string suffix. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_keyexpr_t { + _0: [u8; 32], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_view_keyexpr_t { + _0: [u8; 32], +} +/// A loaned key expression. +/// +/// Key expressions can identify a single key or a set of keys. +/// +/// Examples : +/// - ``"key/expression"``. +/// - ``"key/ex*"``. +/// +/// Using :c:func:`z_declare_keyexpr` allows zenoh to optimize a key expression, +/// both for local processing and network-wise. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_keyexpr_t { + _0: [u8; 32], +} +/// An owned zenoh session. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_session_t { + _0: [u8; 8], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_session_t { + _0: [u8; 40], +} +/// An owned zenoh configuration. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_config_t { + _0: [u8; 1544], +} +/// A loaned zenoh configuration. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_config_t { + _0: [u8; 1544], +} +/// Represents a Zenoh ID. +/// +/// In general, valid Zenoh IDs are LSB-first 128bit unsigned and non-zero integers. +#[derive(Copy, Clone)] +#[repr(C, align(1))] +pub struct z_id_t { + id: [u8; 16], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_timestamp_t { + _0: [u8; 24], +} +/// An owned zenoh publisher. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_publisher_t { + _0: [u8; 56], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_publisher_t { + _0: [u8; 56], +} +/// An owned zenoh matching listener. Destroying the matching listener cancels the subscription. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct zcu_owned_matching_listener_t { + _0: [u8; 40], +} +/// An owned zenoh subscriber. Destroying the subscriber cancels the subscription. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_subscriber_t { + _0: [u8; 32], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_subscriber_t { + _0: [u8; 32], +} +/// A liveliness token that can be used to provide the network with information about connectivity to its +/// declarer: when constructed, a PUT sample will be received by liveliness subscribers on intersecting key +/// expressions. +/// +/// A DELETE on the token's key expression will be received by subscribers if the token is destroyed, or if connectivity between the subscriber and the token's creator is lost. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct zc_owned_liveliness_token_t { + _0: [u8; 32], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct zc_loaned_liveliness_token_t { + _0: [u8; 32], +} +/// An owned zenoh publication_cache. +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct ze_owned_publication_cache_t { + _0: [u8; 96], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct ze_loaned_publication_cache_t { + _0: [u8; 96], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_mutex_t { + _0: [u8; 24], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_loaned_mutex_t { + _0: [u8; 24], +} +#[derive(Copy, Clone)] +#[repr(C, align(4))] +pub struct z_owned_condvar_t { + _0: [u8; 8], +} +#[derive(Copy, Clone)] +#[repr(C, align(4))] +pub struct z_loaned_condvar_t { + _0: [u8; 4], +} +#[derive(Copy, Clone)] +#[repr(C, align(8))] +pub struct z_owned_task_t { + _0: [u8; 24], +} diff --git a/src/payload.rs b/src/payload.rs new file mode 100644 index 000000000..1283f28a6 --- /dev/null +++ b/src/payload.rs @@ -0,0 +1,300 @@ +use crate::errors::{self, z_error_t}; +use crate::transmute::{ + unwrap_ref_unchecked, unwrap_ref_unchecked_mut, Inplace, TransmuteFromHandle, + TransmuteIntoHandle, TransmuteRef, TransmuteUninitPtr, +}; +use crate::{ + z_loaned_slice_map_t, z_loaned_slice_t, z_loaned_str_t, z_owned_slice_map_t, z_owned_slice_t, + z_owned_str_t, ZHashMap, +}; +use core::fmt; +use std::any::Any; +use std::io::{Read, Seek, SeekFrom}; +use std::mem::MaybeUninit; +use std::slice::from_raw_parts_mut; +use zenoh::buffers::{ZSlice, ZSliceBuffer}; +use zenoh::bytes::{ZBytes, ZBytesReader}; + +pub use crate::opaque_types::z_owned_bytes_t; +decl_transmute_owned!(Option, z_owned_bytes_t); + +/// The gravestone value for `z_owned_bytes_t`. +#[no_mangle] +extern "C" fn z_bytes_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); +} + +/// Decrements the payload's reference counter, destroying it if applicable. +/// +/// `this` will be reset to `z_buffer_null`, preventing UB on double-frees. +#[no_mangle] +extern "C" fn z_bytes_drop(this: &mut z_owned_bytes_t) { + let this = this.transmute_mut(); + Inplace::drop(this); +} + +/// Returns `true` if the payload is in a valid state. +#[no_mangle] +extern "C" fn z_bytes_check(payload: &z_owned_bytes_t) -> bool { + payload.transmute_ref().is_some() +} + +/// Loans the payload, allowing you to call functions that only need a loan of it. +#[no_mangle] +extern "C" fn z_bytes_loan(payload: &z_owned_bytes_t) -> &z_loaned_bytes_t { + let payload = payload.transmute_ref(); + let payload = unwrap_ref_unchecked(payload); + payload.transmute_handle() +} + +pub use crate::opaque_types::z_loaned_bytes_t; +decl_transmute_handle!(ZBytes, z_loaned_bytes_t); + +/// Increments the payload's reference count, returning an owned version of it. +#[no_mangle] +extern "C" fn z_bytes_clone(src: &z_loaned_bytes_t, dst: *mut MaybeUninit) { + let dst = dst.transmute_uninit_ptr(); + let src = src.transmute_ref(); + let src = Some(src.clone()); + Inplace::init(dst, src); +} + +/// Returns total number bytes in the payload. +#[no_mangle] +extern "C" fn z_bytes_len(payload: &z_loaned_bytes_t) -> usize { + payload.transmute_ref().len() +} + +/// Decodes payload into null-terminated string. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_decode_into_string( + payload: &z_loaned_bytes_t, + dst: *mut MaybeUninit, +) -> z_error_t { + let len = z_bytes_len(payload); + let payload = payload.transmute_ref(); + let mut out = vec![0u8; len + 1]; + if let Err(e) = payload.reader().read(out.as_mut_slice()) { + log::error!("Failed to read the payload: {}", e); + Inplace::empty(dst.transmute_uninit_ptr()); + errors::Z_EIO + } else if let Err(e) = std::str::from_utf8(out.as_slice()) { + log::error!("Payload is not a valid utf-8 string: {}", e); + Inplace::empty(dst.transmute_uninit_ptr()); + errors::Z_EPARSE + } else { + let b = out.into_boxed_slice(); + Inplace::init(dst.transmute_uninit_ptr(), Some(b)); + errors::Z_OK + } +} + +/// Decodes payload into bytes map. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_decode_into_bytes_map( + payload: z_loaned_bytes_t, + dst: *mut MaybeUninit, +) -> z_error_t { + let dst = dst.transmute_uninit_ptr(); + let payload = payload.transmute_ref(); + let iter = payload.iter::<(Vec, Vec)>(); + let mut hm = ZHashMap::new(); + for (k, v) in iter { + hm.insert(k.into(), v.into()); + } + Inplace::init(dst, Some(hm)); + errors::Z_OK +} + +/// Decodes payload into owned bytes +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_decode_into_bytes( + payload: &z_loaned_bytes_t, + dst: *mut MaybeUninit, +) -> z_error_t { + let payload = payload.transmute_ref(); + match payload.deserialize::>() { + Ok(v) => { + let b = v.into_boxed_slice(); + Inplace::init(dst.transmute_uninit_ptr(), Some(b)); + errors::Z_OK + } + Err(e) => { + log::error!("Failed to read the payload: {}", e); + Inplace::empty(dst.transmute_uninit_ptr()); + errors::Z_EIO + } + } +} + +unsafe impl Send for z_loaned_slice_t {} +unsafe impl Sync for z_loaned_slice_t {} + +impl fmt::Debug for z_loaned_slice_t { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let s = self.transmute_ref(); + f.debug_struct("z_loaned_slice_t").field("_0", s).finish() + } +} + +impl ZSliceBuffer for z_loaned_slice_t { + fn as_slice(&self) -> &[u8] { + self.transmute_ref() + } + fn as_any(&self) -> &dyn Any { + self + } + + fn as_any_mut(&mut self) -> &mut dyn Any { + self + } +} + +/// Encodes byte sequence by aliasing. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_encode_from_bytes( + this: *mut MaybeUninit, + bytes: &z_loaned_slice_t, +) { + let this = this.transmute_uninit_ptr(); + let payload = ZBytes::from(ZSlice::from(*bytes)); + Inplace::init(this, Some(payload)); +} + +/// Encodes bytes map by copying. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_encode_from_bytes_map( + this: *mut MaybeUninit, + bytes_map: &z_loaned_slice_map_t, +) { + let dst = this.transmute_uninit_ptr(); + let hm = bytes_map.transmute_ref(); + let payload = ZBytes::from_iter(hm.iter()); + Inplace::init(dst, Some(payload)); +} + +/// Encodes a null-terminated string by aliasing. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_encode_from_string( + this: *mut MaybeUninit, + s: &z_loaned_str_t, +) { + let s = s.transmute_ref(); + let ss = &s[0..s.len() - 1]; + let b = ss.transmute_handle(); + z_bytes_encode_from_bytes(this, b); +} + +pub use crate::opaque_types::z_owned_bytes_reader_t; +decl_transmute_owned!(Option>, z_owned_bytes_reader_t); + +pub use crate::opaque_types::z_loaned_bytes_reader_t; +decl_transmute_handle!(ZBytesReader<'static>, z_loaned_bytes_reader_t); + +/// Creates a reader for the specified `payload`. +/// +/// Returns 0 in case of success, -1 if `payload` is not valid. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_reader_new( + payload: z_loaned_bytes_t, + this: *mut MaybeUninit, +) { + let this = this.transmute_uninit_ptr(); + let payload = payload.transmute_ref(); + let reader = payload.reader(); + Inplace::init(this, Some(reader)); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_reader_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_reader_check(this: &z_owned_bytes_reader_t) -> bool { + this.transmute_ref().is_some() +} + +#[no_mangle] +extern "C" fn z_bytes_reader_drop(this: &mut z_owned_bytes_reader_t) { + let reader = this.transmute_mut(); + Inplace::drop(reader); +} + +#[no_mangle] +extern "C" fn z_bytes_reader_loan(reader: &z_owned_bytes_reader_t) -> &z_loaned_bytes_reader_t { + let reader = reader.transmute_ref(); + let reader = unwrap_ref_unchecked(reader); + reader.transmute_handle() +} + +#[no_mangle] +extern "C" fn z_bytes_reader_loan_mut( + reader: &mut z_owned_bytes_reader_t, +) -> &mut z_loaned_bytes_reader_t { + let reader = reader.transmute_mut(); + let reader = unwrap_ref_unchecked_mut(reader); + reader.transmute_handle_mut() +} + +/// Reads data into specified destination. +/// +/// Will read at most `len` bytes. +/// Returns number of bytes read. If return value is smaller than `len`, it means that end of the payload was reached. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_reader_read( + this: &mut z_loaned_bytes_reader_t, + dest: *mut u8, + len: usize, +) -> usize { + let reader = this.transmute_mut(); + let buf = unsafe { from_raw_parts_mut(dest, len) }; + reader.read(buf).unwrap_or(0) +} + +/// Sets the `reader` position indicator for the payload to the value pointed to by offset. +/// The new position is exactly offset bytes measured from the beginning of the payload if origin is SEEK_SET, +/// from the current reader position if origin is SEEK_CUR, and from the end of the payload if origin is SEEK_END. +/// Return ​0​ upon success, negative error code otherwise. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_bytes_reader_seek( + this: &mut z_loaned_bytes_reader_t, + offset: i64, + origin: libc::c_int, +) -> z_error_t { + let reader = this.transmute_mut(); + let pos = match origin { + libc::SEEK_SET => offset.try_into().map(SeekFrom::Start), + libc::SEEK_CUR => Ok(SeekFrom::Current(offset)), + libc::SEEK_END => Ok(SeekFrom::End(offset)), + _ => { + return errors::Z_EINVAL; + } + }; + match pos.map(|p| reader.seek(p)) { + Ok(_) => 0, + Err(_) => errors::Z_EINVAL, + } +} + +/// Returns the read position indicator. +/// Returns read position indicator on success or -1L if failure occurs. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_loaned_bytes_reader_tell(this: &mut z_loaned_bytes_reader_t) -> i64 { + let reader = this.transmute_mut(); + reader.stream_position().map(|p| p as i64).unwrap_or(-1) +} diff --git a/src/platform/synchronization.rs b/src/platform/synchronization.rs index a16664352..52032c8aa 100644 --- a/src/platform/synchronization.rs +++ b/src/platform/synchronization.rs @@ -1,240 +1,211 @@ use std::{ + mem::MaybeUninit, sync::{Condvar, Mutex, MutexGuard}, thread::{self, JoinHandle}, }; use libc::c_void; -use crate::{impl_guarded_transmute, GuardedTransmute}; +pub use crate::opaque_types::z_loaned_mutex_t; +pub use crate::opaque_types::z_owned_mutex_t; +use crate::{ + errors, + transmute::{ + unwrap_ref_unchecked, unwrap_ref_unchecked_mut, Inplace, TransmuteFromHandle, + TransmuteIntoHandle, TransmuteRef, TransmuteUninitPtr, + }, +}; -pub struct ZMutex<'a> { - mutex: Mutex<()>, - lock: Option>, -} +decl_transmute_owned!( + Option<(Mutex<()>, Option>)>, + z_owned_mutex_t +); +decl_transmute_handle!( + (Mutex<()>, Option>), + z_loaned_mutex_t +); -pub struct ZMutexPtr { - data: Option>>, +#[no_mangle] +pub extern "C" fn z_mutex_init(this: *mut MaybeUninit) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); + let m = (Mutex::<()>::new(()), None::>); + Inplace::init(this, Some(m)); + errors::Z_OK } -/// Mutex -/// -#[repr(C)] -#[derive(Clone, Copy)] -pub struct z_mutex_t(usize); - -impl_guarded_transmute!(noderefs z_mutex_t, ZMutexPtr); -impl_guarded_transmute!(noderefs ZMutexPtr, z_mutex_t); - -// using the same error codes as in GNU pthreads, but with negative sign -// due to convention to return negative values on error -const EBUSY: i8 = -16; -const EINVAL: i8 = -22; -const EAGAIN: i8 = -11; -const EPOISON: i8 = -22; // same as EINVAL +#[no_mangle] +pub extern "C" fn z_mutex_drop(this: &mut z_owned_mutex_t) { + let _ = this.transmute_mut().extract().take(); +} #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_mutex_init(m: *mut z_mutex_t) -> i8 { - if m.is_null() { - return EINVAL; - } - let t = ZMutexPtr { - data: Some(Box::new(ZMutex { - mutex: Mutex::new(()), - lock: None, - })), - }; - *m = t.transmute(); - 0 +pub extern "C" fn z_mutex_check(this: &z_owned_mutex_t) -> bool { + this.transmute_ref().is_some() } #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_mutex_free(m: *mut z_mutex_t) -> i8 { - if m.is_null() { - return EINVAL; - } - let mut t = (*m).transmute(); +pub extern "C" fn z_mutex_null(this: *mut MaybeUninit) { + Inplace::empty(this.transmute_uninit_ptr()); +} - t.data.take(); - *m = t.transmute(); - 0 +#[no_mangle] +pub extern "C" fn z_mutex_loan_mut(this: &mut z_owned_mutex_t) -> &mut z_loaned_mutex_t { + let this = this.transmute_mut(); + let this = unwrap_ref_unchecked_mut(this); + this.transmute_handle_mut() } #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_mutex_lock(m: *mut z_mutex_t) -> i8 { - if m.is_null() { - return EINVAL; - } - let mut t = (*m).transmute(); - if t.data.is_none() { - return EINVAL; - } - let mut_data = t.data.as_mut().unwrap(); - match mut_data.mutex.lock() { +pub extern "C" fn z_mutex_lock(this: &mut z_loaned_mutex_t) -> errors::z_error_t { + let this = this.transmute_mut(); + + match this.0.lock() { Ok(new_lock) => { - let old_lock = mut_data.lock.replace(std::mem::transmute(new_lock)); + let old_lock = this.1.replace(new_lock); std::mem::forget(old_lock); } Err(_) => { - return EPOISON; + return errors::Z_EPOISON_MUTEX; } } - - *m = t.transmute(); - 0 + errors::Z_OK } #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_mutex_unlock(m: *mut z_mutex_t) -> i8 { - if m.is_null() { - return EINVAL; - } - let mut t = (*m).transmute(); - if t.data.is_none() { - return EINVAL; - } - let mut_data = t.data.as_mut().unwrap(); - if mut_data.lock.is_none() { - return EINVAL; +pub extern "C" fn z_mutex_unlock(this: &mut z_loaned_mutex_t) -> errors::z_error_t { + let this = this.transmute_mut(); + if this.1.is_none() { + return errors::Z_EINVAL_MUTEX; } else { - mut_data.lock.take(); + this.1.take(); } - *m = t.transmute(); - 0 + errors::Z_OK } #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_mutex_try_lock(m: *mut z_mutex_t) -> i8 { - if m.is_null() { - return EINVAL; - } - let mut t = (*m).transmute(); - if t.data.is_none() { - return EINVAL; - } - let mut_data = t.data.as_mut().unwrap(); - let mut ret: i8 = 0; - match mut_data.mutex.try_lock() { +pub unsafe extern "C" fn z_loaned_mutex_try_lock(this: &mut z_loaned_mutex_t) -> errors::z_error_t { + let this = this.transmute_mut(); + match this.0.try_lock() { Ok(new_lock) => { - let old_lock = mut_data.lock.replace(std::mem::transmute(new_lock)); + let old_lock = this.1.replace(new_lock); std::mem::forget(old_lock); } Err(_) => { - ret = EBUSY; + return errors::Z_EBUSY_MUTEX; } } - *m = t.transmute(); - ret + errors::Z_OK } -struct ZCondvarPtr { - data: Option>, +pub use crate::opaque_types::z_loaned_condvar_t; +pub use crate::opaque_types::z_owned_condvar_t; + +decl_transmute_owned!(Option, z_owned_condvar_t); +decl_transmute_handle!(Condvar, z_loaned_condvar_t); + +#[no_mangle] +pub extern "C" fn z_condvar_init(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::init(this, Some(Condvar::new())); } -/// Condvar -/// -#[repr(C)] -#[derive(Clone, Copy)] -pub struct z_condvar_t(usize); +#[no_mangle] +pub extern "C" fn z_condvar_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); +} -impl_guarded_transmute!(noderefs z_condvar_t, ZCondvarPtr); -impl_guarded_transmute!(noderefs ZCondvarPtr, z_condvar_t); +#[no_mangle] +pub extern "C" fn z_condvar_drop(this: &mut z_owned_condvar_t) { + let _ = this.transmute_mut().extract().take(); +} #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_condvar_init(cv: *mut z_condvar_t) -> i8 { - if cv.is_null() { - return EINVAL; - } - let t: ZCondvarPtr = ZCondvarPtr { - data: Some(Box::new(Condvar::new())), - }; - *cv = t.transmute(); - 0 +pub extern "C" fn z_condvar_check(this: &z_owned_condvar_t) -> bool { + this.transmute_ref().is_some() } #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_condvar_free(cv: *mut z_condvar_t) -> i8 { - if cv.is_null() { - return EINVAL; - } - let mut t = (*cv).transmute(); - if t.data.is_none() { - return EINVAL; - } - t.data.take(); - *cv = t.transmute(); - 0 +pub extern "C" fn z_condvar_loan(this: &z_owned_condvar_t) -> &z_loaned_condvar_t { + let this = this.transmute_ref(); + let this = unwrap_ref_unchecked(this); + this.transmute_handle() } #[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_condvar_signal(cv: *mut z_condvar_t) -> i8 { - if cv.is_null() { - return EINVAL; - } - let t = (*cv).transmute(); - if t.data.is_none() { - return EINVAL; - } - t.data.as_ref().unwrap().notify_one(); - *cv = t.transmute(); - 0 +pub extern "C" fn z_condvar_loan_mut(this: &mut z_owned_condvar_t) -> &mut z_loaned_condvar_t { + let this = this.transmute_mut(); + let this = unwrap_ref_unchecked_mut(this); + this.transmute_handle_mut() +} + +#[no_mangle] +pub extern "C" fn z_condvar_signal(this: &z_loaned_condvar_t) -> errors::z_error_t { + let this = this.transmute_ref(); + this.notify_one(); + errors::Z_OK } #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_condvar_wait(cv: *mut z_condvar_t, m: *mut z_mutex_t) -> i8 { - if cv.is_null() { - return EINVAL; - } - let tcv = (*cv).transmute(); - if tcv.data.is_none() { - return EINVAL; - } - if m.is_null() { - return EINVAL; - } - let mut tm = (*m).transmute(); - if tm.data.is_none() || tm.data.as_ref().unwrap().lock.is_none() { - return EINVAL; +pub unsafe extern "C" fn z_condvar_wait( + this: &z_loaned_condvar_t, + m: &mut z_loaned_mutex_t, +) -> errors::z_error_t { + let this = this.transmute_ref(); + let m = m.transmute_mut(); + if m.1.is_none() { + return errors::Z_EINVAL_MUTEX; // lock was not aquired prior to wait call } - let mut_data = tm.data.as_mut().unwrap(); - let lock = mut_data.lock.take().unwrap(); - match tcv.data.as_ref().unwrap().wait(lock) { - Ok(new_lock) => mut_data.lock = Some(std::mem::transmute(new_lock)), - Err(_) => return EPOISON, + + let lock = m.1.take().unwrap(); + match this.wait(lock) { + Ok(new_lock) => m.1 = Some(new_lock), + Err(_) => return errors::Z_EPOISON_MUTEX, } - *cv = tcv.transmute(); - *m = tm.transmute(); - 0 -} -struct ZTask { - join_handle: JoinHandle<()>, + errors::Z_OK } -struct ZTaskPtr { - data: Option>, -} +pub use crate::opaque_types::z_owned_task_t; -/// Task -/// -#[repr(C)] -#[derive(Clone, Copy)] -pub struct z_task_t(usize); +decl_transmute_owned!(Option>, z_owned_task_t); #[repr(C)] #[derive(Clone, Copy)] pub struct z_task_attr_t(usize); -impl_guarded_transmute!(noderefs z_task_t, ZTaskPtr); -impl_guarded_transmute!(noderefs ZTaskPtr, z_task_t); +#[no_mangle] +pub extern "C" fn z_task_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); +} + +/// Detaches the task and releases all allocated resources. +#[no_mangle] +pub extern "C" fn z_task_detach(this: &mut z_owned_task_t) { + let _ = this.transmute_mut().extract().take(); +} + +/// Joins the task and releases all allocated resources +#[no_mangle] +pub extern "C" fn z_task_join(this: &mut z_owned_task_t) -> errors::z_error_t { + let this = this.transmute_mut().extract().take(); + if let Some(task) = this { + match task.join() { + Ok(_) => errors::Z_OK, + Err(_) => errors::Z_EINVAL_MUTEX, + } + } else { + errors::Z_OK + } +} + +#[no_mangle] +pub extern "C" fn z_task_check(this: &z_owned_task_t) -> bool { + this.transmute_ref().is_some() +} struct FunArgPair { fun: unsafe extern "C" fn(arg: *mut c_void), @@ -252,42 +223,19 @@ unsafe impl Send for FunArgPair {} #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn z_task_init( - task: *mut z_task_t, + this: *mut MaybeUninit, _attr: *const z_task_attr_t, fun: unsafe extern "C" fn(arg: *mut c_void), arg: *mut c_void, -) -> i8 { - if task.is_null() { - return EINVAL; - } - - let mut ttask = ZTaskPtr { data: None }; +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); let fun_arg_pair = FunArgPair { fun, arg }; - let mut ret = 0; match thread::Builder::new().spawn(move || fun_arg_pair.call()) { - Ok(join_handle) => ttask.data = Some(Box::new(ZTask { join_handle })), - Err(_) => ret = EAGAIN, - } - *task = ttask.transmute(); - ret -} - -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_task_join(task: *mut z_task_t) -> i8 { - if task.is_null() { - return EINVAL; - } - let mut ttask = (*task).transmute(); - if ttask.data.is_none() { - return EINVAL; + Ok(join_handle) => { + Inplace::init(this, Some(join_handle)); + } + Err(_) => return errors::Z_EAGAIN_MUTEX, } - let data = ttask.data.take(); - let ret = match data.unwrap().join_handle.join() { - Ok(_) => 0, - Err(_) => EINVAL, - }; - *task = ttask.transmute(); - ret + errors::Z_OK } diff --git a/src/publication_cache.rs b/src/publication_cache.rs index a97354b3b..49cc9f1f1 100644 --- a/src/publication_cache.rs +++ b/src/publication_cache.rs @@ -12,21 +12,19 @@ // ZettaScale Zenoh team, // -use std::ops::Deref; +use std::mem::MaybeUninit; +use std::ptr::null; +use zenoh::prelude::SyncResolve; use zenoh_ext::SessionExt; -use zenoh_util::core::zresult::ErrNo; -use zenoh_util::core::SyncResolve; -use crate::{ - impl_guarded_transmute, z_keyexpr_t, z_session_t, zcu_locality_default, zcu_locality_t, - UninitializedKeyExprError, -}; +use crate::transmute::{Inplace, TransmuteFromHandle, TransmuteRef, TransmuteUninitPtr}; +use crate::{errors, z_loaned_keyexpr_t, z_loaned_session_t, zcu_locality_default, zcu_locality_t}; /// Options passed to the :c:func:`ze_declare_publication_cache` function. /// /// Members: -/// z_keyexpr_t queryable_prefix: The prefix used for queryable +/// z_loaned_keyexpr_t queryable_prefix: The prefix used for queryable /// zcu_locality_t queryable_origin: The restriction for the matching queries that will be receive by this /// publication cache /// bool queryable_complete: the `complete` option for the queryable @@ -34,7 +32,7 @@ use crate::{ /// size_t resources_limit: The limit number of cached resources #[repr(C)] pub struct ze_publication_cache_options_t { - pub queryable_prefix: z_keyexpr_t, + pub queryable_prefix: *const z_loaned_keyexpr_t, pub queryable_origin: zcu_locality_t, pub queryable_complete: bool, pub history: usize, @@ -43,47 +41,32 @@ pub struct ze_publication_cache_options_t { /// Constructs the default value for :c:type:`ze_publication_cache_options_t`. #[no_mangle] -pub extern "C" fn ze_publication_cache_options_default() -> ze_publication_cache_options_t { - ze_publication_cache_options_t { - queryable_prefix: z_keyexpr_t::null(), +pub extern "C" fn ze_publication_cache_options_default(this: &mut ze_publication_cache_options_t) { + *this = ze_publication_cache_options_t { + queryable_prefix: null(), queryable_origin: zcu_locality_default(), queryable_complete: false, history: 1, resources_limit: 0, - } + }; } -type PublicationCache = Option>>; - -/// An owned zenoh publication_cache. -/// -/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. -/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. -/// -/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. -#[repr(C)] -pub struct ze_owned_publication_cache_t([usize; 1]); - -impl_guarded_transmute!(PublicationCache, ze_owned_publication_cache_t); - -impl ze_owned_publication_cache_t { - pub fn new(pub_cache: zenoh_ext::PublicationCache<'static>) -> Self { - Some(Box::new(pub_cache)).into() - } - pub fn null() -> Self { - None.into() - } -} +pub use crate::opaque_types::ze_loaned_publication_cache_t; +pub use crate::opaque_types::ze_owned_publication_cache_t; +decl_transmute_owned!( + Option>, + ze_owned_publication_cache_t +); +decl_transmute_handle!( + zenoh_ext::PublicationCache<'static>, + ze_loaned_publication_cache_t +); /// Declares a Publication Cache. /// /// Parameters: -/// z_session_t session: The zenoh session. -/// z_keyexpr_t keyexpr: The key expression to publish. +/// z_loaned_session_t session: The zenoh session. +/// z_loaned_keyexpr_t key_expr: The key expression to publish. /// ze_publication_cache_options_t options: Additional options for the publication_cache. /// /// Returns: @@ -106,74 +89,66 @@ impl ze_owned_publication_cache_t { #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn ze_declare_publication_cache( - session: z_session_t, - keyexpr: z_keyexpr_t, - options: Option<&ze_publication_cache_options_t>, -) -> ze_owned_publication_cache_t { - match session.upgrade() { - Some(s) => { - let keyexpr = keyexpr.deref().as_ref().map(|s| s.clone().into_owned()); - if let Some(key_expr) = keyexpr { - let mut p = s.declare_publication_cache(key_expr); - if let Some(options) = options { - p = p.history(options.history); - p = p.queryable_allowed_origin(options.queryable_origin.into()); - p = p.queryable_complete(options.queryable_complete); - if options.resources_limit != 0 { - p = p.resources_limit(options.resources_limit) - } - if options.queryable_prefix.deref().is_some() { - let queryable_prefix = options - .queryable_prefix - .deref() - .as_ref() - .map(|s| s.clone().into_owned()); - if let Some(queryable_prefix) = queryable_prefix { - p = p.queryable_prefix(queryable_prefix) - } - } - } - match p.res_sync() { - Ok(publication_cache) => ze_owned_publication_cache_t::new(publication_cache), - Err(e) => { - log::error!("{}", e); - ze_owned_publication_cache_t::null() - } - } - } else { - log::error!("{}", UninitializedKeyExprError); - ze_owned_publication_cache_t::null() - } + this: *mut MaybeUninit, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, + options: Option<&mut ze_publication_cache_options_t>, +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); + let session = session.transmute_ref(); + let key_expr = key_expr.transmute_ref(); + let mut p = session.declare_publication_cache(key_expr); + if let Some(options) = options { + p = p.history(options.history); + p = p.queryable_allowed_origin(options.queryable_origin.into()); + p = p.queryable_complete(options.queryable_complete); + if options.resources_limit != 0 { + p = p.resources_limit(options.resources_limit) + } + if !options.queryable_prefix.is_null() { + let queryable_prefix = unsafe { *options.queryable_prefix }.transmute_ref(); + p = p.queryable_prefix(queryable_prefix.clone()); + } + } + match p.res_sync() { + Ok(publication_cache) => { + Inplace::init(this, Some(publication_cache)); + errors::Z_OK + } + Err(e) => { + log::error!("{}", e); + Inplace::empty(this); + errors::Z_EGENERIC } - None => ze_owned_publication_cache_t::null(), } } /// Constructs a null safe-to-drop value of 'ze_owned_publication_cache_t' type #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn ze_publication_cache_null() -> ze_owned_publication_cache_t { - ze_owned_publication_cache_t::null() +pub extern "C" fn ze_publication_cache_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); } /// Returns ``true`` if `pub_cache` is valid. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn ze_publication_cache_check(pub_cache: &ze_owned_publication_cache_t) -> bool { - pub_cache.as_ref().is_some() +pub extern "C" fn ze_publication_cache_check(this: &ze_owned_publication_cache_t) -> bool { + this.transmute_ref().is_some() } /// Closes the given :c:type:`ze_owned_publication_cache_t`, droping it and invalidating it for double-drop safety. #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn ze_undeclare_publication_cache( - pub_cache: &mut ze_owned_publication_cache_t, -) -> i8 { - if let Some(p) = pub_cache.take() { + this: &mut ze_owned_publication_cache_t, +) -> errors::z_error_t { + if let Some(p) = this.transmute_mut().extract().take() { if let Err(e) = p.close().res_sync() { log::error!("{}", e); - return e.errno().get(); + return errors::Z_EGENERIC; } } - 0 + errors::Z_OK } diff --git a/src/publisher.rs b/src/publisher.rs index f49d8cd31..acc473008 100644 --- a/src/publisher.rs +++ b/src/publisher.rs @@ -12,29 +12,30 @@ // ZettaScale Zenoh team, // +use crate::errors; +use crate::transmute::unwrap_ref_unchecked; +use crate::transmute::Inplace; +use crate::transmute::TransmuteFromHandle; +use crate::transmute::TransmuteIntoHandle; +use crate::transmute::TransmuteRef; +use crate::transmute::TransmuteUninitPtr; +use crate::z_owned_encoding_t; use crate::zcu_closure_matching_status_call; use crate::zcu_owned_closure_matching_status_t; -use std::ops::{Deref, DerefMut}; +use std::mem::MaybeUninit; +use std::ptr; +use zenoh::handlers::DefaultHandler; use zenoh::prelude::SessionDeclarations; -use zenoh::{ - prelude::{Priority, Value}, - publication::MatchingListener, - publication::Publisher, - sample::AttachmentBuilder, -}; -use zenoh_protocol::core::CongestionControl; -use zenoh_util::core::{zresult::ErrNo, SyncResolve}; +use zenoh::publication::CongestionControl; +use zenoh::sample::QoSBuilderTrait; +use zenoh::sample::SampleBuilderTrait; +use zenoh::sample::ValueBuilderTrait; +use zenoh::{prelude::Priority, publication::MatchingListener, publication::Publisher}; -use crate::attachment::{ - insert_in_attachment_builder, z_attachment_check, z_attachment_iterate, z_attachment_null, - z_attachment_t, -}; -use libc::c_void; +use zenoh::prelude::SyncResolve; use crate::{ - impl_guarded_transmute, z_congestion_control_t, z_encoding_default, z_encoding_t, z_keyexpr_t, - z_owned_keyexpr_t, z_priority_t, z_session_t, zc_owned_payload_t, GuardedTransmute, - UninitializedKeyExprError, LOG_INVALID_SESSION, + z_congestion_control_t, z_loaned_keyexpr_t, z_loaned_session_t, z_owned_bytes_t, z_priority_t, }; /// Options passed to the :c:func:`z_declare_publisher` function. @@ -50,54 +51,17 @@ pub struct z_publisher_options_t { /// Constructs the default value for :c:type:`z_publisher_options_t`. #[no_mangle] -pub extern "C" fn z_publisher_options_default() -> z_publisher_options_t { - z_publisher_options_t { +pub extern "C" fn z_publisher_options_default(this: &mut z_publisher_options_t) { + *this = z_publisher_options_t { congestion_control: CongestionControl::default().into(), priority: Priority::default().into(), - } + }; } -/// An owned zenoh publisher. -/// -/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. -/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. -/// -/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. -#[cfg(not(target_arch = "arm"))] -#[repr(C, align(8))] -pub struct z_owned_publisher_t([u64; 7]); - -#[cfg(target_arch = "arm")] -#[repr(C, align(4))] -pub struct z_owned_publisher_t([u32; 8]); - -impl_guarded_transmute!(noderefs Option>, z_owned_publisher_t); - -impl<'a> From>> for z_owned_publisher_t { - fn from(val: Option) -> Self { - val.transmute() - } -} -impl Deref for z_owned_publisher_t { - type Target = Option>; - fn deref(&self) -> &Self::Target { - unsafe { std::mem::transmute(self) } - } -} -impl DerefMut for z_owned_publisher_t { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { std::mem::transmute(self) } - } -} -impl z_owned_publisher_t { - pub fn null() -> Self { - None.into() - } -} +pub use crate::opaque_types::z_owned_publisher_t; +decl_transmute_owned!(Option>, z_owned_publisher_t); +pub use crate::opaque_types::z_loaned_publisher_t; +decl_transmute_handle!(Publisher<'static>, z_loaned_publisher_t); /// Declares a publisher for the given key expression. /// @@ -106,7 +70,7 @@ impl z_owned_publisher_t { /// /// Parameters: /// session: The zenoh session. -/// keyexpr: The key expression to publish. +/// key_expr: The key expression to publish. /// options: additional options for the publisher. /// /// Returns: @@ -135,193 +99,124 @@ impl z_owned_publisher_t { #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn z_declare_publisher( - session: z_session_t, - keyexpr: z_keyexpr_t, + this: *mut MaybeUninit, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, options: Option<&z_publisher_options_t>, -) -> z_owned_publisher_t { - match session.upgrade() { - Some(s) => { - let keyexpr = keyexpr.deref().as_ref().map(|s| s.clone().into_owned()); - if let Some(key_expr) = keyexpr { - let mut p = s.declare_publisher(key_expr); - if let Some(options) = options { - p = p - .congestion_control(options.congestion_control.into()) - .priority(options.priority.into()); - } - match p.res_sync() { - Err(e) => { - log::error!("{}", e); - None - } - Ok(publisher) => Some(publisher), - } - } else { - log::error!("{}", UninitializedKeyExprError); - None - } +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); + let session = session.transmute_ref(); + let key_expr = key_expr.transmute_ref().clone().into_owned(); + let mut p = session.declare_publisher(key_expr); + if let Some(options) = options { + p = p + .congestion_control(options.congestion_control.into()) + .priority(options.priority.into()); + } + match p.res_sync() { + Err(e) => { + log::error!("{}", e); + Inplace::empty(this); + errors::Z_EGENERIC } - None => { - log::debug!("{}", LOG_INVALID_SESSION); - None + Ok(publisher) => { + Inplace::init(this, Some(publisher)); + errors::Z_OK } } - .into() } /// Constructs a null safe-to-drop value of 'z_owned_publisher_t' type #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_publisher_null() -> z_owned_publisher_t { - z_owned_publisher_t::null() +pub extern "C" fn z_publisher_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); } /// Returns ``true`` if `pub` is valid. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_publisher_check(pbl: &z_owned_publisher_t) -> bool { - pbl.as_ref().is_some() -} - -/// A loaned zenoh publisher. -#[allow(non_camel_case_types)] -#[derive(Clone, Copy)] -#[repr(C)] -pub struct z_publisher_t(*const z_owned_publisher_t); - -impl<'a> AsRef>> for z_owned_publisher_t { - fn as_ref(&self) -> &'a Option> { - unsafe { std::mem::transmute(self) } - } -} - -impl<'a> AsMut>> for z_owned_publisher_t { - fn as_mut(&mut self) -> &'a mut Option> { - unsafe { std::mem::transmute(self) } - } +pub extern "C" fn z_publisher_check(this: &z_owned_publisher_t) -> bool { + this.transmute_ref().is_some() } -impl<'a> AsRef>> for z_publisher_t { - fn as_ref(&self) -> &'a Option> { - unsafe { (*self.0).as_ref() } - } -} - -/// Returns a :c:type:`z_publisher_t` loaned from `p`. +/// Returns a :c:type:`z_loaned_publisher_t` loaned from `p`. #[no_mangle] -pub extern "C" fn z_publisher_loan(p: &z_owned_publisher_t) -> z_publisher_t { - z_publisher_t(p) +pub extern "C" fn z_publisher_loan(this: &z_owned_publisher_t) -> &z_loaned_publisher_t { + let this = this.transmute_ref(); + let this = unwrap_ref_unchecked(this); + this.transmute_handle() } /// Options passed to the :c:func:`z_publisher_put` function. /// /// Members: -/// z_encoding_t encoding: The encoding of the payload. -/// z_attachment_t attachment: The attachment to attach to the publication. +/// z_owned_encoding_t encoding: The encoding of the payload. +/// z_owned_bytes_t attachment: The attachment to attach to the publication. #[repr(C)] pub struct z_publisher_put_options_t { - pub encoding: z_encoding_t, - pub attachment: z_attachment_t, + pub encoding: *mut z_owned_encoding_t, + pub attachment: *mut z_owned_bytes_t, } /// Constructs the default value for :c:type:`z_publisher_put_options_t`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_publisher_put_options_default() -> z_publisher_put_options_t { - z_publisher_put_options_t { - encoding: z_encoding_default(), - attachment: z_attachment_null(), +pub extern "C" fn z_publisher_put_options_default(this: &mut z_publisher_put_options_t) { + *this = z_publisher_put_options_t { + encoding: ptr::null_mut(), + attachment: ptr::null_mut(), } } -/// Sends a `PUT` message onto the publisher's key expression. -/// -/// The payload's encoding can be sepcified through the options. -/// -/// Parameters: -/// session: The zenoh session. -/// payload: The value to put. -/// len: The length of the value to put. -/// options: The publisher put options. -/// Returns: -/// ``0`` in case of success, negative values in case of failure. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_publisher_put( - publisher: z_publisher_t, - payload: *const u8, - len: usize, - options: Option<&z_publisher_put_options_t>, -) -> i8 { - if let Some(p) = publisher.as_ref() { - let value: Value = std::slice::from_raw_parts(payload, len).into(); - let put = match options { - Some(options) => { - let mut put = p.put(value.encoding(options.encoding.into())); - if z_attachment_check(&options.attachment) { - let mut attachment_builder = AttachmentBuilder::new(); - z_attachment_iterate( - options.attachment, - insert_in_attachment_builder, - &mut attachment_builder as *mut AttachmentBuilder as *mut c_void, - ); - put = put.with_attachment(attachment_builder.build()); - }; - put - } - None => p.put(value), - }; - if let Err(e) = put.res_sync() { - log::error!("{}", e); - e.errno().get() - } else { - 0 - } - } else { - i8::MIN - } -} - -/// Sends a `PUT` message onto the publisher's key expression, transfering the buffer ownership. +/// Sends a `PUT` message onto the publisher's key expression, transfering the payload ownership. /// /// This is avoids copies when transfering data that was either: -/// - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher +/// - `z_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher /// - constructed from a `zc_owned_shmbuf_t` /// -/// The payload's encoding can be sepcified through the options. +/// The payload and all owned options fields are consumed upon function return. /// /// Parameters: /// session: The zenoh session. /// payload: The value to put. -/// len: The length of the value to put. /// options: The publisher put options. /// Returns: /// ``0`` in case of success, negative values in case of failure. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn zc_publisher_put_owned( - publisher: z_publisher_t, - payload: Option<&mut zc_owned_payload_t>, - options: Option<&z_publisher_put_options_t>, -) -> i8 { - if let Some(p) = publisher.as_ref() { - let Some(payload) = payload.and_then(|p| p.take()) else { - log::debug!("Attempted to put without a payload"); - return i8::MIN; - }; - let value: Value = payload.into(); - let put = match options { - Some(options) => p.put(value.encoding(options.encoding.into())), - None => p.put(value), +pub unsafe extern "C" fn z_publisher_put( + publisher: &z_loaned_publisher_t, + payload: &mut z_owned_bytes_t, + options: Option<&mut z_publisher_put_options_t>, +) -> errors::z_error_t { + let publisher = publisher.transmute_ref(); + let payload = match payload.transmute_mut().extract() { + Some(p) => p, + None => { + log::debug!("Attempted to put with a null payload"); + return errors::Z_EINVAL; + } + }; + + let mut put = publisher.put(payload); + if let Some(options) = options { + if !options.encoding.is_null() { + let encoding = unsafe { *options.encoding }.transmute_mut().extract(); + put = put.encoding(encoding); }; - if let Err(e) = put.res_sync() { - log::error!("{}", e); - e.errno().get() - } else { - 0 + if !options.attachment.is_null() { + let attachment = unsafe { *options.attachment }.transmute_mut().extract(); + put = put.attachment(attachment); } + } + + if let Err(e) = put.res_sync() { + log::error!("{}", e); + errors::Z_EGENERIC } else { - i8::MIN + errors::Z_OK } } @@ -338,8 +233,8 @@ pub struct z_publisher_delete_options_t { /// Returns the constructed :c:type:`z_publisher_delete_options_t`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_publisher_delete_options_default() -> z_publisher_delete_options_t { - z_publisher_delete_options_t { __dummy: 0 } +pub extern "C" fn z_publisher_delete_options_default(this: &mut z_publisher_delete_options_t) { + *this = z_publisher_delete_options_t { __dummy: 0 } } /// Sends a `DELETE` message onto the publisher's key expression. /// @@ -348,62 +243,32 @@ pub extern "C" fn z_publisher_delete_options_default() -> z_publisher_delete_opt #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn z_publisher_delete( - publisher: z_publisher_t, - _options: *const z_publisher_delete_options_t, -) -> i8 { - if let Some(p) = publisher.as_ref() { - if let Err(e) = p.delete().res_sync() { - log::error!("{}", e); - e.errno().get() - } else { - 0 - } + publisher: &z_loaned_publisher_t, + _options: z_publisher_delete_options_t, +) -> errors::z_error_t { + let publisher = publisher.transmute_ref(); + if let Err(e) = publisher.delete().res_sync() { + log::error!("{}", e); + errors::Z_EGENERIC } else { - i8::MIN + errors::Z_OK } } /// Returns the key expression of the publisher #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_publisher_keyexpr(publisher: z_publisher_t) -> z_owned_keyexpr_t { - if let Some(p) = publisher.as_ref() { - p.key_expr().clone().into() - } else { - z_keyexpr_t::null().into() - } +pub extern "C" fn z_publisher_keyexpr(publisher: &z_loaned_publisher_t) -> &z_loaned_keyexpr_t { + let publisher = publisher.transmute_ref(); + publisher.key_expr().transmute_handle() } -/// An owned zenoh matching listener. Destroying the matching listener cancels the subscription. -/// -/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. -/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. -/// -/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. -#[repr(C, align(8))] -pub struct zcu_owned_matching_listener_t([u64; 4]); - -impl_guarded_transmute!(noderefs - Option>, +pub use crate::opaque_types::zcu_owned_matching_listener_t; +decl_transmute_owned!( + Option>, zcu_owned_matching_listener_t ); -impl From>> for zcu_owned_matching_listener_t { - fn from(val: Option>) -> Self { - val.transmute() - } -} - -impl zcu_owned_matching_listener_t { - pub fn null() -> Self { - None.into() - } -} - /// A struct that indicates if there exist Subscribers matching the Publisher's key expression. /// /// Members: @@ -418,40 +283,44 @@ pub struct zcu_matching_status_t { #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn zcu_publisher_matching_listener_callback( - publisher: z_publisher_t, + this: *mut MaybeUninit, + publisher: &z_loaned_publisher_t, callback: &mut zcu_owned_closure_matching_status_t, -) -> zcu_owned_matching_listener_t { +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); let mut closure = zcu_owned_closure_matching_status_t::empty(); std::mem::swap(callback, &mut closure); - { - if let Some(p) = publisher.as_ref() { - let listener = p - .matching_listener() - .callback_mut(move |matching_status| { - let status = zcu_matching_status_t { - matching: matching_status.matching_subscribers(), - }; - zcu_closure_matching_status_call(&closure, &status); - }) - .res() - .unwrap(); - Some(listener) - } else { - None + let publisher = publisher.transmute_ref(); + let listener = publisher + .matching_listener() + .callback_mut(move |matching_status| { + let status = zcu_matching_status_t { + matching: matching_status.matching_subscribers(), + }; + zcu_closure_matching_status_call(&closure, &status); + }) + .res(); + match listener { + Ok(_) => { + Inplace::empty(this); + errors::Z_OK + } + Err(e) => { + log::error!("{}", e); + errors::Z_EGENERIC } } - .into() } /// Undeclares the given :c:type:`z_owned_publisher_t`, droping it and invalidating it for double-drop safety. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_undeclare_publisher(publisher: &mut z_owned_publisher_t) -> i8 { - if let Some(p) = publisher.take() { +pub extern "C" fn z_undeclare_publisher(this: &mut z_owned_publisher_t) -> errors::z_error_t { + if let Some(p) = this.transmute_mut().extract().take() { if let Err(e) = p.undeclare().res_sync() { log::error!("{}", e); - return e.errno().get(); + return errors::Z_EGENERIC; } } - 0 + errors::Z_OK } diff --git a/src/pull_subscriber.rs b/src/pull_subscriber.rs index 0eee4bc94..79ba96eb3 100644 --- a/src/pull_subscriber.rs +++ b/src/pull_subscriber.rs @@ -22,7 +22,6 @@ use crate::z_reliability_t; use crate::LOG_INVALID_SESSION; use zenoh::prelude::sync::SyncResolve; use zenoh::prelude::SessionDeclarations; -use zenoh::prelude::SplitBuffer; use zenoh_protocol::core::SubInfo; use zenoh_util::core::zresult::ErrNo; @@ -132,15 +131,15 @@ pub extern "C" fn z_pull_subscriber_options_default() -> z_pull_subscriber_optio /// /// .. code-block:: C /// -/// z_subscriber_options_t opts = z_subscriber_options_default(); +/// z_subscriber_options_t options = z_subscriber_options_default(); /// z_owned_subscriber_t sub = z_declare_pull_subscriber(z_loan(s), z_keyexpr(expr), callback, &opts); #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn z_declare_pull_subscriber( - session: z_session_t, - keyexpr: z_keyexpr_t, + session: z_loaned_session_t, + keyexpr: z_loaned_keyexpr_t, callback: &mut z_owned_closure_sample_t, - opts: Option<&z_pull_subscriber_options_t>, + options: Option<&z_pull_subscriber_options_t>, ) -> z_owned_pull_subscriber_t { let mut closure = z_owned_closure_sample_t::empty(); std::mem::swap(callback, &mut closure); @@ -150,12 +149,7 @@ pub extern "C" fn z_declare_pull_subscriber( let mut res = s .declare_subscriber(keyexpr) .callback(move |sample| { - let payload = sample.payload.contiguous(); - let owner = match payload { - std::borrow::Cow::Owned(v) => zenoh::buffers::ZBuf::from(v), - _ => sample.payload.clone(), - }; - let sample = z_sample_t::new(&sample, &owner); + let sample = z_loaned_sample_t::new(&sample); z_closure_sample_call(&closure, &sample) }) .pull_mode(); diff --git a/src/put.rs b/src/put.rs index b5d9f2f94..ef5f99801 100644 --- a/src/put.rs +++ b/src/put.rs @@ -1,3 +1,5 @@ +use std::ptr::null_mut; + // // Copyright (c) 2017, 2022 ZettaScale Technology. // @@ -12,235 +14,96 @@ // ZettaScale Zenoh team, // use crate::commons::*; +use crate::errors; use crate::keyexpr::*; -use crate::session::*; -use crate::LOG_INVALID_SESSION; -use libc::c_void; -use libc::size_t; -use zenoh::prelude::{sync::SyncResolve, Priority, SampleKind}; +use crate::transmute::Inplace; +use crate::transmute::TransmuteFromHandle; +use crate::transmute::TransmuteRef; +use crate::z_loaned_session_t; +use crate::z_owned_bytes_t; +use zenoh::prelude::{sync::SyncResolve, Priority}; use zenoh::publication::CongestionControl; -use zenoh::sample::AttachmentBuilder; -use zenoh_util::core::zresult::ErrNo; - -use crate::attachment::{ - insert_in_attachment_builder, z_attachment_check, z_attachment_iterate, z_attachment_null, - z_attachment_t, -}; - -/// The priority of zenoh messages. -/// -/// - **REAL_TIME** -/// - **INTERACTIVE_HIGH** -/// - **INTERACTIVE_LOW** -/// - **DATA_HIGH** -/// - **DATA** -/// - **DATA_LOW** -/// - **BACKGROUND** -#[allow(non_camel_case_types)] -#[repr(C)] -#[derive(Clone, Copy)] -pub enum z_priority_t { - REAL_TIME = 1, - INTERACTIVE_HIGH = 2, - INTERACTIVE_LOW = 3, - DATA_HIGH = 4, - DATA = 5, - DATA_LOW = 6, - BACKGROUND = 7, -} - -impl From for z_priority_t { - fn from(p: Priority) -> Self { - match p { - Priority::RealTime => z_priority_t::REAL_TIME, - Priority::InteractiveHigh => z_priority_t::INTERACTIVE_HIGH, - Priority::InteractiveLow => z_priority_t::INTERACTIVE_LOW, - Priority::DataHigh => z_priority_t::DATA_HIGH, - Priority::Data => z_priority_t::DATA, - Priority::DataLow => z_priority_t::DATA_LOW, - Priority::Background => z_priority_t::BACKGROUND, - } - } -} - -impl From for Priority { - fn from(p: z_priority_t) -> Self { - match p { - z_priority_t::REAL_TIME => Priority::RealTime, - z_priority_t::INTERACTIVE_HIGH => Priority::InteractiveHigh, - z_priority_t::INTERACTIVE_LOW => Priority::InteractiveLow, - z_priority_t::DATA_HIGH => Priority::DataHigh, - z_priority_t::DATA => Priority::Data, - z_priority_t::DATA_LOW => Priority::DataLow, - z_priority_t::BACKGROUND => Priority::Background, - } - } -} - -/// The kind of congestion control. -/// -/// - **BLOCK** -/// - **DROP** -#[allow(non_camel_case_types)] -#[repr(C)] -#[derive(Clone, Copy)] -pub enum z_congestion_control_t { - BLOCK, - DROP, -} - -impl From for z_congestion_control_t { - fn from(cc: CongestionControl) -> Self { - match cc { - CongestionControl::Block => z_congestion_control_t::BLOCK, - CongestionControl::Drop => z_congestion_control_t::DROP, - } - } -} - -impl From for CongestionControl { - fn from(cc: z_congestion_control_t) -> Self { - match cc { - z_congestion_control_t::BLOCK => CongestionControl::Block, - z_congestion_control_t::DROP => CongestionControl::Drop, - } - } -} +use zenoh::sample::QoSBuilderTrait; +use zenoh::sample::SampleBuilderTrait; +use zenoh::sample::ValueBuilderTrait; /// Options passed to the :c:func:`z_put` function. /// /// Members: -/// z_encoding_t encoding: The encoding of the payload. +/// z_loaned_encoding_t encoding: The encoding of the payload. /// z_congestion_control_t congestion_control: The congestion control to apply when routing this message. /// z_priority_t priority: The priority of this message. -/// z_attachment_t attachment: The attachment to this message. +/// z_loaned_bytes_t attachment: The attachment to this message. #[repr(C)] #[allow(non_camel_case_types)] pub struct z_put_options_t { - pub encoding: z_encoding_t, + pub encoding: *mut z_owned_encoding_t, pub congestion_control: z_congestion_control_t, pub priority: z_priority_t, - pub attachment: z_attachment_t, + pub attachment: *mut z_owned_bytes_t, } /// Constructs the default value for :c:type:`z_put_options_t`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_put_options_default() -> z_put_options_t { - z_put_options_t { - encoding: z_encoding_default(), +pub extern "C" fn z_put_options_default(this: &mut z_put_options_t) { + *this = z_put_options_t { + encoding: null_mut(), congestion_control: CongestionControl::default().into(), priority: Priority::default().into(), - attachment: z_attachment_null(), - } + attachment: null_mut(), + }; } -/// Put data. +/// Put data, transfering its ownership. /// -/// The payload's encoding can be sepcified through the options. +/// +/// The payload's encoding and attachment can be sepcified through the options. These values are consumed upon function +/// return. /// /// Parameters: /// session: The zenoh session. -/// keyexpr: The key expression to put. -/// payload: The value to put. -/// len: The length of the value to put. +/// key_expr: The key expression to put. +/// payload: The value to put (consumed upon function return). /// options: The put options. /// Returns: -/// ``0`` in case of success, negative values in case of failure. +/// ``0`` in case of success, negative error values in case of failure. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_put( - session: z_session_t, - keyexpr: z_keyexpr_t, - payload: *const u8, - len: size_t, - opts: Option<&z_put_options_t>, -) -> i8 { - match session.upgrade() { - Some(s) => { - let mut res = s - .put(keyexpr, std::slice::from_raw_parts(payload, len)) - .kind(SampleKind::Put); - if let Some(opts) = opts { - res = res - .encoding(opts.encoding) - .congestion_control(opts.congestion_control.into()) - .priority(opts.priority.into()); - if z_attachment_check(&opts.attachment) { - let mut attachment_builder = AttachmentBuilder::new(); - z_attachment_iterate( - opts.attachment, - insert_in_attachment_builder, - &mut attachment_builder as *mut AttachmentBuilder as *mut c_void, - ); - res = res.with_attachment(attachment_builder.build()); - }; - } - match res.res_sync() { - Err(e) => { - log::error!("{}", e); - e.errno().get() - } - Ok(()) => 0, - } - } +pub extern "C" fn z_put( + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, + payload: &mut z_owned_bytes_t, + options: Option<&mut z_put_options_t>, +) -> errors::z_error_t { + let session = session.transmute_ref(); + let key_expr = key_expr.transmute_ref(); + let payload = match payload.transmute_mut().extract() { + Some(p) => p, None => { - log::debug!("{}", LOG_INVALID_SESSION); - i8::MIN + log::debug!("Attempted to put with a null payload"); + return errors::Z_EINVAL; } - } -} + }; -/// Put data, transfering the buffer ownership. -/// -/// This is avoids copies when transfering data that was either: -/// - `zc_sample_payload_rcinc`'d from a sample, when forwarding samples from a subscriber/query to a publisher -/// - constructed from a `zc_owned_shmbuf_t` -/// -/// The payload's encoding can be sepcified through the options. -/// -/// Parameters: -/// session: The zenoh session. -/// keyexpr: The key expression to put. -/// payload: The value to put. -/// options: The put options. -/// Returns: -/// ``0`` in case of success, negative values in case of failure. -#[no_mangle] -#[allow(clippy::missing_safety_doc)] -pub extern "C" fn zc_put_owned( - session: z_session_t, - keyexpr: z_keyexpr_t, - payload: Option<&mut zc_owned_payload_t>, - opts: Option<&z_put_options_t>, -) -> i8 { - match session.upgrade() { - Some(s) => { - if let Some(payload) = payload.and_then(|p| p.take()) { - let mut res = s.put(keyexpr, payload).kind(SampleKind::Put); - if let Some(opts) = opts { - res = res - .encoding(opts.encoding) - .congestion_control(opts.congestion_control.into()) - .priority(opts.priority.into()); - } - match res.res_sync() { - Err(e) => { - log::error!("{}", e); - e.errno().get() - } - Ok(()) => 0, - } - } else { - log::debug!("zc_payload_null was provided as payload for put"); - i8::MIN - } - } - None => { - log::debug!("{}", LOG_INVALID_SESSION); - i8::MIN + let mut put = session.put(key_expr, payload); + if let Some(options) = options { + if !options.encoding.is_null() { + let encoding = unsafe { *options.encoding }.transmute_mut().extract(); + put = put.encoding(encoding); + }; + if !options.attachment.is_null() { + let attachment = unsafe { *options.attachment }.transmute_mut().extract(); + put = put.attachment(attachment); } } + + if let Err(e) = put.res_sync() { + log::error!("{}", e); + errors::Z_EGENERIC + } else { + errors::Z_OK + } } /// Options passed to the :c:func:`z_delete` function. @@ -254,47 +117,42 @@ pub struct z_delete_options_t { /// Constructs the default value for :c:type:`z_put_options_t`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub unsafe extern "C" fn z_delete_options_default() -> z_delete_options_t { - z_delete_options_t { +pub unsafe extern "C" fn z_delete_options_default(this: *mut z_delete_options_t) { + *this = z_delete_options_t { congestion_control: CongestionControl::default().into(), priority: Priority::default().into(), - } + }; } /// Delete data. /// /// Parameters: /// session: The zenoh session. -/// keyexpr: The key expression to delete. -/// options: The put options. +/// key_expr: The key expression to delete. +/// options: The delete options. /// Returns: /// ``0`` in case of success, negative values in case of failure. #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn z_delete( - session: z_session_t, - keyexpr: z_keyexpr_t, - opts: Option<&z_delete_options_t>, -) -> i8 { - match session.upgrade() { - Some(s) => { - let mut res = s.delete(keyexpr); - if let Some(opts) = opts { - res = res - .congestion_control(opts.congestion_control.into()) - .priority(opts.priority.into()); - } - match res.res_sync() { - Err(e) => { - log::error!("{}", e); - e.errno().get() - } - Ok(()) => 0, - } - } - None => { - log::debug!("{}", LOG_INVALID_SESSION); - i8::MIN + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, + options: Option<&mut z_delete_options_t>, +) -> errors::z_error_t { + let session = session.transmute_ref(); + let key_expr = key_expr.transmute_ref(); + let mut del = session.delete(key_expr); + if let Some(options) = options { + del = del + .congestion_control(options.congestion_control.into()) + .priority(options.priority.into()); + } + + match del.res_sync() { + Err(e) => { + log::error!("{}", e); + errors::Z_EGENERIC } + Ok(()) => errors::Z_OK, } } diff --git a/src/queryable.rs b/src/queryable.rs index 1906dc735..03da4edbe 100644 --- a/src/queryable.rs +++ b/src/queryable.rs @@ -11,82 +11,34 @@ // Contributors: // ZettaScale Zenoh team, // -use crate::attachment::{ - attachment_iteration_driver, insert_in_attachment_builder, z_attachment_check, - z_attachment_iterate, z_attachment_null, z_attachment_t, +use crate::transmute::{ + unwrap_ref_unchecked, Inplace, TransmuteFromHandle, TransmuteIntoHandle, TransmuteRef, + TransmuteUninitPtr, }; use crate::{ - impl_guarded_transmute, z_bytes_t, z_closure_query_call, z_encoding_default, z_encoding_t, - z_keyexpr_t, z_owned_closure_query_t, z_session_t, z_value_t, LOG_INVALID_SESSION, + errors, z_closure_query_call, z_loaned_bytes_t, z_loaned_keyexpr_t, z_loaned_session_t, + z_loaned_value_t, z_owned_bytes_t, z_owned_closure_query_t, z_owned_encoding_t, z_view_slice_t, + z_view_slice_wrap, }; -use libc::c_void; -use std::ops::{Deref, DerefMut}; +use std::mem::MaybeUninit; +use std::ptr::{null, null_mut}; use zenoh::prelude::SessionDeclarations; -use zenoh::{ - prelude::{Sample, SplitBuffer}, - queryable::{Query, Queryable as CallbackQueryable}, - sample::AttachmentBuilder, - value::Value, -}; -use zenoh_util::core::{zresult::ErrNo, SyncResolve}; - -type Queryable = Option>; -/// An owned zenoh queryable. -/// -/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. -/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. -/// -/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. -#[cfg(not(target_arch = "arm"))] -#[repr(C, align(8))] -pub struct z_owned_queryable_t([u64; 4]); - -#[cfg(target_arch = "arm")] -#[repr(C, align(4))] -pub struct z_owned_queryable_t([u32; 4]); +use zenoh::prelude::SyncResolve; +use zenoh::prelude::{Query, Queryable}; +use zenoh::sample::{SampleBuilderTrait, ValueBuilderTrait}; -impl_guarded_transmute!(Queryable, z_owned_queryable_t); - -impl z_owned_queryable_t { - pub fn null() -> Self { - None.into() - } -} +pub use crate::opaque_types::z_owned_queryable_t; +decl_transmute_owned!(Option>, z_owned_queryable_t); /// Constructs a null safe-to-drop value of 'z_owned_queryable_t' type #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_queryable_null() -> z_owned_queryable_t { - z_owned_queryable_t::null() +pub extern "C" fn z_queryable_null(this: *mut MaybeUninit) { + Inplace::empty(this.transmute_uninit_ptr()); } -/// Loaned variant of a Query received by a Queryable. -/// -/// Queries are atomically reference-counted, letting you extract them from the callback that handed them to you by cloning. -/// `z_query_t`'s are valid as long as at least one corresponding `z_owned_query_t` exists, including the one owned by Zenoh until the callback returns. -#[allow(non_camel_case_types)] -#[repr(C)] -pub struct z_query_t(*mut c_void); -impl From<&Query> for z_query_t { - fn from(value: &Query) -> Self { - z_query_t(value as *const _ as *mut _) - } -} -impl From> for z_query_t { - fn from(value: Option<&Query>) -> Self { - value.map_or(Self(core::ptr::null_mut()), Into::into) - } -} -impl Deref for z_query_t { - type Target = Option<&'static Query>; - fn deref(&self) -> &Self::Target { - unsafe { core::mem::transmute(self) } - } -} +pub use crate::opaque_types::z_loaned_query_t; +decl_transmute_handle!(Query, z_loaned_query_t); /// Owned variant of a Query received by a Queryable. /// @@ -96,68 +48,46 @@ impl Deref for z_query_t { /// /// Holding onto an `z_owned_query_t` for too long (10s by default, can be set in `z_get`'s options) will trigger a timeout error /// to be sent to the querier by the infrastructure, and new responses to the outdated query will be silently dropped. -#[allow(non_camel_case_types)] -#[repr(C)] -pub struct z_owned_query_t(*mut c_void); +pub use crate::opaque_types::z_owned_query_t; +decl_transmute_owned!(Option, z_owned_query_t); -impl From> for z_owned_query_t { - fn from(value: Option) -> Self { - unsafe { core::mem::transmute(value) } - } -} -impl From for z_owned_query_t { - fn from(value: Query) -> Self { - Some(value).into() - } -} -impl Deref for z_owned_query_t { - type Target = Option; - fn deref(&self) -> &Self::Target { - unsafe { core::mem::transmute(self) } - } -} -impl DerefMut for z_owned_query_t { - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { core::mem::transmute(self) } - } -} -impl Drop for z_owned_query_t { - fn drop(&mut self) { - let _: Option = self.take(); - } -} /// The gravestone value of `z_owned_query_t`. #[no_mangle] -pub extern "C" fn z_query_null() -> z_owned_query_t { - unsafe { core::mem::transmute(None::) } +pub extern "C" fn z_query_null(this: *mut MaybeUninit) { + Inplace::empty(this.transmute_uninit_ptr()); } /// Returns `false` if `this` is in a gravestone state, `true` otherwise. /// /// This function may not be called with the null pointer, but can be called with the gravestone value. #[no_mangle] -pub extern "C" fn z_query_check(this: &z_owned_query_t) -> bool { - this.is_some() +pub extern "C" fn z_query_check(query: &z_owned_query_t) -> bool { + query.transmute_ref().is_some() } /// Aliases the query. /// /// This function may not be called with the null pointer, but can be called with the gravestone value. #[no_mangle] -pub extern "C" fn z_query_loan(this: &z_owned_query_t) -> z_query_t { - this.as_ref().into() +pub extern "C" fn z_query_loan(this: &'static z_owned_query_t) -> &z_loaned_query_t { + let this = this.transmute_ref(); + let this = unwrap_ref_unchecked(this); + this.transmute_handle() } /// Destroys the query, setting `this` to its gravestone value to prevent double-frees. /// /// This function may not be called with the null pointer, but can be called with the gravestone value. #[no_mangle] pub extern "C" fn z_query_drop(this: &mut z_owned_query_t) { - let _: Option = this.take(); + Inplace::drop(this.transmute_mut()) } /// Clones the query, allowing to keep it in an "open" state past the callback's return. /// /// This operation is infallible, but may return a gravestone value if `query` itself was a gravestone value (which cannot be the case in a callback). #[no_mangle] -pub extern "C" fn z_query_clone(query: Option<&z_query_t>) -> z_owned_query_t { - query.and_then(|q| q.cloned()).into() +pub extern "C" fn z_query_clone(this: &z_loaned_query_t, dst: *mut MaybeUninit) { + let this = this.transmute_ref(); + let this = this.clone(); + let dst = dst.transmute_uninit_ptr(); + Inplace::init(dst, Some(this)); } /// Options passed to the :c:func:`z_declare_queryable` function. @@ -172,38 +102,38 @@ pub struct z_queryable_options_t { /// Constructs the default value for :c:type:`z_query_reply_options_t`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_queryable_options_default() -> z_queryable_options_t { - z_queryable_options_t { complete: false } +pub extern "C" fn z_queryable_options_default(this: &mut z_queryable_options_t) { + *this = z_queryable_options_t { complete: false }; } /// Represents the set of options that can be applied to a query reply, /// sent via :c:func:`z_query_reply`. /// /// Members: -/// z_encoding_t encoding: The encoding of the payload. -/// z_attachment_t attachment: The attachment to this reply. +/// z_owned_encoding_t encoding: The encoding of the payload. +/// z_owned_bytes_t attachment: The attachment to this reply. #[allow(non_camel_case_types)] #[repr(C)] pub struct z_query_reply_options_t { - pub encoding: z_encoding_t, - pub attachment: z_attachment_t, + pub encoding: *mut z_owned_encoding_t, + pub attachment: *mut z_owned_bytes_t, } /// Constructs the default value for :c:type:`z_query_reply_options_t`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_query_reply_options_default() -> z_query_reply_options_t { - z_query_reply_options_t { - encoding: z_encoding_default(), - attachment: z_attachment_null(), - } +pub extern "C" fn z_query_reply_options_default(this: &mut z_query_reply_options_t) { + *this = z_query_reply_options_t { + encoding: null_mut(), + attachment: null_mut(), + }; } /// Creates a Queryable for the given key expression. /// /// Parameters: /// session: The zenoh session. -/// keyexpr: The key expression the Queryable will reply to. +/// key_expr: The key expression the Queryable will reply to. /// callback: The callback function that will be called each time a matching query is received. /// options: Options for the queryable. /// @@ -212,31 +142,34 @@ pub extern "C" fn z_query_reply_options_default() -> z_query_reply_options_t { #[allow(clippy::missing_safety_doc)] #[no_mangle] pub extern "C" fn z_declare_queryable( - session: z_session_t, - keyexpr: z_keyexpr_t, + this: *mut MaybeUninit, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, callback: &mut z_owned_closure_query_t, - options: Option<&z_queryable_options_t>, -) -> z_owned_queryable_t { + options: Option<&mut z_queryable_options_t>, +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); let mut closure = z_owned_closure_query_t::empty(); std::mem::swap(&mut closure, callback); - - let session = match session.upgrade() { - Some(s) => s, - None => { - log::error!("{}", LOG_INVALID_SESSION); - return None.into(); - } - }; + let session = session.transmute_ref(); + let keyexpr = key_expr.transmute_ref(); let mut builder = session.declare_queryable(keyexpr); if let Some(options) = options { builder = builder.complete(options.complete); } - builder - .callback(move |query| z_closure_query_call(&closure, &z_query_t::from(&query))) - .res_sync() - .map_err(|e| log::error!("{}", e)) - .ok() - .into() + let queryable = builder + .callback(move |query| z_closure_query_call(&closure, query.transmute_handle())) + .res_sync(); + match queryable { + Ok(q) => { + Inplace::init(this, Some(q)); + errors::Z_OK + } + Err(e) => { + log::error!("{}", e); + errors::Z_EGENERIC + } + } } /// Undeclares a `z_owned_queryable_t`, droping it and invalidating it for doube-drop safety. @@ -245,21 +178,20 @@ pub extern "C" fn z_declare_queryable( /// qable: The :c:type:`z_owned_queryable_t` to undeclare. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_undeclare_queryable(qable: &mut z_owned_queryable_t) -> i8 { - if let Some(qable) = qable.take() { +pub extern "C" fn z_undeclare_queryable(qable: &mut z_owned_queryable_t) -> errors::z_error_t { + if let Some(qable) = qable.transmute_mut().extract().take() { if let Err(e) = qable.undeclare().res_sync() { log::error!("{}", e); - return e.errno().get(); + return errors::Z_EGENERIC; } } - 0 + errors::Z_OK } /// Returns ``true`` if `qable` is valid. -#[allow(clippy::missing_safety_doc)] #[no_mangle] pub extern "C" fn z_queryable_check(qable: &z_owned_queryable_t) -> bool { - qable.as_ref().is_some() + qable.transmute_ref().is_some() } /// Send a reply to a query. @@ -271,103 +203,94 @@ pub extern "C" fn z_queryable_check(qable: &z_owned_queryable_t) -> bool { /// /// Parameters: /// query: The query to reply to. -/// key: The key of this reply. +/// key_expr: The key of this reply. /// payload: The value of this reply. -/// len: The length of the value of this reply. /// options: The options of this reply. +/// +/// The payload and all owned options fields are consumed upon function return. #[allow(clippy::missing_safety_doc)] #[no_mangle] pub unsafe extern "C" fn z_query_reply( - query: &z_query_t, - key: z_keyexpr_t, - payload: *const u8, - len: usize, - options: Option<&z_query_reply_options_t>, -) -> i8 { - let Some(query) = query.as_ref() else { - log::error!("Called `z_query_reply` with invalidated `query`"); - return i8::MIN; - }; - if let Some(key) = &*key { - let mut s = Sample::new( - key.clone().into_owned(), - std::slice::from_raw_parts(payload, len), - ); - if let Some(o) = options { - s.encoding = o.encoding.into(); - if z_attachment_check(&o.attachment) { - let mut attachment_builder = AttachmentBuilder::new(); - z_attachment_iterate( - o.attachment, - insert_in_attachment_builder, - &mut attachment_builder as *mut AttachmentBuilder as *mut c_void, - ); - s = s.with_attachment(attachment_builder.build()); - }; + query: z_loaned_query_t, + key_expr: z_loaned_keyexpr_t, + payload: &mut z_owned_bytes_t, + options: Option<&mut z_query_reply_options_t>, +) -> errors::z_error_t { + let query = query.transmute_ref(); + let key_expr = key_expr.transmute_ref(); + + let payload = match payload.transmute_mut().extract() { + Some(p) => p, + None => { + log::debug!("Attempted to reply with a null payload"); + return errors::Z_EINVAL; } - if let Err(e) = query.reply(Ok(s)).res_sync() { - log::error!("{}", e); - return e.errno().get(); + }; + + let mut reply = query.reply(key_expr, payload); + if let Some(options) = options { + if !options.encoding.is_null() { + let encoding = unsafe { *options.encoding }.transmute_mut().extract(); + reply = reply.encoding(encoding); + }; + if !options.attachment.is_null() { + let attachment = unsafe { *options.attachment }.transmute_mut().extract(); + reply = reply.attachment(attachment); } - 0 - } else { - i8::MIN } + + if let Err(e) = reply.res_sync() { + log::error!("{}", e); + return errors::Z_EGENERIC; + } + errors::Z_OK } /// Get a query's key by aliasing it. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_query_keyexpr(query: &z_query_t) -> z_keyexpr_t { - let Some(query) = query.as_ref() else { - return z_keyexpr_t::null(); - }; - query.key_expr().borrowing_clone().into() +pub extern "C" fn z_query_keyexpr(query: &z_loaned_query_t) -> &z_loaned_keyexpr_t { + query.transmute_ref().key_expr().transmute_handle() } /// Get a query's `value selector `_ by aliasing it. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_query_parameters(query: &z_query_t) -> z_bytes_t { - let Some(query) = query.as_ref() else { - return z_bytes_t::empty(); - }; - let complement = query.parameters(); - z_bytes_t { - start: complement.as_ptr(), - len: complement.len(), - } +pub unsafe extern "C" fn z_query_parameters( + query: &z_loaned_query_t, + parameters: *mut MaybeUninit, +) { + let query = query.transmute_ref(); + let params = query.parameters().as_str(); + unsafe { z_view_slice_wrap(parameters, params.as_ptr(), params.len()) }; } -/// Get a query's `payload value `_ by aliasing it. +/// Checks if query contains a payload value. +#[no_mangle] +pub extern "C" fn z_query_has_value(query: &z_loaned_query_t) -> bool { + query.transmute_ref().value().is_some() +} + +/// Gets a query's `payload value `_ by aliasing it. /// /// **WARNING: This API has been marked as unstable: it works as advertised, but it may change in a future release.** -#[allow(clippy::missing_safety_doc)] +/// Before calling this funciton, the user must ensure that `z_query_has_value` returns true. #[no_mangle] -pub unsafe extern "C" fn z_query_value(query: &z_query_t) -> z_value_t { - match query.as_ref().and_then(|q| q.value()) { - Some(value) => { - #[allow(mutable_transmutes)] - if let std::borrow::Cow::Owned(payload) = value.payload.contiguous() { - unsafe { std::mem::transmute::<_, &mut Value>(value).payload = payload.into() } - } - value.into() - } - None => (&Value::empty()).into(), - } +pub extern "C" fn z_query_value(query: &z_loaned_query_t) -> &z_loaned_value_t { + query + .transmute_ref() + .value() + .expect("Query does not contain a value") + .transmute_handle() } -/// Returns the attachment to the query by aliasing. +/// Gets the attachment to the query by aliasing. /// -/// `z_check(return_value) == false` if there was no attachment to the query. -#[allow(clippy::missing_safety_doc)] +/// Returns NULL if query does not contain an attachment. #[no_mangle] -pub unsafe extern "C" fn z_query_attachment(query: &z_query_t) -> z_attachment_t { - match query.as_ref().and_then(|q| q.attachment()) { - Some(attachment) => z_attachment_t { - data: attachment as *const _ as *mut c_void, - iteration_driver: Some(attachment_iteration_driver), - }, - None => z_attachment_null(), +pub extern "C" fn z_query_attachment(query: &z_loaned_query_t) -> *const z_loaned_bytes_t { + match query.transmute_ref().attachment() { + Some(attachment) => attachment.transmute_handle() as *const _, + None => null(), } } diff --git a/src/querying_subscriber.rs b/src/querying_subscriber.rs index cdec44f0f..c1d180ecc 100644 --- a/src/querying_subscriber.rs +++ b/src/querying_subscriber.rs @@ -12,72 +12,49 @@ // ZettaScale Zenoh team, // +use std::mem::MaybeUninit; +use std::ptr::null; + +use crate::errors; +use crate::transmute::unwrap_ref_unchecked; +use crate::transmute::Inplace; +use crate::transmute::TransmuteFromHandle; +use crate::transmute::TransmuteIntoHandle; +use crate::transmute::TransmuteRef; +use crate::transmute::TransmuteUninitPtr; +use crate::z_loaned_keyexpr_t; +use crate::z_owned_closure_sample_t; +use crate::z_reliability_t; +use crate::{ + z_closure_sample_call, z_get_options_t, z_loaned_query_target_default, z_loaned_query_target_t, + z_loaned_session_t, z_query_consolidation_none, z_query_consolidation_t, zcu_locality_default, + zcu_locality_t, zcu_reply_keyexpr_default, zcu_reply_keyexpr_t, +}; use zenoh::prelude::sync::SyncResolve; -use zenoh::prelude::KeyExpr; use zenoh::prelude::SessionDeclarations; -use zenoh::prelude::SplitBuffer; +use zenoh::session::Session; +use zenoh::subscriber::Reliability; use zenoh_ext::*; -use zenoh_protocol::core::SubInfo; -use zenoh_util::core::zresult::ErrNo; - -use crate::{ - impl_guarded_transmute, z_closure_sample_call, z_get_options_t, z_keyexpr_t, - z_owned_closure_sample_t, z_query_consolidation_none, z_query_consolidation_t, - z_query_target_default, z_query_target_t, z_reliability_t, z_sample_t, z_session_t, - zcu_locality_default, zcu_locality_t, zcu_reply_keyexpr_default, zcu_reply_keyexpr_t, - LOG_INVALID_SESSION, -}; - -pub struct FetchingSubscriberWrapper { - fetching_subscriber: zenoh_ext::FetchingSubscriber<'static, ()>, - session: z_session_t, -} -type FetchingSubscriber = Option>; -//type FetchingSubscriber = Option>>; - -/// An owned zenoh querying subscriber. Destroying the subscriber cancels the subscription. -/// -/// Like most `ze_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. -/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. -/// -/// Like all `ze_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. -#[repr(C)] -pub struct ze_owned_querying_subscriber_t([usize; 1]); - -impl_guarded_transmute!(FetchingSubscriber, ze_owned_querying_subscriber_t); - -#[repr(C)] -#[allow(non_camel_case_types)] -pub struct ze_querying_subscriber_t<'a>(&'a ze_owned_querying_subscriber_t); -impl<'a> AsRef for ze_querying_subscriber_t<'a> { - fn as_ref(&self) -> &FetchingSubscriber { - self.0 - } -} - -impl ze_owned_querying_subscriber_t { - pub fn new(sub: zenoh_ext::FetchingSubscriber<'static, ()>, session: z_session_t) -> Self { - Some(Box::new(FetchingSubscriberWrapper { - fetching_subscriber: sub, - session, - })) - .into() - } - pub fn null() -> Self { - None.into() - } -} +use crate::opaque_types::ze_loaned_querying_subscriber_t; +use crate::opaque_types::ze_owned_querying_subscriber_t; +decl_transmute_owned!( + Option<(zenoh_ext::FetchingSubscriber<'static, ()>, &'static Session)>, + ze_owned_querying_subscriber_t +); +decl_transmute_handle!( + (zenoh_ext::FetchingSubscriber<'static, ()>, &'static Session), + ze_loaned_querying_subscriber_t +); /// Constructs a null safe-to-drop value of 'ze_owned_querying_subscriber_t' type #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn ze_querying_subscriber_null() -> ze_owned_querying_subscriber_t { - ze_owned_querying_subscriber_t::null() +pub extern "C" fn ze_querying_subscriber_null( + this: *mut MaybeUninit, +) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); } /// Represents the set of options that can be applied to a querying subscriber, @@ -87,8 +64,8 @@ pub extern "C" fn ze_querying_subscriber_null() -> ze_owned_querying_subscriber_ /// z_reliability_t reliability: The subscription reliability. /// zcu_locality_t allowed_origin: The restriction for the matching publications that will be /// receive by this subscriber. -/// z_keyexpr_t query_selector: The selector to be used for queries. -/// z_query_target_t query_target: The target to be used for queries. +/// z_loaned_keyexpr_t query_selector: The selector to be used for queries. +/// z_loaned_query_target_t query_target: The target to be used for queries. /// z_query_consolidation_t query_consolidation: The consolidation mode to be used for queries. /// zcu_reply_keyexpr_t query_accept_replies: The accepted replies for queries. /// uint64_t query_timeout_ms: The timeout to be used for queries. @@ -97,8 +74,8 @@ pub extern "C" fn ze_querying_subscriber_null() -> ze_owned_querying_subscriber_ pub struct ze_querying_subscriber_options_t { reliability: z_reliability_t, allowed_origin: zcu_locality_t, - query_selector: z_keyexpr_t, - query_target: z_query_target_t, + query_selector: *const z_loaned_keyexpr_t, + query_target: z_loaned_query_target_t, query_consolidation: z_query_consolidation_t, query_accept_replies: zcu_reply_keyexpr_t, query_timeout_ms: u64, @@ -106,23 +83,25 @@ pub struct ze_querying_subscriber_options_t { /// Constructs the default value for :c:type:`ze_querying_subscriber_options_t`. #[no_mangle] -pub extern "C" fn ze_querying_subscriber_options_default() -> ze_querying_subscriber_options_t { - ze_querying_subscriber_options_t { - reliability: SubInfo::default().reliability.into(), +pub extern "C" fn ze_querying_subscriber_options_default( + this: &mut ze_querying_subscriber_options_t, +) { + *this = ze_querying_subscriber_options_t { + reliability: Reliability::DEFAULT.into(), allowed_origin: zcu_locality_default(), - query_selector: z_keyexpr_t::null(), - query_target: z_query_target_default(), + query_selector: null(), + query_target: z_loaned_query_target_default(), query_consolidation: z_query_consolidation_none(), query_accept_replies: zcu_reply_keyexpr_default(), query_timeout_ms: 0, - } + }; } /// Declares a Querying Subscriber for a given key expression. /// /// Parameters: -/// z_session_t session: The zenoh session. -/// z_keyexpr_t keyexpr: The key expression to subscribe. +/// z_loaned_session_t session: The zenoh session. +/// z_loaned_keyexpr_t keyexpr: The key expression to subscribe. /// z_owned_closure_sample_t callback: The callback function that will be called each time a data matching the subscribed expression is received. /// ze_querying_subscriber_options_t options: Additional options for the querying subscriber. /// @@ -152,60 +131,47 @@ pub extern "C" fn ze_querying_subscriber_options_default() -> ze_querying_subscr #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn ze_declare_querying_subscriber( - session: z_session_t, - keyexpr: z_keyexpr_t, + this: *mut MaybeUninit, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, callback: &mut z_owned_closure_sample_t, - options: Option<&ze_querying_subscriber_options_t>, -) -> ze_owned_querying_subscriber_t { + options: Option<&mut ze_querying_subscriber_options_t>, +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); let mut closure = z_owned_closure_sample_t::empty(); std::mem::swap(callback, &mut closure); - - match session.upgrade() { - Some(s) => { - let mut sub = s.declare_subscriber(keyexpr).querying(); - if let Some(options) = options { - sub = sub - .reliability(options.reliability.into()) - .allowed_origin(options.allowed_origin.into()) - .query_target(options.query_target.into()) - .query_consolidation(options.query_consolidation) - .query_accept_replies(options.query_accept_replies.into()); - if options.query_selector.is_some() { - let query_selector = options - .query_selector - .as_ref() - .map(|s| s.clone().into_owned()); - if let Some(query_selector) = query_selector { - sub = sub.query_selector(query_selector) - } - } - if options.query_timeout_ms != 0 { - sub = sub - .query_timeout(std::time::Duration::from_millis(options.query_timeout_ms)); - } - } - match sub - .callback(move |sample| { - let payload = sample.payload.contiguous(); - let owner = match payload { - std::borrow::Cow::Owned(v) => zenoh::buffers::ZBuf::from(v), - _ => sample.payload.clone(), - }; - let sample = z_sample_t::new(&sample, &owner); - z_closure_sample_call(&closure, &sample) - }) - .res() - { - Ok(sub) => ze_owned_querying_subscriber_t::new(sub, session), - Err(e) => { - log::debug!("{}", e); - ze_owned_querying_subscriber_t::null() - } - } + let session = session.transmute_ref(); + let mut sub = session + .declare_subscriber(key_expr.transmute_ref()) + .querying(); + if let Some(options) = options { + sub = sub + .reliability(options.reliability.into()) + .allowed_origin(options.allowed_origin.into()) + .query_target(options.query_target.into()) + .query_consolidation(options.query_consolidation) + .query_accept_replies(options.query_accept_replies.into()); + if !options.query_selector.is_null() { + let query_selector = unsafe { *options.query_selector }.transmute_ref().clone(); + sub = sub.query_selector(query_selector) + } + if options.query_timeout_ms != 0 { + sub = sub.query_timeout(std::time::Duration::from_millis(options.query_timeout_ms)); + } + } + let sub = sub.callback(move |sample| { + let sample = sample.transmute_handle(); + z_closure_sample_call(&closure, sample); + }); + match sub.res() { + Ok(sub) => { + Inplace::init(this, Some((sub, session))); + errors::Z_OK } - None => { - log::debug!("{}", LOG_INVALID_SESSION); - ze_owned_querying_subscriber_t::null() + Err(e) => { + log::debug!("{}", e); + Inplace::empty(this); + errors::Z_EGENERIC } } } @@ -215,69 +181,64 @@ pub unsafe extern "C" fn ze_declare_querying_subscriber( #[allow(clippy::missing_safety_doc)] #[no_mangle] pub unsafe extern "C" fn ze_querying_subscriber_get( - sub: ze_querying_subscriber_t, - selector: z_keyexpr_t, + sub: &ze_loaned_querying_subscriber_t, + selector: &z_loaned_keyexpr_t, options: Option<&z_get_options_t>, -) -> i8 { +) -> errors::z_error_t { unsafe impl Sync for z_get_options_t {} - - if let Some(sub) = sub.as_ref() { - match sub.session.upgrade() { - Some(s) => { - if let Err(e) = sub - .fetching_subscriber - .fetch({ - let selector = KeyExpr::try_from(selector).unwrap(); - move |cb| match options { - Some(options) => s - .get(selector) - .target(options.target.into()) - .consolidation(options.consolidation) - .timeout(std::time::Duration::from_millis(options.timeout_ms)) - .callback(cb) - .res_sync(), - None => s.get(selector).callback(cb).res_sync(), - } - }) - .res() - { - log::debug!("{}", e); - return -1; - } + let sub = sub.transmute_ref(); + let session = sub.1; + let selector = selector.transmute_ref().clone(); + if let Err(e) = sub + .0 + .fetch({ + move |cb| match options { + Some(options) => session + .get(selector) + .target(options.target.into()) + .consolidation(options.consolidation) + .timeout(std::time::Duration::from_millis(options.timeout_ms)) + .callback(cb) + .res_sync(), + None => session.get(selector).callback(cb).res_sync(), } - None => { - log::debug!("{}", LOG_INVALID_SESSION); - return -1; - } - } + }) + .res() + { + log::debug!("{}", e); + return errors::Z_EGENERIC; } - 0 + errors::Z_OK } /// Undeclares the given :c:type:`ze_owned_querying_subscriber_t`, droping it and invalidating it for double-drop safety. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn ze_undeclare_querying_subscriber(sub: &mut ze_owned_querying_subscriber_t) -> i8 { - if let Some(s) = sub.take() { - if let Err(e) = s.fetching_subscriber.close().res_sync() { - log::warn!("{}", e); - return e.errno().get(); +pub extern "C" fn ze_undeclare_querying_subscriber( + this: &mut ze_owned_querying_subscriber_t, +) -> errors::z_error_t { + if let Some(s) = this.transmute_mut().extract().take() { + if let Err(e) = s.0.close().res_sync() { + log::error!("{}", e); + return errors::Z_EGENERIC; } } - 0 + errors::Z_OK } -/// Returns ``true`` if `sub` is valid. +/// Returns ``true`` if `this` is valid. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn ze_querying_subscriber_check(sub: &ze_owned_querying_subscriber_t) -> bool { - sub.as_ref().is_some() +pub extern "C" fn ze_querying_subscriber_check(this: &ze_owned_querying_subscriber_t) -> bool { + this.transmute_ref().is_some() } -/// Returns a :c:type:`ze_querying_subscriber_loan` loaned from `p`. +/// Returns a :c:type:`ze_querying_subscriber_loan` loaned from `this`. #[no_mangle] pub extern "C" fn ze_querying_subscriber_loan( - p: &ze_owned_querying_subscriber_t, -) -> ze_querying_subscriber_t { - ze_querying_subscriber_t(p) + this: &ze_owned_querying_subscriber_t, +) -> &ze_loaned_querying_subscriber_t { + let this = this.transmute_ref(); + let this = unwrap_ref_unchecked(this); + this.transmute_handle() } diff --git a/src/scouting.rs b/src/scouting.rs index c7dd80be7..7a7931301 100644 --- a/src/scouting.rs +++ b/src/scouting.rs @@ -12,12 +12,15 @@ // ZettaScale Zenoh team, // use crate::{ - z_closure_hello_call, z_config_check, z_config_default, z_config_null, z_config_t, z_id_t, - z_owned_closure_hello_t, z_owned_config_t, zc_init_logger, CopyableToCArray, + errors::{self, Z_OK}, + transmute::{Inplace, TransmuteRef}, + z_closure_hello_call, z_config_check, z_config_clone, z_config_default, z_config_drop, + z_config_null, z_id_t, z_loaned_config_t, z_owned_closure_hello_t, z_owned_config_t, + zc_init_logger, CopyableToCArray, }; use async_std::task; use libc::{c_char, c_uint, c_ulong, size_t}; -use std::{ffi::CString, os::raw::c_void}; +use std::{ffi::CString, mem::MaybeUninit, os::raw::c_void}; use zenoh::scouting::Hello; use zenoh_protocol::core::{whatami::WhatAmIMatcher, WhatAmI}; use zenoh_util::core::AsyncResolve; @@ -39,9 +42,9 @@ pub struct z_owned_str_array_t { #[allow(clippy::missing_safety_doc)] #[no_mangle] pub unsafe extern "C" fn z_str_array_drop(strs: &mut z_owned_str_array_t) { - let locators = Vec::from_raw_parts(strs.val as *mut *const c_char, strs.len, strs.len); - for locator in locators { - std::mem::drop(CString::from_raw(locator as *mut c_char)); + let vals = Vec::from_raw_parts(strs.val as *mut *const c_char, strs.len, strs.len); + for val in vals { + std::mem::drop(CString::from_raw(val as *mut c_char)); } strs.val = std::ptr::null_mut(); strs.len = 0; @@ -64,11 +67,8 @@ pub struct z_str_array_t { /// Returns a :c:type:`z_str_array_t` loaned from :c:type:`z_owned_str_array_t`. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_str_array_loan(strs: &z_owned_str_array_t) -> z_str_array_t { - z_str_array_t { - val: strs.val as *const _, - len: strs.len, - } +pub unsafe extern "C" fn z_str_array_loan(strs: &z_owned_str_array_t) -> &z_str_array_t { + std::mem::transmute(strs) } /// A zenoh-allocated hello message returned by a zenoh entity to a scout message sent with `z_scout`. /// @@ -143,26 +143,23 @@ pub unsafe extern "C" fn z_hello_drop(hello: &mut z_owned_hello_t) { /// Returns a :c:type:`z_hello_t` loaned from :c:type:`z_owned_hello_t`. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_hello_loan(hello: &z_owned_hello_t) -> z_hello_t { - z_hello_t { - whatami: hello._whatami, - pid: hello._pid, - locators: z_str_array_loan(&hello._locators), - } +pub unsafe extern "C" fn z_hello_loan(hello: &z_owned_hello_t) -> &z_hello_t { + std::mem::transmute(hello) } /// Constructs a gravestone value for hello, useful to steal one from a callback #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_hello_null() -> z_owned_hello_t { - z_owned_hello_t { +pub unsafe extern "C" fn z_hello_null(this: *mut MaybeUninit) { + let h = z_owned_hello_t { _whatami: 0, - _pid: z_id_t { id: [0; 16] }, + _pid: [0; 16].into(), _locators: z_owned_str_array_t { val: std::ptr::null_mut(), len: 0, }, - } + }; + (*this).write(h); } impl Drop for z_owned_hello_t { fn drop(&mut self) { @@ -188,32 +185,52 @@ pub const DEFAULT_SCOUTING_TIMEOUT: c_ulong = 1000; #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_scouting_config_null() -> z_owned_scouting_config_t { - z_owned_scouting_config_t { - _config: z_config_null(), +pub unsafe extern "C" fn z_scouting_config_null(this: *mut MaybeUninit) { + let mut _config = MaybeUninit::::uninit(); + z_config_null(&mut _config as *mut MaybeUninit); + let _config = _config.assume_init(); + + let config = z_owned_scouting_config_t { + _config, zc_timeout_ms: DEFAULT_SCOUTING_TIMEOUT, zc_what: DEFAULT_SCOUTING_WHAT, - } + }; + (*this).write(config); } #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_scouting_config_default() -> z_owned_scouting_config_t { - z_owned_scouting_config_t { - _config: z_config_default(), +pub unsafe extern "C" fn z_scouting_config_default( + this: *mut MaybeUninit, +) { + let mut _config = MaybeUninit::::uninit(); + z_config_default(&mut _config as *mut MaybeUninit); + let _config = _config.assume_init(); + + let config = z_owned_scouting_config_t { + _config, zc_timeout_ms: DEFAULT_SCOUTING_TIMEOUT, zc_what: DEFAULT_SCOUTING_WHAT, - } + }; + (*this).write(config); } #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_scouting_config_from(config: z_config_t) -> z_owned_scouting_config_t { - z_owned_scouting_config_t { - _config: config.as_ref().clone().into(), +pub unsafe extern "C" fn z_scouting_config_from( + this: *mut MaybeUninit, + config: &z_loaned_config_t, +) { + let mut dst = MaybeUninit::uninit(); + z_config_clone(config, &mut dst as *mut _); + let _config = dst.assume_init(); + + let config = z_owned_scouting_config_t { + _config, zc_timeout_ms: DEFAULT_SCOUTING_TIMEOUT, zc_what: DEFAULT_SCOUTING_WHAT, - } + }; + (*this).write(config); } #[no_mangle] @@ -225,7 +242,7 @@ pub extern "C" fn z_scouting_config_check(config: &z_owned_scouting_config_t) -> #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn z_scouting_config_drop(config: &mut z_owned_scouting_config_t) { - std::mem::drop(std::mem::replace(config, z_scouting_config_null())); + z_config_drop(&mut config._config) } /// Scout for routers and/or peers. @@ -241,21 +258,24 @@ pub extern "C" fn z_scouting_config_drop(config: &mut z_owned_scouting_config_t) pub extern "C" fn z_scout( config: &mut z_owned_scouting_config_t, callback: &mut z_owned_closure_hello_t, -) -> i8 { +) -> errors::z_error_t { if cfg!(feature = "logger-autoinit") { zc_init_logger(); } - let config = std::mem::replace(config, z_scouting_config_null()); let what = WhatAmIMatcher::try_from(config.zc_what).unwrap_or(WhatAmI::Router | WhatAmI::Peer); #[allow(clippy::unnecessary_cast)] // Required for multi-target let timeout = config.zc_timeout_ms as u64; - let mut config = config._config; - let config = config.as_mut().take().expect("invalid config"); + let config = match config._config.transmute_mut().extract().take() { + Some(c) => c, + None => { + return errors::Z_EINVAL; + } + }; let mut closure = z_owned_closure_hello_t::empty(); std::mem::swap(&mut closure, callback); task::block_on(async move { - let scout = zenoh::scout(what, *config) + let scout = zenoh::scout(what, config) .callback(move |h| { let mut hello = h.into(); z_closure_hello_call(&closure, &mut hello) @@ -266,7 +286,7 @@ pub extern "C" fn z_scout( async_std::task::sleep(std::time::Duration::from_millis(timeout)).await; std::mem::drop(scout); }); - 0 + Z_OK } /// Converts the kind of zenoh entity into a string. @@ -281,10 +301,10 @@ pub extern "C" fn z_scout( #[no_mangle] pub extern "C" fn z_whatami_to_str(whatami: u8, buf: *mut c_char, len: usize) -> i8 { if buf.is_null() || len == 0 { - return -1; + return errors::Z_EINVAL; } match WhatAmIMatcher::try_from(whatami) { - Err(_) => -1, + Err(_) => errors::Z_EINVAL, Ok(w) => { let s = w.to_str(); let res = s.copy_to_c_array(buf as *mut c_void, len - 1); diff --git a/src/session.rs b/src/session.rs index 2caab85ea..68a182e36 100644 --- a/src/session.rs +++ b/src/session.rs @@ -12,92 +12,91 @@ // ZettaScale Zenoh team, // -use crate::{config::*, impl_guarded_transmute, zc_init_logger}; -use std::sync::{Arc, Weak}; +#[cfg(all(feature = "unstable", feature = "shared-memory"))] +use crate::client_storage::z_shared_memory_client_storage_t; +use crate::transmute::{ + unwrap_ref_unchecked, Inplace, TransmuteIntoHandle, TransmuteRef, TransmuteUninitPtr, +}; +use crate::{errors, z_owned_config_t, zc_init_logger}; +use std::mem::MaybeUninit; +use std::sync::Arc; +use zenoh::core::ErrNo; use zenoh::prelude::sync::SyncResolve; -use zenoh::Session; -use zenoh_util::core::zresult::ErrNo; +use zenoh::session::Session; -/// An owned zenoh session. -/// -/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. -/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. -/// -/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. -#[repr(C)] -pub struct z_owned_session_t(usize); - -impl_guarded_transmute!(Option>, z_owned_session_t); - -impl AsRef>> for z_session_t { - fn as_ref(&self) -> &Option> { - unsafe { std::mem::transmute(self) } - } -} - -impl z_session_t { - pub fn upgrade(&self) -> Option> { - self.as_ref().as_ref().and_then(Weak::upgrade) - } -} - -impl From>> for z_session_t { - fn from(val: Option>) -> Self { - unsafe { std::mem::transmute(val) } - } -} - -impl z_owned_session_t { - pub fn new(session: Arc) -> Self { - Some(session).into() - } - pub fn null() -> Self { - None::>.into() - } -} +use crate::opaque_types::z_owned_session_t; +decl_transmute_owned!(Option>, z_owned_session_t); /// A loaned zenoh session. -#[allow(non_camel_case_types)] -#[derive(Clone, Copy)] -#[repr(C)] -pub struct z_session_t(usize); +use crate::opaque_types::z_loaned_session_t; +decl_transmute_handle!(Session, z_loaned_session_t); -/// Returns a :c:type:`z_session_t` loaned from `s`. +/// Returns a :c:type:`z_loaned_session_t` loaned from `s`. /// /// This handle doesn't increase the refcount of the session, but does allow to do so with `zc_session_rcinc`. /// /// # Safety -/// The returned `z_session_t` aliases `z_owned_session_t`'s internal allocation, +/// The returned `z_loaned_session_t` aliases `z_owned_session_t`'s internal allocation, /// attempting to use it after all owned handles to the session (including publishers, queryables and subscribers) /// have been destroyed is UB (likely SEGFAULT) #[no_mangle] -pub extern "C" fn z_session_loan(s: &z_owned_session_t) -> z_session_t { - match s.as_ref() { - Some(s) => { - let mut weak = Arc::downgrade(s); - unsafe { std::ptr::drop_in_place(&mut weak) }; - Some(weak) - } - None => None, - } - .into() +pub extern "C" fn z_session_loan(this: &z_owned_session_t) -> &z_loaned_session_t { + let this = this.transmute_ref(); + let this = unwrap_ref_unchecked(this); + let this = this.as_ref(); + this.transmute_handle() } /// Constructs a null safe-to-drop value of 'z_owned_session_t' type #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_session_null() -> z_owned_session_t { - z_owned_session_t::null() +pub extern "C" fn z_session_null(this: *mut MaybeUninit) { + Inplace::empty(this.transmute_uninit_ptr()); } /// Opens a zenoh session. Should the session opening fail, `z_check` ing the returned value will return `false`. +/// Config value is always consumed upon function return. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_open(config: &mut z_owned_config_t) -> z_owned_session_t { +pub extern "C" fn z_open( + this: *mut MaybeUninit, + config: &mut z_owned_config_t, +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); + if cfg!(feature = "logger-autoinit") { + zc_init_logger(); + } + let config = match config.transmute_mut().extract() { + Some(c) => c, + None => { + log::error!("Config not provided"); + Inplace::empty(this); + return errors::Z_EINVAL; + } + }; + match zenoh::open(config).res() { + Ok(s) => { + Inplace::init(this, Some(Arc::new(s))); + errors::Z_OK + } + Err(e) => { + log::error!("Error opening session: {}", e); + Inplace::empty(this); + errors::Z_ENETWORK + } + } +} + +/// Opens a zenoh session. Should the session opening fail, `z_check` ing the returned value will return `false`. +#[allow(clippy::missing_safety_doc)] +#[no_mangle] +#[cfg(all(feature = "unstable", feature = "shared-memory"))] +pub extern "C" fn z_open_with_shm_clients( + config: &mut z_owned_config_t, + shm_clients: z_shared_memory_client_storage_t, +) -> z_owned_session_t { + use crate::GuardedTransmute; + if cfg!(feature = "logger-autoinit") { zc_init_logger(); } @@ -109,7 +108,10 @@ pub extern "C" fn z_open(config: &mut z_owned_config_t) -> z_owned_session_t { return z_owned_session_t::null(); } }; - match zenoh::open(*config).res() { + match zenoh::open(*config) + .with_shm_clients(shm_clients.transmute_ref().clone()) + .res() + { Ok(s) => z_owned_session_t::new(Arc::new(s)), Err(e) => { log::error!("Error opening session: {}", e); @@ -121,8 +123,8 @@ pub extern "C" fn z_open(config: &mut z_owned_config_t) -> z_owned_session_t { /// Returns ``true`` if `session` is valid. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_session_check(session: &z_owned_session_t) -> bool { - session.as_ref().is_some() +pub extern "C" fn z_session_check(this: &z_owned_session_t) -> bool { + this.transmute_ref().is_some() } /// Closes a zenoh session. This drops and invalidates `session` for double-drop safety. @@ -131,9 +133,10 @@ pub extern "C" fn z_session_check(session: &z_owned_session_t) -> bool { /// Returns the remaining reference count of the session otherwise, saturating at i8::MAX. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_close(session: &mut z_owned_session_t) -> i8 { +pub extern "C" fn z_close(session: &mut z_owned_session_t) -> errors::z_error_t { + let session = session.transmute_mut(); let Some(s) = session.take() else { - return 0; + return errors::Z_OK; }; let s = match Arc::try_unwrap(s) { Ok(s) => s, @@ -143,13 +146,22 @@ pub extern "C" fn z_close(session: &mut z_owned_session_t) -> i8 { }; match s.close().res() { Err(e) => e.errno().get(), - Ok(_) => 0, + Ok(_) => errors::Z_OK, } } /// Increments the session's reference count, returning a new owning handle. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn zc_session_rcinc(session: z_session_t) -> z_owned_session_t { - session.as_ref().as_ref().and_then(|s| s.upgrade()).into() +pub extern "C" fn zc_session_clone( + dst: *mut MaybeUninit, + src: &z_owned_session_t, +) -> errors::z_error_t { + // session.as_ref().as_ref().and_then(|s| s.upgrade()).into() + let dst = dst.transmute_uninit_ptr(); + let Some(src) = src.transmute_ref() else { + return errors::Z_EINVAL; + }; + Inplace::init(dst, Some(src.clone())); + errors::Z_OK } diff --git a/src/shm.rs b/src/shm.rs index 50f8b7236..cb90ed65f 100644 --- a/src/shm.rs +++ b/src/shm.rs @@ -23,7 +23,7 @@ use zenoh::{ shm::{SharedMemoryBuf, SharedMemoryManager}, }; -use crate::{z_session_t, zc_owned_payload_t, zc_payload_null}; +use crate::{z_loaned_session_t, z_owned_bytes_t, z_bytes_null}; #[repr(C)] pub struct zc_owned_shm_manager_t(usize); @@ -51,7 +51,7 @@ impl zc_owned_shm_manager_t { #[no_mangle] pub extern "C" fn zc_shm_manager_new( - session: z_session_t, + session: z_loaned_session_t, id: *const c_char, size: usize, ) -> zc_owned_shm_manager_t { @@ -179,10 +179,10 @@ pub extern "C" fn zc_shmbuf_null() -> zc_owned_shmbuf_t { /// Constructs an owned payload from an owned SHM buffer. #[no_mangle] -pub extern "C" fn zc_shmbuf_into_payload(buf: &mut zc_owned_shmbuf_t) -> zc_owned_payload_t { +pub extern "C" fn zc_shmbuf_into_payload(buf: &mut zc_owned_shmbuf_t) -> z_owned_bytes_t { match buf.get_mut().take() { Some(buf) => ZBuf::from(buf).try_into().unwrap_or_default(), - None => zc_payload_null(), + None => z_bytes_null(), } } diff --git a/src/shm/client/mod.rs b/src/shm/client/mod.rs new file mode 100644 index 000000000..eab20733e --- /dev/null +++ b/src/shm/client/mod.rs @@ -0,0 +1,16 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +pub mod shared_memory_client; +pub mod shared_memory_segment; diff --git a/src/shm/client/shared_memory_client.rs b/src/shm/client/shared_memory_client.rs new file mode 100644 index 000000000..9cd84a00c --- /dev/null +++ b/src/shm/client/shared_memory_client.rs @@ -0,0 +1,156 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// +use std::{mem::MaybeUninit, sync::Arc}; + +use libc::c_void; +use zenoh::{ + shm::{ + client::{ + shared_memory_client::SharedMemoryClient, shared_memory_segment::SharedMemorySegment, + }, + common::types::SegmentID, + }, + Result, +}; +use zenoh_util::core::bail; + +use crate::{ + common::types::z_segment_id_t, decl_rust_new_owned_type, impl_guarded_transmute, + prepare_memory_to_init, zc_threadsafe_context_t, DroppableContext, GuardedTransmute, + ThreadsafeContext, +}; + +use super::shared_memory_segment::{z_shared_memory_segment_t, DynamicSharedMemorySegment}; + +/// A callbacks for SharedMemoryClient +#[derive(Debug)] +#[repr(C)] +pub struct zc_shared_memory_client_callbacks_t { + attach_fn: unsafe extern "C" fn( + *mut c_void, + z_segment_id_t, + &mut MaybeUninit, + ) -> bool, +} + +/// A loaned SharedMemoryClient +#[allow(non_camel_case_types)] +#[derive(Clone, Copy)] +#[repr(C)] +pub struct z_shared_memory_client_t<'a>(&'a z_owned_shared_memory_client_t); + +/// An owned SharedMemoryClient +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_owned_shared_memory_client_t([u64; 2]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_owned_shared_memory_client_t([u64; 2]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_owned_shared_memory_client_t([u64; 2]); + +decl_rust_new_owned_type!( + zenoh:(Option>), + c:(z_owned_shared_memory_client_t) +); + +#[derive(Debug)] +pub struct DynamicSharedMemoryClient { + context: ThreadsafeContext, + callbacks: zc_shared_memory_client_callbacks_t, +} + +impl DynamicSharedMemoryClient { + pub fn new(context: ThreadsafeContext, callbacks: zc_shared_memory_client_callbacks_t) -> Self { + Self { context, callbacks } + } +} + +impl SharedMemoryClient for DynamicSharedMemoryClient { + fn attach(&self, segment: SegmentID) -> Result> { + let mut segment_data = MaybeUninit::uninit(); + unsafe { + match (self.callbacks.attach_fn)(self.context.get(), segment, &mut segment_data) { + true => Ok(Arc::new(DynamicSharedMemorySegment::new( + segment_data.assume_init(), + ))), + false => bail!("C Callback returned error"), + } + } + } +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_owned_shared_memory_client_new( + out_client: &mut z_owned_shared_memory_client_t, + context: zc_threadsafe_context_t, + callbacks: zc_shared_memory_client_callbacks_t, +) -> i32 { + let out_client = prepare_memory_to_init!(out_client); + + let client = Arc::new(DynamicSharedMemoryClient::new( + context.transmute(), + callbacks, + )) as Arc; + + *out_client = Some(client); + 0 +} + +/// Initializes a null memory for safe-to-drop value of 'z_owned_shared_memory_client_t' type +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_owned_shared_memory_client_null( + out_client: &mut z_owned_shared_memory_client_t, +) { + out_client.make_null(); +} + +/// Returns ``true`` if `client` is valid. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_owned_shared_memory_client_check( + client: &z_owned_shared_memory_client_t, +) -> bool { + client.check() +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_owned_shared_memory_client_delete( + out_client: &mut z_owned_shared_memory_client_t, +) { + out_client.delete(); +} + +/// Returns a :c:type:`z_shared_memory_client_t` loaned from `client`. +#[no_mangle] +pub extern "C" fn z_owned_shared_memory_client_loan( + client: &z_owned_shared_memory_client_t, +) -> z_shared_memory_client_t { + z_shared_memory_client_t(client) +} diff --git a/src/shm/client/shared_memory_segment.rs b/src/shm/client/shared_memory_segment.rs new file mode 100644 index 000000000..3dc51bdbc --- /dev/null +++ b/src/shm/client/shared_memory_segment.rs @@ -0,0 +1,69 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use std::sync::atomic::AtomicPtr; + +use libc::c_void; +use zenoh::{ + shm::{client::shared_memory_segment::SharedMemorySegment, common::types::ChunkID}, + Result, +}; +use zenoh_util::core::zerror; + +use crate::{ + common::types::z_chunk_id_t, zc_threadsafe_context_t, DroppableContext, GuardedTransmute, + ThreadsafeContext, +}; + +/// A callbacks for SharedMemorySegment +#[derive(Debug)] +#[repr(C)] +pub struct zc_shared_memory_segment_callbacks_t { + map_fn: unsafe extern "C" fn(*mut c_void, z_chunk_id_t) -> *mut u8, +} + +/// A SharedMemorySegment +#[derive(Debug)] +#[repr(C)] +pub struct z_shared_memory_segment_t { + context: zc_threadsafe_context_t, + callbacks: zc_shared_memory_segment_callbacks_t, +} + +#[derive(Debug)] +pub struct DynamicSharedMemorySegment { + context: ThreadsafeContext, + callbacks: zc_shared_memory_segment_callbacks_t, +} + +impl DynamicSharedMemorySegment { + pub fn new(data: z_shared_memory_segment_t) -> Self { + Self { + context: data.context.transmute(), + callbacks: data.callbacks, + } + } +} + +impl SharedMemorySegment for DynamicSharedMemorySegment { + fn map(&self, chunk: ChunkID) -> Result> { + unsafe { + let cb_result = (self.callbacks.map_fn)(self.context.get(), chunk); + cb_result + .as_mut() + .map(|p| AtomicPtr::new(p)) + .ok_or_else(|| zerror!("C callback returned null pointer!").into()) + } + } +} diff --git a/src/shm/client_storage/mod.rs b/src/shm/client_storage/mod.rs new file mode 100644 index 000000000..f01452632 --- /dev/null +++ b/src/shm/client_storage/mod.rs @@ -0,0 +1,201 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use zenoh::{ + shm::{ + client::shared_memory_client::SharedMemoryClient, client_storage::GLOBAL_CLIENT_STORAGE, + common::types::ProtocolID, + }, + SharedMemoryClientStorage, +}; + +use crate::{ + access_owned_memory, client::shared_memory_client::z_owned_shared_memory_client_t, + common::types::z_protocol_id_t, decl_rust_new_owned_type, impl_guarded_transmute, + move_owned_memory, prepare_memory_to_init, GuardedTransmute, +}; +use std::sync::Arc; + +/// A loaned list of SharedMemoryClients +#[allow(non_camel_case_types)] +#[derive(Clone, Copy)] +#[repr(C)] +pub struct zc_loaned_shared_memory_client_list_t<'a>(&'a zc_owned_shared_memory_client_list_t); + +/// An owned list of SharedMemoryClients +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct zc_owned_shared_memory_client_list_t([u64; 3]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct zc_owned_shared_memory_client_list_t([u64; 4]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct zc_owned_shared_memory_client_list_t([u64; 3]); + +decl_rust_new_owned_type!( + zenoh:(Option)>>), + c:(zc_owned_shared_memory_client_list_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_shared_memory_client_list_new( + out: &mut zc_owned_shared_memory_client_list_t, +) -> i32 { + let out = prepare_memory_to_init!(out); + *out = Some(Vec::default()); + 0 +} + +/// Initializes a null memory for safe-to-drop value of 'zc_owned_shared_memory_client_list_t' type +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn zc_shared_memory_client_list_null( + val: &mut zc_owned_shared_memory_client_list_t, +) { + val.make_null(); +} + +/// Returns ``true`` if `val` is valid. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn zc_shared_memory_client_list_check( + val: &zc_owned_shared_memory_client_list_t, +) -> bool { + val.check() +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_shared_memory_client_list_delete( + val: &mut zc_owned_shared_memory_client_list_t, +) { + val.delete(); +} + +/// Returns a :c:type:`zc_loaned_shared_memory_client_list_t` loaned from `list`. +#[no_mangle] +pub extern "C" fn zc_shared_memory_client_list_loan( + list: &zc_owned_shared_memory_client_list_t, +) -> zc_loaned_shared_memory_client_list_t { + zc_loaned_shared_memory_client_list_t(list) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn zc_shared_memory_client_list_add_client( + id: z_protocol_id_t, + client: &mut z_owned_shared_memory_client_t, + list: zc_loaned_shared_memory_client_list_t, +) -> i32 { + access_owned_memory!(list.0, |list: &mut Vec<_>| { + move_owned_memory!(client, |client| { + list.push((id, client)); + 0 + }) + }) +} + +/// A SharedMemoryClientStorage. +#[repr(C)] +pub struct z_owned_shared_memory_client_storage_t(usize); + +decl_rust_new_owned_type!( + zenoh:(Option>), + c:(z_owned_shared_memory_client_storage_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_client_storage_global( + out: &mut z_owned_shared_memory_client_storage_t, +) -> i32 { + let out = prepare_memory_to_init!(out); + *out = Some(GLOBAL_CLIENT_STORAGE.clone()); + 0 +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_owned_shared_memory_client_storage_new( + out: &mut z_owned_shared_memory_client_storage_t, + clients: zc_loaned_shared_memory_client_list_t, +) -> i32 { + let out = prepare_memory_to_init!(out); + access_owned_memory!(clients.0, |list: &Vec<_>| { + if list.is_empty() { + return -5; // todo: E_ARGUMENT_INVALID + } + let builder = SharedMemoryClientStorage::builder().with_clients(list); + *out = Some(Arc::new(builder.build())); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_owned_shared_memory_client_storage_new_with_default_client_set( + out: &mut z_owned_shared_memory_client_storage_t, + clients: zc_loaned_shared_memory_client_list_t, +) -> i32 { + let out = prepare_memory_to_init!(out); + access_owned_memory!(clients.0, |list: &Vec<_>| { + if list.is_empty() { + return -5; // todo: E_ARGUMENT_INVALID + } + let builder = SharedMemoryClientStorage::builder() + .with_default_client_set() + .with_clients(list); + *out = Some(Arc::new(builder.build())); + 0 + }) +} + +/// Initializes a null memory for safe-to-drop value of 'z_owned_shared_memory_client_storage_t' type +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_shared_memory_client_storage_null( + out: &mut z_owned_shared_memory_client_storage_t, +) { + out.make_null(); +} + +/// Returns ``true`` if `storage` is valid. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_shared_memory_client_storage_check( + storage: &z_owned_shared_memory_client_storage_t, +) -> bool { + storage.check() +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_client_storage_deref( + storage: &mut z_owned_shared_memory_client_storage_t, +) { + storage.delete(); +} diff --git a/src/shm/common/mod.rs b/src/shm/common/mod.rs new file mode 100644 index 000000000..222c7286b --- /dev/null +++ b/src/shm/common/mod.rs @@ -0,0 +1,15 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +pub mod types; diff --git a/src/shm/common/types.rs b/src/shm/common/types.rs new file mode 100644 index 000000000..4b4d7518f --- /dev/null +++ b/src/shm/common/types.rs @@ -0,0 +1,27 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +/// Unique protocol identifier. +/// Here is a contract: it is up to user to make sure that incompatible SharedMemoryClient +/// and SharedMemoryProviderBackend implementations will never use the same ProtocolID +#[allow(non_camel_case_types)] +pub type z_protocol_id_t = u32; + +/// Unique segment identifier +#[allow(non_camel_case_types)] +pub type z_segment_id_t = u32; + +/// Chunk id within it's segment +#[allow(non_camel_case_types)] +pub type z_chunk_id_t = u32; diff --git a/src/shm/mod.rs b/src/shm/mod.rs new file mode 100644 index 000000000..6eeb0122a --- /dev/null +++ b/src/shm/mod.rs @@ -0,0 +1,19 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +pub mod client; +pub mod client_storage; +pub mod common; +pub mod protocol_implementations; +pub mod provider; diff --git a/src/shm/protocol_implementations/mod.rs b/src/shm/protocol_implementations/mod.rs new file mode 100644 index 000000000..df92f6353 --- /dev/null +++ b/src/shm/protocol_implementations/mod.rs @@ -0,0 +1,15 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +pub mod posix; diff --git a/src/shm/protocol_implementations/posix/mod.rs b/src/shm/protocol_implementations/posix/mod.rs new file mode 100644 index 000000000..9f984d20b --- /dev/null +++ b/src/shm/protocol_implementations/posix/mod.rs @@ -0,0 +1,17 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +pub mod posix_shared_memory_client; +pub mod posix_shared_memory_provider; +pub mod protocol_id; diff --git a/src/shm/protocol_implementations/posix/posix_shared_memory_client.rs b/src/shm/protocol_implementations/posix/posix_shared_memory_client.rs new file mode 100644 index 000000000..debbc9420 --- /dev/null +++ b/src/shm/protocol_implementations/posix/posix_shared_memory_client.rs @@ -0,0 +1,36 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use std::sync::Arc; + +use zenoh::shm::{ + client::shared_memory_client::SharedMemoryClient, + protocol_implementations::posix::posix_shared_memory_client::PosixSharedMemoryClient, +}; + +use crate::{ + client::shared_memory_client::z_owned_shared_memory_client_t, prepare_memory_to_init, + GuardedTransmute, +}; + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_posix_shared_memory_client_new( + out_client: &mut z_owned_shared_memory_client_t, +) -> i32 { + let out_client = prepare_memory_to_init!(out_client); + let client = Arc::new(PosixSharedMemoryClient) as Arc; + *out_client = Some(client); + 0 +} diff --git a/src/shm/protocol_implementations/posix/posix_shared_memory_provider.rs b/src/shm/protocol_implementations/posix/posix_shared_memory_provider.rs new file mode 100644 index 000000000..f8fc1df2d --- /dev/null +++ b/src/shm/protocol_implementations/posix/posix_shared_memory_provider.rs @@ -0,0 +1,81 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use std::mem::MaybeUninit; + +use zenoh::shm::{ + protocol_implementations::posix::{ + posix_shared_memory_provider_backend::PosixSharedMemoryProviderBackend, + protocol_id::POSIX_PROTOCOL_ID, + }, + provider::shared_memory_provider::{ + SharedMemoryProvider, SharedMemoryProviderBuilder, StaticProtocolID, + }, +}; + +use crate::{ + decl_rust_copy_type, impl_guarded_transmute, provider::types::z_memory_layout_t, + GuardedTransmute, +}; + +/// An owned SharedMemoryProvider with POSIX backend +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_posix_shared_memory_provider_t([u64; 26]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_posix_shared_memory_provider_t([u64; 26]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_posix_shared_memory_provider_t([u64; 26]); + +type PosixSharedMemoryProvider = + SharedMemoryProvider, PosixSharedMemoryProviderBackend>; + +decl_rust_copy_type!( + zenoh:(PosixSharedMemoryProvider), + c:(z_posix_shared_memory_provider_t)); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_posix_shared_memory_provider_new( + layout: &z_memory_layout_t, + out_provider: &mut MaybeUninit, +) -> bool { + match PosixSharedMemoryProviderBackend::builder() + .with_layout(layout.transmute_ref()) + .res() + { + Ok(backend) => { + let provider = SharedMemoryProviderBuilder::builder() + .protocol_id::() + .backend(backend) + .res(); + out_provider.write(provider.transmute()); + true + } + Err(e) => { + log::error!("{}", e); + false + } + } +} diff --git a/src/shm/protocol_implementations/posix/protocol_id.rs b/src/shm/protocol_implementations/posix/protocol_id.rs new file mode 100644 index 000000000..f893138f7 --- /dev/null +++ b/src/shm/protocol_implementations/posix/protocol_id.rs @@ -0,0 +1,17 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +// Protocol identifier to use when creating SharedMemoryProvider +//#[repr(C)] +//pub const POSIX_PROTOCOL_ID: ProtocolID = 0; diff --git a/src/shm/provider/alloc_layout.rs b/src/shm/provider/alloc_layout.rs new file mode 100644 index 000000000..b6d1f88a8 --- /dev/null +++ b/src/shm/provider/alloc_layout.rs @@ -0,0 +1,150 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use zenoh::shm::provider::shared_memory_provider::{ + AllocLayout, BlockOn, Deallocate, Defragment, DynamicProtocolID, GarbageCollect, JustAlloc, +}; + +use crate::{ + access_owned_memory, decl_rust_new_owned_type, impl_guarded_transmute, prepare_memory_to_init, + Context, GuardedTransmute, +}; + +use super::{ + shared_memory_provider_backend::DynamicSharedMemoryProviderBackend, + types::z_owned_buf_alloc_result_t, +}; + +/// A loaned non-thread-safe SharedMemoryProvider's AllocLayout +#[allow(non_camel_case_types)] +#[derive(Clone, Copy)] +#[repr(C)] +pub struct z_alloc_layout_t<'a>(&'a z_owned_alloc_layout_t); + +/// A non-thread-safe SharedMemoryProvider's AllocLayout +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_owned_alloc_layout_t([u64; 4]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_owned_alloc_layout_t([u64; 14]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_owned_alloc_layout_t([u64; 14]); + +decl_rust_new_owned_type!( + zenoh:(Option>>), + c:(z_owned_alloc_layout_t) +); + +/// Initializes a null memory for safe-to-drop value of 'z_owned_alloc_layout_t' type +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_alloc_layout_null(out: &mut z_owned_alloc_layout_t) { + out.make_null(); +} + +/// Returns ``true`` if `layout` is valid. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_alloc_layout_check(layout: &z_owned_alloc_layout_t) -> bool { + layout.check() +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_delete(layout: &mut z_owned_alloc_layout_t) { + layout.delete(); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_alloc( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout.alloc().with_policy::().res(); + *out_buffer = Some(buffer); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_alloc_gc( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout.alloc().with_policy::().res(); + *out_buffer = Some(buffer); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_alloc_gc_defrag( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout + .alloc() + .with_policy::>() + .res(); + *out_buffer = Some(buffer); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_alloc_gc_defrag_dealloc( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout + .alloc() + .with_policy::>>() + .res(); + *out_buffer = Some(buffer); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_alloc_gc_defrag_blocking( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout + .alloc() + .with_policy::>>() + .res(); + *out_buffer = Some(buffer); + 0 + }) +} diff --git a/src/shm/provider/alloc_layout_threadsafe.rs b/src/shm/provider/alloc_layout_threadsafe.rs new file mode 100644 index 000000000..0b41ab9f8 --- /dev/null +++ b/src/shm/provider/alloc_layout_threadsafe.rs @@ -0,0 +1,183 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use libc::c_void; +use zenoh::shm::provider::shared_memory_provider::{ + AllocLayout, BlockOn, Deallocate, Defragment, DynamicProtocolID, GarbageCollect, JustAlloc, +}; + +use crate::{ + access_owned_memory, decl_rust_new_owned_type, impl_guarded_transmute, prepare_memory_to_init, + zc_threadsafe_context_t, DroppableContext, GuardedTransmute, ThreadsafeContext, +}; + +use super::{ + shared_memory_provider_backend::DynamicSharedMemoryProviderBackend, + types::z_owned_buf_alloc_result_t, +}; + +/// A loaned thread-safe SharedMemoryProvider's AllocLayout +#[allow(non_camel_case_types)] +#[derive(Clone, Copy)] +#[repr(C)] +pub struct z_alloc_layout_threadsafe_t<'a>(&'a z_owned_alloc_layout_threadsafe_t); + +/// A thread-safe SharedMemoryProvider's AllocLayout +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_owned_alloc_layout_threadsafe_t([u64; 4]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_owned_alloc_layout_threadsafe_t([u64; 4]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_owned_alloc_layout_threadsafe_t([u64; 4]); + +decl_rust_new_owned_type!( + zenoh:(Option>>), + c:(z_owned_alloc_layout_threadsafe_t) +); + +/// Initializes a null memory for safe-to-drop value of 'z_owned_alloc_layout_threadsafe_t' type +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_alloc_layout_threadsafe_null( + out: &mut z_owned_alloc_layout_threadsafe_t, +) { + out.make_null(); +} + +/// Returns ``true`` if `layout` is valid. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_alloc_layout_threadsafe_check( + layout: &z_owned_alloc_layout_threadsafe_t, +) -> bool { + layout.check() +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_threadsafe_delete( + layout: &mut z_owned_alloc_layout_threadsafe_t, +) { + layout.delete(); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_threadsafe_alloc( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_threadsafe_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout.alloc().with_policy::().res(); + *out_buffer = Some(buffer); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_threadsafe_alloc_gc( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_threadsafe_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout.alloc().with_policy::().res(); + *out_buffer = Some(buffer); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_threadsafe_alloc_gc_defrag( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_threadsafe_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout + .alloc() + .with_policy::>() + .res(); + *out_buffer = Some(buffer); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_threadsafe_alloc_gc_defrag_dealloc( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_threadsafe_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout + .alloc() + .with_policy::>>() + .res(); + *out_buffer = Some(buffer); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_threadsafe_alloc_gc_defrag_blocking( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_threadsafe_t, +) -> i32 { + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + let out_buffer = prepare_memory_to_init!(out_buffer); + let buffer = layout + .alloc() + .with_policy::>>() + .res(); + *out_buffer = Some(buffer); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_layout_threadsafe_alloc_gc_defrag_async( + out_buffer: &mut z_owned_buf_alloc_result_t, + layout: z_alloc_layout_threadsafe_t, + + result_context: zc_threadsafe_context_t, + result_callback: unsafe extern "C" fn(*mut c_void, &mut z_owned_buf_alloc_result_t), +) -> i32 { + let transmuted_out_buffer = prepare_memory_to_init!(out_buffer); + //todo: this should be ported to tokio with executor argument support + access_owned_memory!(layout.0, |layout: &AllocLayout<_, _>| { + async_std::task::spawn(async move { + let buffer = layout + .alloc() + .with_policy::>>() + .res_async() + .await; + *transmuted_out_buffer = Some(buffer); + let result_context = result_context.transmute(); + (result_callback)(result_context.get(), out_buffer); + }); + 0 + }) +} diff --git a/src/shm/provider/chunk.rs b/src/shm/provider/chunk.rs new file mode 100644 index 000000000..d9ca0fdb3 --- /dev/null +++ b/src/shm/provider/chunk.rs @@ -0,0 +1,102 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use std::mem::MaybeUninit; + +use zenoh::shm::provider::chunk::{AllocatedChunk, ChunkDescriptor}; + +use crate::{ + common::types::{z_chunk_id_t, z_segment_id_t}, + decl_rust_copy_type, impl_guarded_transmute, GuardedTransmute, +}; + +#[repr(C)] +pub struct zc_chunk_descriptor_data_t { + segment: z_segment_id_t, + chunk: z_chunk_id_t, + len: usize, +} + +/// A ChunkDescriptor +#[repr(C)] +pub struct z_chunk_descriptor_t(zc_chunk_descriptor_data_t); + +decl_rust_copy_type!( + zenoh:(ChunkDescriptor), + c:(z_chunk_descriptor_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_chunk_descriptor_new( + data: zc_chunk_descriptor_data_t, + out_val: &mut MaybeUninit, +) { + let descriptor = ChunkDescriptor::new(data.segment, data.chunk, data.len); + out_val.write(descriptor.transmute()); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_chunk_descriptor_unwrap( + descriptor: z_chunk_descriptor_t, +) -> zc_chunk_descriptor_data_t { + let descriptor = descriptor.transmute(); + zc_chunk_descriptor_data_t { + segment: descriptor.segment, + chunk: descriptor.chunk, + len: descriptor.len, + } +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_chunk_descriptor_delete(val: z_chunk_descriptor_t) { + let _ = val.transmute(); +} + +/// An AllocatedChunk. +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_allocated_chunk_t([u64; 3]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_allocated_chunk_t([u64; 4]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_allocated_chunk_t([u64; 3]); + +decl_rust_copy_type!( + zenoh:(AllocatedChunk), + c:(z_allocated_chunk_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_allocated_chunk_new( + descriptor: z_chunk_descriptor_t, + data: *mut u8, + out_val: &mut MaybeUninit, +) { + let chunk = AllocatedChunk::new(descriptor.transmute(), data.into()); + out_val.write(chunk.transmute()); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_allocated_chunk_delete(val: z_allocated_chunk_t) { + let _ = val.transmute(); +} diff --git a/src/shm/provider/mod.rs b/src/shm/provider/mod.rs new file mode 100644 index 000000000..c8d0abdff --- /dev/null +++ b/src/shm/provider/mod.rs @@ -0,0 +1,23 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +pub mod alloc_layout; +pub mod alloc_layout_threadsafe; +pub mod chunk; +pub mod shared_memory_provider; +pub mod shared_memory_provider_backend; +pub mod shared_memory_provider_impl; +pub mod shared_memory_provider_threadsafe; +pub mod types; +pub mod zsliceshm; diff --git a/src/shm/provider/shared_memory_provider.rs b/src/shm/provider/shared_memory_provider.rs new file mode 100644 index 000000000..13efc559c --- /dev/null +++ b/src/shm/provider/shared_memory_provider.rs @@ -0,0 +1,187 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use std::mem::MaybeUninit; + +use zenoh::shm::provider::shared_memory_provider::{ + AllocPolicy, BlockOn, Deallocate, Defragment, DynamicProtocolID, GarbageCollect, JustAlloc, + SharedMemoryProvider, SharedMemoryProviderBuilder, +}; + +use crate::{ + common::types::z_protocol_id_t, decl_rust_copy_type, impl_guarded_transmute, zc_context_t, + Context, GuardedTransmute, +}; + +use super::{ + chunk::z_allocated_chunk_t, + shared_memory_provider_backend::{ + zc_shared_memory_provider_backend_callbacks_t, DynamicSharedMemoryProviderBackend, + }, + shared_memory_provider_impl::alloc, + types::{z_alloc_alignment_t, z_owned_buf_alloc_result_t}, + zsliceshm::z_owned_slice_shm_mut_t, +}; + +/// A non-thread-safe SharedMemoryProvider specialization +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_shared_memory_provider_t([u64; 14]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_shared_memory_provider_t([u64; 14]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_shared_memory_provider_t([u64; 14]); + +decl_rust_copy_type!( + zenoh:(SharedMemoryProvider>), + c:(z_shared_memory_provider_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_new( + id: z_protocol_id_t, + context: zc_context_t, + callbacks: zc_shared_memory_provider_backend_callbacks_t, + out_provider: &mut MaybeUninit, +) { + let backend = DynamicSharedMemoryProviderBackend::new(context.transmute(), callbacks); + let provider = SharedMemoryProviderBuilder::builder() + .dynamic_protocol_id(id) + .backend(backend) + .res(); + out_provider.write(provider.transmute()); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_delete(provider: z_shared_memory_provider_t) { + let _ = provider.transmute(); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_alloc( + provider: &z_shared_memory_provider_t, + size: usize, + alignment: z_alloc_alignment_t, + out_buffer: &mut MaybeUninit, +) -> bool { + alloc_inner::(provider, size, alignment, out_buffer) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_alloc_gc( + provider: &z_shared_memory_provider_t, + size: usize, + alignment: z_alloc_alignment_t, + out_buffer: &mut MaybeUninit, +) -> bool { + alloc_inner::(provider, size, alignment, out_buffer) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_alloc_gc_defrag( + provider: &z_shared_memory_provider_t, + size: usize, + alignment: z_alloc_alignment_t, + out_buffer: &mut MaybeUninit, +) -> bool { + alloc_inner::>(provider, size, alignment, out_buffer) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_alloc_gc_defrag_dealloc( + provider: &z_shared_memory_provider_t, + size: usize, + alignment: z_alloc_alignment_t, + out_buffer: &mut MaybeUninit, +) -> bool { + alloc_inner::>>( + provider, size, alignment, out_buffer, + ) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_alloc_gc_defrag_blocking( + provider: &z_shared_memory_provider_t, + size: usize, + alignment: z_alloc_alignment_t, + out_buffer: &mut MaybeUninit, +) -> bool { + alloc_inner::>>(provider, size, alignment, out_buffer) +} + +#[allow(clippy::missing_safety_doc)] +unsafe fn alloc_inner( + provider: &z_loaned_shared_memory_provider_t, + size: usize, + alignment: z_alloc_alignment_t, + out_buffer: &mut MaybeUninit, +) -> bool { + alloc::(provider, size, alignment, out_buffer) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_defragment( + provider: &z_shared_memory_provider_t, +) -> usize { + provider.transmute_ref().defragment() +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_garbage_collect( + provider: &z_shared_memory_provider_t, +) -> usize { + provider.transmute_ref().garbage_collect() +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_available( + provider: &z_shared_memory_provider_t, +) -> usize { + provider.transmute_ref().available() +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_map( + provider: &z_shared_memory_provider_t, + allocated_chunk: z_allocated_chunk_t, + len: usize, + out_buffer: &mut MaybeUninit, +) -> bool { + let provider = provider.transmute_ref(); + match provider.map(allocated_chunk.transmute(), len) { + Ok(buffer) => { + out_buffer.write(Some(buffer).transmute()); + true + } + Err(e) => { + log::error!("{e}"); + false + } + } +} diff --git a/src/shm/provider/shared_memory_provider_backend.rs b/src/shm/provider/shared_memory_provider_backend.rs new file mode 100644 index 000000000..7e4b28b14 --- /dev/null +++ b/src/shm/provider/shared_memory_provider_backend.rs @@ -0,0 +1,109 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use std::fmt::Debug; + +use libc::c_void; +use zenoh::shm::provider::{ + chunk::ChunkDescriptor, + shared_memory_provider_backend::SharedMemoryProviderBackend, + types::{ChunkAllocResult, MemoryLayout}, +}; +use zenoh::Result; +use zenoh_util::core::bail; + +use crate::{DroppableContext, GuardedTransmute}; + +use super::{ + chunk::z_chunk_descriptor_t, + types::{z_chunk_alloc_result_t, z_memory_layout_t}, +}; + +/// A callbacks for SharedMemoryProviderBackend +#[derive(Debug)] +#[repr(C)] +pub struct zc_shared_memory_provider_backend_callbacks_t { + alloc_fn: + unsafe extern "C" fn(*mut c_void, *const z_memory_layout_t, *mut z_chunk_alloc_result_t), + free_fn: unsafe extern "C" fn(*mut c_void, *const z_chunk_descriptor_t), + defragment_fn: unsafe extern "C" fn(*mut c_void) -> usize, + available_fn: unsafe extern "C" fn(*mut c_void) -> usize, + layout_for_fn: + unsafe extern "C" fn(*mut c_void, *const z_memory_layout_t, *mut z_memory_layout_t) -> bool, + drop_fn: unsafe extern "C" fn(*mut c_void), +} + +#[derive(Debug)] +pub struct DynamicSharedMemoryProviderBackend +where + TContext: DroppableContext, +{ + context: TContext, + callbacks: zc_shared_memory_provider_backend_callbacks_t, +} + +impl DynamicSharedMemoryProviderBackend +where + TContext: DroppableContext, +{ + pub fn new( + context: TContext, + callbacks: zc_shared_memory_provider_backend_callbacks_t, + ) -> Self { + Self { context, callbacks } + } +} + +impl SharedMemoryProviderBackend for DynamicSharedMemoryProviderBackend +where + TContext: DroppableContext, +{ + fn alloc(&self, layout: &MemoryLayout) -> ChunkAllocResult { + let mut result = std::mem::MaybeUninit::uninit(); + unsafe { + (self.callbacks.alloc_fn)( + self.context.get(), + layout.transmute_ref(), + result.as_mut_ptr(), + ); + result.assume_init().transmute() + } + } + + fn free(&self, chunk: &ChunkDescriptor) { + unsafe { (self.callbacks.free_fn)(self.context.get(), chunk.transmute_ref()) }; + } + + fn defragment(&self) -> usize { + unsafe { (self.callbacks.defragment_fn)(self.context.get()) } + } + + fn available(&self) -> usize { + unsafe { (self.callbacks.available_fn)(self.context.get()) } + } + + fn layout_for(&self, layout: MemoryLayout) -> Result { + let mut result = std::mem::MaybeUninit::uninit(); + unsafe { + match (self.callbacks.layout_for_fn)( + self.context.get(), + layout.transmute_ref(), + result.as_mut_ptr(), + ) { + true => Ok(result.assume_init().transmute()), + false => bail!("{:?}: unsupported layout: {:?}", self, layout), + } + } + } +} diff --git a/src/shm/provider/shared_memory_provider_impl.rs b/src/shm/provider/shared_memory_provider_impl.rs new file mode 100644 index 000000000..90d981752 --- /dev/null +++ b/src/shm/provider/shared_memory_provider_impl.rs @@ -0,0 +1,82 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use std::mem::MaybeUninit; + +use zenoh::shm::provider::shared_memory_provider::{ + AllocPolicy, AsyncAllocPolicy, DynamicProtocolID, SharedMemoryProvider, +}; + +use crate::{DroppableContext, GuardedTransmute, ThreadsafeContext}; + +use super::{ + shared_memory_provider_backend::DynamicSharedMemoryProviderBackend, + types::{z_alloc_alignment_t, z_owned_buf_alloc_result_t}, +}; + +#[allow(clippy::missing_safety_doc)] +pub(crate) unsafe fn alloc( + provider: &SharedMemoryProvider< + DynamicProtocolID, + DynamicSharedMemoryProviderBackend, + >, + size: usize, + alignment: z_alloc_alignment_t, + out_buffer: &mut MaybeUninit, +) -> i32 { + match provider + .alloc_layout() + .size(size) + .alignment(alignment.transmute()) + .res() + { + Ok(layout) => { + let result = layout.alloc().with_policy::().res(); + out_buffer.write(Some(result).transmute()); + 0 + } + Err(e) => { + log::error!("{e}"); + -5 // todo: E_ARGUMENT_INVALID + } + } +} + +#[allow(clippy::missing_safety_doc)] +pub(crate) async fn alloc_async( + provider: &SharedMemoryProvider< + DynamicProtocolID, + DynamicSharedMemoryProviderBackend, + >, + size: usize, + alignment: z_alloc_alignment_t, + out_buffer: &mut MaybeUninit, +) -> i32 { + match provider + .alloc_layout() + .size(size) + .alignment(alignment.transmute()) + .res() + { + Ok(layout) => { + let result = layout.alloc().with_policy::().res_async().await; + out_buffer.write(Some(result).transmute()); + 0 + } + Err(e) => { + log::error!("{e}"); + -5 // todo: E_ARGUMENT_INVALID + } + } +} diff --git a/src/shm/provider/shared_memory_provider_threadsafe.rs b/src/shm/provider/shared_memory_provider_threadsafe.rs new file mode 100644 index 000000000..e00c677c4 --- /dev/null +++ b/src/shm/provider/shared_memory_provider_threadsafe.rs @@ -0,0 +1,297 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use std::mem::MaybeUninit; + +use libc::c_void; +use zenoh::shm::provider::shared_memory_provider::{ + AllocPolicy, BlockOn, Deallocate, Defragment, DynamicProtocolID, GarbageCollect, JustAlloc, + SharedMemoryProvider, SharedMemoryProviderBuilder, +}; + +use crate::{ + access_loaned_memory, access_owned_memory, common::types::z_protocol_id_t, + decl_rust_new_owned_type, impl_guarded_transmute, zc_threadsafe_context_t, DroppableContext, + GuardedTransmute, ThreadsafeContext, +}; + +use super::{ + alloc_layout_threadsafe::z_owned_alloc_layout_threadsafe_t, + chunk::z_allocated_chunk_t, + shared_memory_provider_backend::{ + zc_shared_memory_provider_backend_callbacks_t, DynamicSharedMemoryProviderBackend, + }, + shared_memory_provider_impl::{alloc, alloc_async}, + types::{z_alloc_alignment_t, z_owned_buf_alloc_result_t}, + zsliceshm::z_owned_slice_shm_mut_t, +}; + +/// A loaned SharedMemoryProvider thread-safe specialization +#[allow(non_camel_case_types)] +#[derive(Clone, Copy)] +#[repr(C)] +pub struct z_loaned_shared_memory_provider_threadsafe_t<'a>( + &'a z_owned_shared_memory_provider_threadsafe_t, +); + +/// An owned SharedMemoryProvider thread-safe specialization +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_owned_shared_memory_provider_threadsafe_t([u64; 14]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_owned_shared_memory_provider_threadsafe_t([u64; 14]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_owned_shared_memory_provider_threadsafe_t([u64; 14]); + +decl_rust_new_owned_type!( + zenoh:(Option>>), + c:(z_owned_shared_memory_provider_threadsafe_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_new( + out_provider: &mut MaybeUninit, + id: z_protocol_id_t, + context: zc_threadsafe_context_t, + callbacks: zc_shared_memory_provider_backend_callbacks_t, +) { + let backend = DynamicSharedMemoryProviderBackend::new(context.transmute(), callbacks); + let provider = SharedMemoryProviderBuilder::builder() + .dynamic_protocol_id(id) + .backend(backend) + .res(); + out_provider.write(Some(provider).transmute()); +} + +/// Initializes a null memory for safe-to-drop value of 'z_shared_memory_provider_threadsafe_' type +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_shared_memory_provider_threadsafe_null( + val: &mut z_owned_shared_memory_provider_threadsafe_t, +) { + val.make_null(); +} + +/// Returns ``true`` if `val` is valid. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_shared_memory_provider_threadsafe_check( + val: &z_owned_shared_memory_provider_threadsafe_t, +) -> bool { + val.check() +} + +/// Returns a :c:type:`z_loaned_shared_memory_provider_threadsafe_t` loaned from `val`. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_shared_memory_provider_threadsafe_loan( + val: &z_owned_shared_memory_provider_threadsafe_t, +) -> z_loaned_shared_memory_provider_threadsafe_t { + z_loaned_shared_memory_provider_threadsafe_t(val) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_slice_shm_mut_delete(val: &mut z_owned_slice_shm_mut_t) { + val.delete(); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_alloc_layout_new( + out_layout: &mut MaybeUninit, + provider: z_loaned_shared_memory_provider_threadsafe_t, + size: usize, + alignment: z_alloc_alignment_t, +) -> i32 { + access_loaned_memory!(provider, |val: &mut SharedMemoryProvider<_, _>| { + match val + .alloc_layout() + .size(size) + .alignment(alignment.transmute()) + .res() + { + Ok(layout) => { + out_layout.write(Some(layout).transmute()); + 0 + } + Err(e) => { + log::error!("{e}"); + return -5; // todo: E_ARGUMENT_INVALID + } + } + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_alloc( + out_buffer: &mut MaybeUninit, + provider: z_loaned_shared_memory_provider_threadsafe_t, + size: usize, + alignment: z_alloc_alignment_t, +) -> i32 { + alloc_inner::(provider, size, alignment, out_buffer) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_alloc_gc( + out_buffer: &mut MaybeUninit, + provider: z_loaned_shared_memory_provider_threadsafe_t, + size: usize, + alignment: z_alloc_alignment_t, +) -> i32 { + alloc_inner::(provider, size, alignment, out_buffer) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_alloc_gc_defrag( + out_buffer: &mut MaybeUninit, + provider: z_loaned_shared_memory_provider_threadsafe_t, + size: usize, + alignment: z_alloc_alignment_t, +) -> i32 { + alloc_inner::>(provider, size, alignment, out_buffer) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_alloc_gc_defrag_dealloc( + out_buffer: &mut MaybeUninit, + provider: z_loaned_shared_memory_provider_threadsafe_t, + size: usize, + alignment: z_alloc_alignment_t, +) -> i32 { + alloc_inner::>>( + provider, size, alignment, out_buffer, + ) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_alloc_gc_defrag_blocking( + out_buffer: &mut MaybeUninit, + provider: z_loaned_shared_memory_provider_threadsafe_t, + size: usize, + alignment: z_alloc_alignment_t, +) -> i32 { + alloc_inner::>>(provider, size, alignment, out_buffer) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_alloc_gc_defrag_async( + out_buffer: &mut MaybeUninit, + provider: z_loaned_shared_memory_provider_threadsafe_t, + size: usize, + alignment: z_alloc_alignment_t, + result_context: zc_threadsafe_context_t, + result_callback: unsafe extern "C" fn( + *mut c_void, + &mut MaybeUninit, + i32, + ), +) { + let result_context = result_context.transmute(); + //todo: this should be ported to tokio with executor argument support + async_std::task::spawn(async move { + let result = match provider.0.transmute_ref() { + Some(val) => { + alloc_async::>>(val, size, alignment, out_buffer) + .await + } + None => -2, // todo: error type E_ACCESS_NULL + }; + + (result_callback)(result_context.get(), out_buffer, result); + }); +} + +#[allow(clippy::missing_safety_doc)] +unsafe fn alloc_inner( + provider: z_loaned_shared_memory_provider_threadsafe_t, + size: usize, + alignment: z_alloc_alignment_t, + out_buffer: &mut MaybeUninit, +) -> i32 { + access_loaned_memory!(provider, |val| { + alloc::(val, size, alignment, out_buffer) + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_defragment( + provider: z_loaned_shared_memory_provider_threadsafe_t, +) -> i32 { + access_loaned_memory!(provider, |val: &mut SharedMemoryProvider<_, _>| { + let _ = val.defragment(); + 0 + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_garbage_collect( + provider: z_loaned_shared_memory_provider_threadsafe_t, +) -> i32 { + access_loaned_memory!(provider, |val: &mut SharedMemoryProvider<_, _>| { + let _ = val.garbage_collect(); + 0 + }) +} + +//#[no_mangle] +//#[allow(clippy::missing_safety_doc)] +//pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_available( +// provider: z_loaned_shared_memory_provider_threadsafe_t, +//) -> i32 { +// access_loaned_memory!(provider, |val: &mut SharedMemoryProvider<_, _>| { +// val.available() +// }) +//} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_shared_memory_provider_threadsafe_map( + provider: &z_owned_shared_memory_provider_threadsafe_t, + allocated_chunk: z_allocated_chunk_t, + len: usize, + out_buffer: &mut MaybeUninit, +) -> bool { + let provider = provider.transmute_ref(); + match provider.map(allocated_chunk.transmute(), len) { + Ok(buffer) => { + out_buffer.write(buffer.transmute()); + true + } + Err(e) => { + log::error!("{e}"); + false + } + } +} diff --git a/src/shm/provider/types.rs b/src/shm/provider/types.rs new file mode 100644 index 000000000..dfaf2ed9e --- /dev/null +++ b/src/shm/provider/types.rs @@ -0,0 +1,214 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use std::mem::MaybeUninit; + +use zenoh::shm::provider::types::{ + AllocAlignment, BufAllocResult, ChunkAllocResult, MemoryLayout, ZAllocError, +}; +use zenoh_util::core::zerror; + +use crate::{decl_rust_copy_type, decl_rust_new_owned_type, impl_guarded_transmute, move_owned_memory, GuardedTransmute}; + +use super::{chunk::z_allocated_chunk_t, zsliceshm::z_owned_slice_shm_mut_t}; + +/// Allocation errors +/// +/// - **NEED_DEFRAGMENT**: defragmentation needed +/// - **OUT_OF_MEMORY**: the provider is out of memory +/// - **OTHER**: other error +#[allow(non_camel_case_types)] +#[repr(C)] +#[derive(Clone, Copy)] +pub enum z_alloc_error_t { + NEED_DEFRAGMENT, + OUT_OF_MEMORY, + OTHER, +} + +impl From for z_alloc_error_t { + #[inline] + fn from(value: ZAllocError) -> Self { + match value { + ZAllocError::NeedDefragment => z_alloc_error_t::NEED_DEFRAGMENT, + ZAllocError::OutOfMemory => z_alloc_error_t::OUT_OF_MEMORY, + ZAllocError::Other(_) => z_alloc_error_t::OTHER, + } + } +} + +impl From for ZAllocError { + #[inline] + fn from(value: z_alloc_error_t) -> Self { + match value { + z_alloc_error_t::NEED_DEFRAGMENT => ZAllocError::NeedDefragment, + z_alloc_error_t::OUT_OF_MEMORY => ZAllocError::OutOfMemory, + z_alloc_error_t::OTHER => ZAllocError::Other(zerror!("other error").into()), + } + } +} + +// An AllocAlignment. +#[cfg(target_arch = "x86_64")] +#[repr(C, align(4))] +pub struct z_alloc_alignment_t([u32; 1]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(4))] +pub struct z_alloc_alignment_t([u32; 1]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(4))] +pub struct z_alloc_alignment_t([u32; 1]); + +decl_rust_copy_type!( + zenoh:(AllocAlignment), + c:(z_alloc_alignment_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_alloc_alignment_delete(alignment: z_alloc_alignment_t) { + let _ = alignment.transmute(); +} + +// An owned MemoryLayout. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_memory_layout_t([u64; 2]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_memory_layout_t([u64; 2]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_memory_layout_t([u64; 2]); +decl_rust_copy_type!( + zenoh:(MemoryLayout), + c:(z_memory_layout_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_memory_layout_delete(layout: z_memory_layout_t) { + let _ = layout.transmute(); +} + +// An owned ChunkAllocResult +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` (or `z_check(val)` if your compiler supports `_Generic`), which will return `true` if `val` is valid. +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_chunk_alloc_result_t([u64; 4]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_chunk_alloc_result_t([u64; 4]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_chunk_alloc_result_t([u64; 4]); +decl_rust_copy_type!( + zenoh:(ChunkAllocResult), + c:(z_chunk_alloc_result_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_chunk_alloc_result_new_ok( + allocated_chunk: z_allocated_chunk_t, + out_result: &mut MaybeUninit, +) { + let allocated_chunk = allocated_chunk.transmute(); + let result = Ok(allocated_chunk); + out_result.write(result.transmute()); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_chunk_alloc_result_new_error( + alloc_error: z_alloc_error_t, + out_result: &mut MaybeUninit, +) { + let alloc_error = alloc_error.into(); + let result = Err(alloc_error); + out_result.write(result.transmute()); +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_chunk_alloc_result_delete(result: z_chunk_alloc_result_t) { + let _ = result.transmute(); +} + +/// A loaned BufAllocResult +#[allow(non_camel_case_types)] +#[derive(Clone, Copy)] +#[repr(C)] +pub struct z_buf_alloc_result_t<'a>(&'a z_owned_buf_alloc_result_t); + +// A BufAllocResult +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_owned_buf_alloc_result_t([u64; 11]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_owned_buf_alloc_result_t([u64; 12]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_owned_buf_alloc_result_t([u64; 11]); +decl_rust_new_owned_type!( + zenoh:(Option), + c:(z_owned_buf_alloc_result_t) +); + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_owned_buf_alloc_result_unwrap( + alloc_result: &mut z_owned_buf_alloc_result_t, + out_buf: &mut MaybeUninit, + out_error: &mut MaybeUninit, +) -> i32 { + move_owned_memory!(alloc_result, |result: BufAllocResult| { + match result { + Ok(val) => { + out_buf.write(Some(val).transmute()); + 0 + } + Err(e) => { + out_error.write(e.into()); + -5 // todo: E_ARGUMENT_INVALID + } + } + }) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_owned_buf_alloc_result_delete(result: z_owned_buf_alloc_result_t) { + let _ = result.transmute(); +} diff --git a/src/shm/provider/zsliceshm.rs b/src/shm/provider/zsliceshm.rs new file mode 100644 index 000000000..afeac5d6b --- /dev/null +++ b/src/shm/provider/zsliceshm.rs @@ -0,0 +1,86 @@ +// +// Copyright (c) 2023 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, +// + +use zenoh::shm::slice::zsliceshmmut::ZSliceShmMut; + +use crate::{decl_rust_new_owned_type, impl_guarded_transmute, GuardedTransmute}; + + +/// A loaned ZSliceShmMut +#[allow(non_camel_case_types)] +#[derive(Clone, Copy)] +#[repr(C)] +pub struct z_loaned_slice_shm_mut_t<'a>(&'a z_owned_slice_shm_mut_t); + +/// An owned ZSliceShmMut +/// +/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. +/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. +/// +/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. +/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. +/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. +/// +/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. +#[cfg(target_arch = "x86_64")] +#[repr(C, align(8))] +pub struct z_owned_slice_shm_mut_t([u64; 10]); + +#[cfg(target_arch = "aarch64")] +#[repr(C, align(16))] +pub struct z_owned_slice_shm_mut_t([u64; 10]); + +#[cfg(target_arch = "arm")] +#[repr(C, align(8))] +pub struct z_owned_slice_shm_mut_t([u64; 10]); + +decl_rust_new_owned_type!( + zenoh:(Option), + c:(z_owned_slice_shm_mut_t) +); + +/// Initializes a null memory for safe-to-drop value of 'z_owned_slice_shm_mut_t' type +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_slice_shm_mut_null( + val: &mut z_owned_slice_shm_mut_t, +) { + val.make_null(); +} + +/// Returns ``true`` if `val` is valid. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_slice_shm_mut_check( + val: &z_owned_slice_shm_mut_t, +) -> bool { + val.check() +} + +/// Returns a :c:type:`z_loaned_slice_shm_mut_t` loaned from `val`. +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub extern "C" fn z_slice_shm_mut_loan( + val: &z_owned_slice_shm_mut_t, +) -> z_loaned_slice_shm_mut_t { + z_loaned_slice_shm_mut_t(val) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn z_slice_shm_mut_delete( + val: &mut z_owned_slice_shm_mut_t, +) { + val.delete(); +} \ No newline at end of file diff --git a/src/subscriber.rs b/src/subscriber.rs index b9488960a..f1cb26beb 100644 --- a/src/subscriber.rs +++ b/src/subscriber.rs @@ -12,19 +12,23 @@ // ZettaScale Zenoh team, // -use crate::commons::*; -use crate::impl_guarded_transmute; +use std::mem::MaybeUninit; + +use crate::errors; use crate::keyexpr::*; -use crate::session::*; +use crate::transmute::unwrap_ref_unchecked; +use crate::transmute::Inplace; +use crate::transmute::TransmuteFromHandle; +use crate::transmute::TransmuteIntoHandle; +use crate::transmute::TransmuteRef; +use crate::transmute::TransmuteUninitPtr; use crate::z_closure_sample_call; +use crate::z_loaned_session_t; use crate::z_owned_closure_sample_t; -use crate::LOG_INVALID_SESSION; use zenoh::prelude::sync::SyncResolve; use zenoh::prelude::SessionDeclarations; -use zenoh::prelude::SplitBuffer; use zenoh::subscriber::Reliability; -use zenoh_protocol::core::SubInfo; -use zenoh_util::core::zresult::ErrNo; +use zenoh::subscriber::Subscriber; /// The subscription reliability. /// @@ -58,62 +62,25 @@ impl From for Reliability { } } -/**************************************/ -/* DECLARATION */ -/**************************************/ -type Subscriber = Option>>; - -/// An owned zenoh subscriber. Destroying the subscriber cancels the subscription. -/// -/// Like most `z_owned_X_t` types, you may obtain an instance of `z_X_t` by loaning it using `z_X_loan(&val)`. -/// The `z_loan(val)` macro, available if your compiler supports C11's `_Generic`, is equivalent to writing `z_X_loan(&val)`. -/// -/// Like all `z_owned_X_t`, an instance will be destroyed by any function which takes a mutable pointer to said instance, as this implies the instance's inners were moved. -/// To make this fact more obvious when reading your code, consider using `z_move(val)` instead of `&val` as the argument. -/// After a move, `val` will still exist, but will no longer be valid. The destructors are double-drop-safe, but other functions will still trust that your `val` is valid. -/// -/// To check if `val` is still valid, you may use `z_X_check(&val)` or `z_check(val)` if your compiler supports `_Generic`, which will return `true` if `val` is valid. -#[cfg(not(target_arch = "arm"))] -#[repr(C, align(8))] -pub struct z_owned_subscriber_t([u64; 1]); - -#[cfg(target_arch = "arm")] -#[repr(C, align(4))] -pub struct z_owned_subscriber_t([u32; 1]); - -impl_guarded_transmute!(Subscriber, z_owned_subscriber_t); +pub use crate::opaque_types::z_loaned_subscriber_t; +pub use crate::opaque_types::z_owned_subscriber_t; -impl z_owned_subscriber_t { - pub fn new(sub: zenoh::subscriber::Subscriber<'static, ()>) -> Self { - Some(Box::new(sub)).into() - } - pub fn null() -> Self { - None.into() - } -} +decl_transmute_owned!(Option>, z_owned_subscriber_t); +decl_transmute_handle!(Subscriber<'static, ()>, z_loaned_subscriber_t); /// Constructs a null safe-to-drop value of 'z_owned_subscriber_t' type #[no_mangle] -pub extern "C" fn z_subscriber_null() -> z_owned_subscriber_t { - z_owned_subscriber_t::null() +pub extern "C" fn z_subscriber_null(this: *mut MaybeUninit) { + let this = this.transmute_uninit_ptr(); + Inplace::empty(this); } -/// A loaned zenoh subscriber. -#[allow(non_camel_case_types)] -#[derive(Clone, Copy)] -#[repr(C)] -pub struct z_subscriber_t(*const z_owned_subscriber_t); - -impl AsRef for z_subscriber_t { - fn as_ref(&self) -> &Subscriber { - unsafe { &(*self.0) } - } -} - -/// Returns a :c:type:`z_subscriber_t` loaned from `p`. +/// Returns a :c:type:`z_loaned_subscriber_t` loaned from `this`. #[no_mangle] -pub extern "C" fn z_subscriber_loan(p: &z_owned_subscriber_t) -> z_subscriber_t { - z_subscriber_t(p) +pub extern "C" fn z_subscriber_loan(this: &z_owned_subscriber_t) -> &z_loaned_subscriber_t { + let this = this.transmute_ref(); + let this = unwrap_ref_unchecked(this); + this.transmute_handle() } /// Options passed to the :c:func:`z_declare_subscriber` or :c:func:`z_declare_pull_subscriber` function. @@ -128,10 +95,9 @@ pub struct z_subscriber_options_t { /// Constructs the default value for :c:type:`z_subscriber_options_t`. #[no_mangle] -pub extern "C" fn z_subscriber_options_default() -> z_subscriber_options_t { - let info = SubInfo::default(); - z_subscriber_options_t { - reliability: info.reliability.into(), +pub extern "C" fn z_subscriber_options_default(this: &mut z_subscriber_options_t) { + *this = z_subscriber_options_t { + reliability: Reliability::DEFAULT.into(), } } @@ -139,7 +105,7 @@ pub extern "C" fn z_subscriber_options_default() -> z_subscriber_options_t { /// /// Parameters: /// session: The zenoh session. -/// keyexpr: The key expression to subscribe. +/// key_expr: The key expression to subscribe. /// callback: The callback function that will be called each time a data matching the subscribed expression is received. /// opts: The options to be passed to describe the options to be passed to the subscriber declaration. /// @@ -169,39 +135,35 @@ pub extern "C" fn z_subscriber_options_default() -> z_subscriber_options_t { #[no_mangle] #[allow(clippy::missing_safety_doc)] pub extern "C" fn z_declare_subscriber( - session: z_session_t, - keyexpr: z_keyexpr_t, + this: *mut MaybeUninit, + session: &z_loaned_session_t, + key_expr: &z_loaned_keyexpr_t, callback: &mut z_owned_closure_sample_t, - opts: Option<&z_subscriber_options_t>, -) -> z_owned_subscriber_t { + options: Option<&mut z_subscriber_options_t>, +) -> errors::z_error_t { + let this = this.transmute_uninit_ptr(); let mut closure = z_owned_closure_sample_t::empty(); std::mem::swap(callback, &mut closure); - - match session.upgrade() { - Some(s) => { - let mut res = s.declare_subscriber(keyexpr).callback(move |sample| { - let payload = sample.payload.contiguous(); - let owner = match payload { - std::borrow::Cow::Owned(v) => zenoh::buffers::ZBuf::from(v), - _ => sample.payload.clone(), - }; - let sample = z_sample_t::new(&sample, &owner); - z_closure_sample_call(&closure, &sample) - }); - if let Some(opts) = opts { - res = res.reliability(opts.reliability.into()) - } - match res.res() { - Ok(sub) => z_owned_subscriber_t::new(sub), - Err(e) => { - log::debug!("{}", e); - z_owned_subscriber_t::null() - } - } + let session = session.transmute_ref(); + let key_expr = key_expr.transmute_ref(); + let mut subscriber = session + .declare_subscriber(key_expr) + .callback(move |sample| { + let sample = sample.transmute_handle(); + z_closure_sample_call(&closure, sample) + }); + if let Some(options) = options { + subscriber = subscriber.reliability(options.reliability.into()); + } + match subscriber.res() { + Ok(sub) => { + Inplace::init(this, Some(sub)); + errors::Z_OK } - None => { - log::debug!("{}", LOG_INVALID_SESSION); - z_owned_subscriber_t::null() + Err(e) => { + log::error!("{}", e); + Inplace::empty(this); + errors::Z_EGENERIC } } } @@ -209,30 +171,29 @@ pub extern "C" fn z_declare_subscriber( /// Returns the key expression of the subscriber. #[no_mangle] #[allow(clippy::missing_safety_doc)] -pub extern "C" fn z_subscriber_keyexpr(subscriber: z_subscriber_t) -> z_owned_keyexpr_t { - if let Some(p) = subscriber.as_ref() { - p.key_expr().clone().into() - } else { - z_keyexpr_t::null().into() - } +pub extern "C" fn z_subscriber_keyexpr(subscriber: &z_loaned_subscriber_t) -> &z_loaned_keyexpr_t { + let subscriber = subscriber.transmute_ref(); + subscriber.key_expr().transmute_handle() } /// Undeclares the given :c:type:`z_owned_subscriber_t`, droping it and invalidating it for double-drop safety. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_undeclare_subscriber(sub: &mut z_owned_subscriber_t) -> i8 { - if let Some(s) = sub.take() { +pub extern "C" fn z_undeclare_subscriber( + subscriber: &mut z_owned_subscriber_t, +) -> errors::z_error_t { + if let Some(s) = subscriber.transmute_mut().extract().take() { if let Err(e) = s.undeclare().res_sync() { - log::warn!("{}", e); - return e.errno().get(); + log::error!("{}", e); + return errors::Z_EGENERIC; } } - 0 + errors::Z_OK } /// Returns ``true`` if `sub` is valid. #[allow(clippy::missing_safety_doc)] #[no_mangle] -pub extern "C" fn z_subscriber_check(sub: &z_owned_subscriber_t) -> bool { - sub.as_ref().is_some() +pub extern "C" fn z_subscriber_check(subscriber: &z_owned_subscriber_t) -> bool { + subscriber.transmute_ref().is_some() } diff --git a/src/transmute.rs b/src/transmute.rs new file mode 100644 index 000000000..136069535 --- /dev/null +++ b/src/transmute.rs @@ -0,0 +1,225 @@ +// +// Copyright (c) 2017, 2024 ZettaScale Technology. +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh team, +// + +// pub fn as_static_ref<'a, T: 'a>(value: &'a T) -> &'static T { +// unsafe { std::mem::transmute::<&'a T, &'static T>(value) } +// } + +use std::mem::MaybeUninit; + +pub fn unwrap_ref_unchecked(value: &Option) -> &T { + debug_assert!(value.is_some()); + unsafe { value.as_ref().unwrap_unchecked() } +} + +pub fn unwrap_ref_unchecked_mut(value: &mut Option) -> &mut T { + debug_assert!(value.is_some()); + unsafe { value.as_mut().unwrap_unchecked() } +} + +pub(crate) trait TransmuteRef: Sized { + fn transmute_ref(&self) -> &T; + fn transmute_mut(&mut self) -> &mut T; +} + +pub(crate) trait TransmuteFromHandle: Sized { + fn transmute_ref(&self) -> &'static T; + fn transmute_mut(&mut self) -> &'static mut T; +} + +pub(crate) trait TransmuteIntoHandle: Sized { + fn transmute_handle(&self) -> &'static T; + fn transmute_handle_mut(&mut self) -> &'static mut T; +} + +pub(crate) trait TransmuteCopy { + fn transmute_copy(self) -> T; +} + +pub(crate) trait TransmuteUninitPtr: Sized { + fn transmute_uninit_ptr(self) -> *mut std::mem::MaybeUninit; +} + +pub(crate) trait Inplace: Sized { + // Initialize the object in place with a memcpy of the provided value. Assumes that the memory passed to the function is uninitialized + fn init(this: *mut std::mem::MaybeUninit, value: Self) { + let this = this as *mut Self; + unsafe { std::ptr::write(this, value) }; + } + + // Initialize the object in place with an empty value + fn empty(this: *mut std::mem::MaybeUninit); + + // Drop the object in place and replaces it with empty value + fn drop(this: &mut Self) { + let this = this as *mut Self; + unsafe { std::ptr::drop_in_place(this) }; + Inplace::empty(this as *mut std::mem::MaybeUninit); + } + + // Move the object out of this, leaving it in empty state + fn extract(&mut self) -> Self { + let mut out: MaybeUninit = MaybeUninit::uninit(); + Self::empty(&mut out); + let mut out = unsafe { out.assume_init() }; + std::mem::swap(&mut out, self); + out + } + // TODO: for effective inplace_init, we can provide a method that takes a closure that initializes the object in place +} + +pub(crate) trait InplaceDefault: Default { + // Default implementation of inplace_init for object implementing Default trait. May be less efficient than a custom implementation + // because for `empty` operation it performs a copy of the default value from stack to provided memory + fn default(this: *mut std::mem::MaybeUninit) { + let this = this as *mut Self; + unsafe { std::ptr::write(this, ::default()) }; + } +} + +// For types implementing Default, we can use provide default implementation of InplaceInit through InplaceInitDefault +impl Inplace for T { + fn empty(this: *mut std::mem::MaybeUninit) { + InplaceDefault::default(this); + } +} + +macro_rules! validate_equivalence { + ($type_a:ty, $type_b:ty) => { + const _: () = { + use const_format::concatcp; + const TYPE_NAME_A: &str = stringify!($type_a); + const TYPE_NAME_B: &str = stringify!($type_b); + const ALIGN_A: usize = std::mem::align_of::<$type_a>(); + const ALIGN_B: usize = std::mem::align_of::<$type_b>(); + if ALIGN_A != ALIGN_B { + const ERR_MESSAGE: &str = concatcp!( + "Alingment mismatch: type ", + TYPE_NAME_A, + " has alignment ", + ALIGN_A, + " while type ", + TYPE_NAME_B, + " has alignment ", + ALIGN_B + ); + panic!("{}", ERR_MESSAGE); + } + const SIZE_A: usize = std::mem::size_of::<$type_a>(); + const SIZE_B: usize = std::mem::size_of::<$type_b>(); + if SIZE_A != SIZE_B { + const ERR_MESSAGE: &str = concatcp!( + "Size mismatch: type ", + TYPE_NAME_A, + " has size ", + SIZE_A, + " while type ", + TYPE_NAME_B, + " has size ", + SIZE_B + ); + panic!("{}", ERR_MESSAGE); + } + }; + }; +} + +#[macro_export] +macro_rules! decl_transmute_owned { + ($zenoh_type:ty, $c_type:ty) => { + impl $crate::transmute::InplaceDefault for $zenoh_type {} + decl_transmute_owned!(custom_inplace_init $zenoh_type, $c_type); + + }; + (custom_inplace_init $zenoh_type:ty, $c_type:ty) => { + validate_equivalence!($zenoh_type, $c_type); + impl_transmute_ref!($zenoh_type, $c_type); + impl_transmute_ref!($c_type, $zenoh_type); + impl_transmute_uninit_ptr!($zenoh_type, $c_type); + impl_transmute_uninit_ptr!($c_type, $zenoh_type); + } +} + +#[macro_export] +macro_rules! decl_transmute_copy { + ($zenoh_type:ty, $c_type:ty) => { + validate_equivalence!($zenoh_type, $c_type); + impl_transmute_copy!($zenoh_type, $c_type); + impl_transmute_copy!($c_type, $zenoh_type); + impl_transmute_uninit_ptr!($zenoh_type, $c_type); + impl_transmute_uninit_ptr!($c_type, $zenoh_type); + }; +} + +#[macro_export] +macro_rules! decl_transmute_handle { + ($zenoh_type:ty, $c_type:ty) => { + validate_equivalence!($zenoh_type, $c_type); + impl_transmute_handle!($c_type, $zenoh_type); + }; +} + +macro_rules! impl_transmute_ref { + ($src_type:ty, $dst_type:ty) => { + impl $crate::transmute::TransmuteRef<$dst_type> for $src_type { + fn transmute_ref(&self) -> &$dst_type { + unsafe { std::mem::transmute::<&$src_type, &$dst_type>(self) } + } + fn transmute_mut(&mut self) -> &mut $dst_type { + unsafe { std::mem::transmute::<&mut $src_type, &mut $dst_type>(self) } + } + } + }; +} + +macro_rules! impl_transmute_copy { + ($src_type:ty, $dst_type:ty) => { + impl $crate::transmute::TransmuteCopy<$dst_type> for $src_type { + fn transmute_copy(self) -> $dst_type { + unsafe { std::mem::transmute::<$src_type, $dst_type>(self) } + } + } + }; +} + +macro_rules! impl_transmute_uninit_ptr { + ($src_type:ty, $dst_type:ty) => { + impl $crate::transmute::TransmuteUninitPtr<$dst_type> for *mut MaybeUninit<$src_type> { + fn transmute_uninit_ptr(self) -> *mut std::mem::MaybeUninit<$dst_type> { + self as *mut std::mem::MaybeUninit<$dst_type> + } + } + }; +} + +macro_rules! impl_transmute_handle { + ($c_type:ty, $zenoh_type:ty) => { + impl $crate::transmute::TransmuteFromHandle<$zenoh_type> for $c_type { + fn transmute_ref(&self) -> &'static $zenoh_type { + unsafe { std::mem::transmute::<&$c_type, &'static $zenoh_type>(self) } + } + fn transmute_mut(&mut self) -> &'static mut $zenoh_type { + unsafe { std::mem::transmute::<&mut $c_type, &'static mut $zenoh_type>(self) } + } + } + impl $crate::transmute::TransmuteIntoHandle<$c_type> for $zenoh_type { + fn transmute_handle(&self) -> &'static $c_type { + unsafe { std::mem::transmute::<&$zenoh_type, &'static $c_type>(self) } + } + fn transmute_handle_mut(&mut self) -> &'static mut $c_type { + unsafe { std::mem::transmute::<&mut $zenoh_type, &'static mut $c_type>(self) } + } + } + }; +} diff --git a/tests/z_api_alignment_test.c b/tests/z_api_alignment_test.c index 43ce08cc3..57bb31fd9 100644 --- a/tests/z_api_alignment_test.c +++ b/tests/z_api_alignment_test.c @@ -41,22 +41,23 @@ void hello_handler(z_owned_hello_t *hello, void *arg) { } volatile unsigned int queries = 0; -void query_handler(const z_query_t *query, void *arg) { +void query_handler(const z_loaned_query_t *query, void *arg) { queries++; - z_owned_str_t k_str = z_keyexpr_to_string(z_query_keyexpr(query)); + z_owned_str_t k_str = z_loaned_keyexpr_to_string(z_query_keyexpr(query)); #ifdef ZENOH_PICO if (k_str == NULL) { - k_str = zp_keyexpr_resolve(*(z_session_t *)arg, z_query_keyexpr(query)); + k_str = zp_keyexpr_resolve(*(z_loaned_session_t *)arg, z_query_keyexpr(query)); } #endif - z_bytes_t pred = z_query_parameters(query); + z_loaned_slice_t pred = z_query_parameters(query); (void)(pred); - z_value_t payload_value = z_query_value(query); + z_loaned_value_t payload_value = z_query_value(query); (void)(payload_value); z_query_reply_options_t _ret_qreply_opt = z_query_reply_options_default(); - z_query_reply(query, z_keyexpr(z_loan(k_str)), (const uint8_t *)value, strlen(value), &_ret_qreply_opt); + z_owned_bytes_t payload = z_bytes_encode_from_string(value); + z_query_reply(query, z_keyexpr(z_loan(k_str)), z_move(payload), &_ret_qreply_opt); z_drop(z_move(k_str)); } @@ -66,17 +67,17 @@ void reply_handler(z_owned_reply_t *reply, void *arg) { replies++; if (z_reply_is_ok(reply)) { - z_sample_t sample = z_reply_ok(reply); + z_loaned_sample_t sample = z_reply_ok(reply); - z_owned_str_t k_str = z_keyexpr_to_string(sample.keyexpr); + z_owned_str_t k_str = z_loaned_keyexpr_to_string(z_sample_keyexpr(&sample)); #ifdef ZENOH_PICO if (k_str == NULL) { - k_str = zp_keyexpr_resolve(*(z_session_t *)arg, sample.keyexpr); + k_str = zp_keyexpr_resolve(*(z_loaned_session_t *)arg, sample.keyexpr); } #endif z_drop(z_move(k_str)); } else { - z_value_t _ret_zvalue = z_reply_err(reply); + z_loaned_value_t _ret_zvalue = z_reply_err(reply); (void)(_ret_zvalue); } @@ -84,13 +85,13 @@ void reply_handler(z_owned_reply_t *reply, void *arg) { } volatile unsigned int datas = 0; -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { datas++; - z_owned_str_t k_str = z_keyexpr_to_string(sample->keyexpr); + z_owned_str_t k_str = z_loaned_keyexpr_to_string(z_sample_keyexpr(sample)); #ifdef ZENOH_PICO if (k_str == NULL) { - k_str = zp_keyexpr_resolve(*(z_session_t *)arg, sample->keyexpr); + k_str = zp_keyexpr_resolve(*(z_loaned_session_t *)arg, sample->keyexpr); } #endif z_drop(z_move(k_str)); @@ -103,7 +104,7 @@ int main(int argc, char **argv) { zc_init_logger(); #endif - z_keyexpr_t key = z_keyexpr("demo/example"); + z_loaned_keyexpr_t key = z_keyexpr("demo/example"); _Bool _ret_bool = z_keyexpr_is_initialized(&key); assert(_ret_bool == true); @@ -242,7 +243,7 @@ int main(int argc, char **argv) { z_sleep_s(SLEEP); - z_session_t ls1 = z_loan(s1); + z_loaned_session_t ls1 = z_loan(s1); z_owned_closure_sample_t _ret_closure_sample = z_closure(data_handler, NULL, &ls1); z_subscriber_options_t _ret_sub_opt = z_subscriber_options_default(); z_owned_subscriber_t _ret_sub = @@ -257,10 +258,11 @@ int main(int argc, char **argv) { assert(z_check(_ret_expr)); z_put_options_t _ret_put_opt = z_put_options_default(); _ret_put_opt.congestion_control = Z_CONGESTION_CONTROL_BLOCK; - z_encoding_t _ret_encoding = z_encoding_default(); + z_loaned_encoding_t _ret_encoding = z_encoding_default(); _ret_encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); _ret_put_opt.encoding = _ret_encoding; - _ret_int8 = z_put(z_loan(s1), z_loan(_ret_expr), (const uint8_t *)value, strlen(value), &_ret_put_opt); + z_owned_bytes_t payload = z_bytes_encode_from_string(value); + _ret_int8 = z_put(z_loan(s1), z_loan(_ret_expr), z_move(payload), &_ret_put_opt); assert(_ret_int8 == 0); z_sleep_s(SLEEP); @@ -292,7 +294,8 @@ int main(int argc, char **argv) { assert(z_check(_ret_pub)); z_publisher_put_options_t _ret_pput_opt = z_publisher_put_options_default(); - _ret_int8 = z_publisher_put(z_loan(_ret_pub), (const uint8_t *)value, strlen(value), &_ret_pput_opt); + payload = z_bytes_encode_from_string(value); + _ret_int8 = z_publisher_put(z_loan(_ret_pub), z_move(payload), &_ret_pput_opt); assert(_ret_int8 == 0); z_sleep_s(SLEEP); @@ -330,10 +333,10 @@ int main(int argc, char **argv) { z_sleep_s(SLEEP); - z_session_t ls2 = z_loan(s2); + z_loaned_session_t ls2 = z_loan(s2); z_owned_closure_reply_t _ret_closure_reply = z_closure(reply_handler, NULL, &ls2); z_get_options_t _ret_get_opt = z_get_options_default(); - _ret_get_opt.target = z_query_target_default(); + _ret_get_opt.target = z_loaned_query_target_default(); _ret_get_opt.consolidation = z_query_consolidation_auto(); _ret_get_opt.consolidation = z_query_consolidation_default(); _ret_get_opt.consolidation = z_query_consolidation_latest(); diff --git a/tests/z_api_attachment_test.c b/tests/z_api_attachment_test.c index 737048e9b..ebcdc6993 100644 --- a/tests/z_api_attachment_test.c +++ b/tests/z_api_attachment_test.c @@ -23,31 +23,31 @@ void writting_through_map_by_alias_read_by_get() { // Writing - z_owned_bytes_map_t map = z_bytes_map_new(); - z_bytes_map_insert_by_alias(&map, z_bytes_from_str("k1"), z_bytes_from_str("v1")); - z_bytes_map_insert_by_alias(&map, z_bytes_from_str("k2"), z_bytes_from_str("v2")); - z_attachment_t attachment = z_bytes_map_as_attachment(&map); + z_owned_bytes_map_t map = z_slice_map_new(); + z_slice_map_insert_by_alias(&map, z_slice_from_str("k1"), z_slice_from_str("v1")); + z_slice_map_insert_by_alias(&map, z_slice_from_str("k2"), z_slice_from_str("v2")); + z_loaned_bytes_t attachment = z_slice_map_as_attachment(&map); // Elements check - assert(z_bytes_map_len(&map) == 2); + assert(z_slice_map_len(&map) == 2); assert(z_attachment_len(attachment) == 2); assert(!z_attachment_is_empty(attachment)); - z_bytes_t a1 = z_attachment_get(attachment, z_bytes_from_str("k1")); + z_loaned_slice_t a1 = z_attachment_get(attachment, z_slice_from_str("k1")); ASSERT_STR_BYTES_EQUAL("v1", a1); - z_bytes_t a2 = z_attachment_get(attachment, z_bytes_from_str("k2")); + z_loaned_slice_t a2 = z_attachment_get(attachment, z_slice_from_str("k2")); ASSERT_STR_BYTES_EQUAL("v2", a2); - z_bytes_t a_non = z_attachment_get(attachment, z_bytes_from_str("k_non")); + z_loaned_slice_t a_non = z_attachment_get(attachment, z_slice_from_str("k_non")); assert(a_non.start == NULL); assert(a_non.len == 0); z_drop(z_move(map)); } -int8_t _attachment_reader(z_bytes_t key, z_bytes_t value, void* ctx) { +int8_t _attachment_reader(z_loaned_slice_t key, z_loaned_slice_t value, void* ctx) { assert((size_t)ctx == 42); if (!strncmp(key.start, "k1", key.len)) { assert(!strncmp(value.start, "v1", value.len)); @@ -60,13 +60,13 @@ int8_t _attachment_reader(z_bytes_t key, z_bytes_t value, void* ctx) { void writting_through_map_by_copy_read_by_iter() { // Writing - z_owned_bytes_map_t map = z_bytes_map_new(); - z_bytes_map_insert_by_copy(&map, z_bytes_from_str("k1"), z_bytes_from_str("v1")); - z_bytes_map_insert_by_copy(&map, z_bytes_from_str("k2"), z_bytes_from_str("v2")); - z_attachment_t attachment = z_bytes_map_as_attachment(&map); + z_owned_bytes_map_t map = z_slice_map_new(); + z_slice_map_insert_by_copy(&map, z_slice_from_str("k1"), z_slice_from_str("v1")); + z_slice_map_insert_by_copy(&map, z_slice_from_str("k2"), z_slice_from_str("v2")); + z_loaned_bytes_t attachment = z_slice_map_as_attachment(&map); // Elements check - assert(z_bytes_map_len(&map) == 2); + assert(z_slice_map_len(&map) == 2); assert(z_attachment_len(attachment) == 2); assert(!z_attachment_is_empty(attachment)); @@ -78,38 +78,38 @@ void writting_through_map_by_copy_read_by_iter() { int8_t _iteration_driver(const void* data, z_attachment_iter_body_t body, void* ctx) { int8_t ret = 0; - ret = body(z_bytes_from_str("k1"), z_bytes_from_str("v1"), ctx); + ret = body(z_slice_from_str("k1"), z_slice_from_str("v1"), ctx); if (ret) { return ret; } - ret = body(z_bytes_from_str("k2"), z_bytes_from_str("v2"), ctx); + ret = body(z_slice_from_str("k2"), z_slice_from_str("v2"), ctx); return ret; } void writting_no_map_read_by_get() { - z_attachment_t attachment = {.data = NULL, .iteration_driver = &_iteration_driver}; + z_loaned_bytes_t attachment = {.data = NULL, .iteration_driver = &_iteration_driver}; // Elements check assert(z_attachment_len(attachment) == 2); assert(!z_attachment_is_empty(attachment)); - z_bytes_t a1 = z_attachment_get(attachment, z_bytes_from_str("k1")); + z_loaned_slice_t a1 = z_attachment_get(attachment, z_slice_from_str("k1")); ASSERT_STR_BYTES_EQUAL("v1", a1); - z_bytes_t a2 = z_attachment_get(attachment, z_bytes_from_str("k2")); + z_loaned_slice_t a2 = z_attachment_get(attachment, z_slice_from_str("k2")); ASSERT_STR_BYTES_EQUAL("v2", a2); - z_bytes_t a_non = z_attachment_get(attachment, z_bytes_from_str("k_non")); + z_loaned_slice_t a_non = z_attachment_get(attachment, z_slice_from_str("k_non")); assert(a_non.start == NULL); assert(a_non.len == 0); } void invalid_attachment_safety() { - z_attachment_t attachment = z_attachment_null(); + z_loaned_bytes_t attachment = z_attachment_null(); assert(z_attachment_is_empty(attachment)); assert(z_attachment_len(attachment) == 0); - z_bytes_t a_non = z_attachment_get(attachment, z_bytes_from_str("k_non")); + z_loaned_slice_t a_non = z_attachment_get(attachment, z_slice_from_str("k_non")); assert(a_non.start == NULL); assert(a_non.len == 0); diff --git a/tests/z_api_double_drop_test.c b/tests/z_api_double_drop_test.c index 3fd158f12..48b5927f6 100644 --- a/tests/z_api_double_drop_test.c +++ b/tests/z_api_double_drop_test.c @@ -71,7 +71,7 @@ void test_scouting_config() { assert(!z_check(config)); } -void data_handler(const z_sample_t *sample, void *arg) {} +void data_handler(const z_loaned_sample_t *sample, void *arg) {} void test_pull_subscriber() { z_owned_config_t config = z_config_default(); @@ -99,7 +99,7 @@ void test_subscriber() { z_drop(z_move(s)); } -void query_handler(const z_query_t *query, void *context) {} +void query_handler(const z_loaned_query_t *query, void *context) {} void test_queryable() { z_owned_config_t config = z_config_default(); diff --git a/tests/z_api_keyexpr_drop_test.c b/tests/z_api_keyexpr_drop_test.c index ac81be4cd..08b77038d 100644 --- a/tests/z_api_keyexpr_drop_test.c +++ b/tests/z_api_keyexpr_drop_test.c @@ -29,14 +29,14 @@ void test_publisher() { z_owned_publisher_t pub = z_declare_publisher(z_loan(s), z_keyexpr(keyexpr), NULL); strncpy(keyexpr, "baz/quax", 256); // Update source string to ensure that the correct keyexpr z_owned_keyexpr_t pub_keyexpr = z_publisher_keyexpr(z_loan(pub)); - z_owned_str_t pub_keyexpr_str = z_keyexpr_to_string(z_loan(pub_keyexpr)); + z_owned_str_t pub_keyexpr_str = z_loaned_keyexpr_to_string(z_loan(pub_keyexpr)); assert(strcmp(z_loan(pub_keyexpr_str), "foo/bar") == 0); // Check that publisher keeps the correct keyexpr z_drop(z_move(pub_keyexpr_str)); z_drop(z_move(pub)); z_drop(z_move(s)); } -void data_handler(const z_sample_t *sample, void *arg) {} +void data_handler(const z_loaned_sample_t *sample, void *arg) {} // void test_pull_subscriber() { // z_owned_config_t config = z_config_default(); @@ -59,14 +59,14 @@ void test_subscriber() { z_owned_subscriber_t sub = z_declare_subscriber(z_loan(s), z_keyexpr(keyexpr), z_move(callback), NULL); strncpy(keyexpr, "baz/quax", 256); // Update source string to ensure that the keyexpr is copied into the subscriber z_owned_keyexpr_t sub_keyexpr = z_subscriber_keyexpr(z_loan(sub)); - z_owned_str_t sub_keyexpr_str = z_keyexpr_to_string(z_loan(sub_keyexpr)); + z_owned_str_t sub_keyexpr_str = z_loaned_keyexpr_to_string(z_loan(sub_keyexpr)); assert(strcmp(z_loan(sub_keyexpr_str), "foo/bar") == 0); // Check that subscriber keeps the correct keyexpr z_drop(z_move(sub_keyexpr_str)); z_drop(z_move(sub)); z_drop(z_move(s)); } -// void query_handler(const z_query_t *query, void *context) {} +// void query_handler(const z_loaned_query_t *query, void *context) {} // void test_queryable() { // z_owned_config_t config = z_config_default(); diff --git a/tests/z_api_keyexpr_test.c b/tests/z_api_keyexpr_test.c index cb3c234b3..e62e27d09 100644 --- a/tests/z_api_keyexpr_test.c +++ b/tests/z_api_keyexpr_test.c @@ -43,7 +43,7 @@ void canonize() { assert(strcmp(keyexpr, "a/**/c") == 0); strcpy(keyexpr, "a/**/**/c"); - z_keyexpr_t key_expr_canonized = z_keyexpr_autocanonize(keyexpr); + z_loaned_keyexpr_t key_expr_canonized = z_keyexpr_autocanonize(keyexpr); assert(z_keyexpr_check(keyexpr) == true); assert(strcmp(keyexpr, "a/**/c") == 0); assert(z_keyexpr_as_bytes(key_expr_canonized).len == len_new); @@ -60,9 +60,9 @@ void canonize() { } void includes() { - z_keyexpr_t nul = z_keyexpr(NULL); - z_keyexpr_t foobar = z_keyexpr("foo/bar"); - z_keyexpr_t foostar = z_keyexpr("foo/*"); + z_loaned_keyexpr_t nul = z_keyexpr(NULL); + z_loaned_keyexpr_t foobar = z_keyexpr("foo/bar"); + z_loaned_keyexpr_t foostar = z_keyexpr("foo/*"); assert(z_keyexpr_includes(foostar, foobar) == 0); assert(z_keyexpr_includes(foobar, foostar) == -1); assert(z_keyexpr_includes(nul, foobar) < -1); @@ -70,10 +70,10 @@ void includes() { } void intersects() { - z_keyexpr_t nul = z_keyexpr(NULL); - z_keyexpr_t foobar = z_keyexpr("foo/bar"); - z_keyexpr_t foostar = z_keyexpr("foo/*"); - z_keyexpr_t barstar = z_keyexpr("bar/*"); + z_loaned_keyexpr_t nul = z_keyexpr(NULL); + z_loaned_keyexpr_t foobar = z_keyexpr("foo/bar"); + z_loaned_keyexpr_t foostar = z_keyexpr("foo/*"); + z_loaned_keyexpr_t barstar = z_keyexpr("bar/*"); assert(z_keyexpr_intersects(foostar, foobar) == 0); assert(z_keyexpr_intersects(barstar, foobar) == -1); assert(z_keyexpr_intersects(nul, foobar) < -1); @@ -90,10 +90,10 @@ void undeclare() { } void relation_to() { - z_keyexpr_t nul = z_keyexpr(NULL); - z_keyexpr_t foobar = z_keyexpr("foo/bar"); - z_keyexpr_t foostar = z_keyexpr("foo/*"); - z_keyexpr_t barstar = z_keyexpr("bar/*"); + z_loaned_keyexpr_t nul = z_keyexpr(NULL); + z_loaned_keyexpr_t foobar = z_keyexpr("foo/bar"); + z_loaned_keyexpr_t foostar = z_keyexpr("foo/*"); + z_loaned_keyexpr_t barstar = z_keyexpr("bar/*"); assert(z_keyexpr_relation_to(foostar, foobar) == Z_KEYEXPR_INTERSECTION_LEVEL_INCLUDES); assert(z_keyexpr_relation_to(foobar, foostar) == Z_KEYEXPR_INTERSECTION_LEVEL_INTERSECTS); assert(z_keyexpr_relation_to(foostar, foostar) == Z_KEYEXPR_INTERSECTION_LEVEL_EQUALS); diff --git a/tests/z_api_null_drop_test.c b/tests/z_api_null_drop_test.c index 814d80e7c..3a0bee06a 100644 --- a/tests/z_api_null_drop_test.c +++ b/tests/z_api_null_drop_test.c @@ -43,9 +43,7 @@ int main(int argc, char **argv) { z_owned_reply_channel_closure_t reply_channel_closure_null_1 = z_reply_channel_closure_null(); z_owned_reply_channel_t reply_channel_null_1 = z_reply_channel_null(); z_owned_str_t str_null_1 = z_str_null(); - zc_owned_payload_t payload_null_1 = zc_payload_null(); - zc_owned_shmbuf_t shmbuf_null_1 = zc_shmbuf_null(); - zc_owned_shm_manager_t shm_manager_null_1 = zc_shm_manager_null(); + z_owned_bytes_t payload_null_1 = z_bytes_null(); // // Test that they actually make invalid value (where applicable) @@ -63,9 +61,7 @@ int main(int argc, char **argv) { assert(!z_check(hello_null_1)); assert(!z_check(str_null_1)); assert(!z_check(payload_null_1)); - assert(!z_check(shmbuf_null_1)); - assert(!z_check(shm_manager_null_1)); - + // // Test that z_null macro defined for all types // @@ -88,10 +84,8 @@ int main(int argc, char **argv) { z_owned_reply_channel_closure_t reply_channel_closure_null_2; z_owned_reply_channel_t reply_channel_null_2; z_owned_str_t str_null_2; - zc_owned_payload_t payload_null_2; - zc_owned_shmbuf_t shmbuf_null_2; - zc_owned_shm_manager_t shm_manager_null_2; - + z_owned_bytes_t payload_null_2; + z_null(&session_null_2); z_null(&publisher_null_2); z_null(&keyexpr_null_2); @@ -112,9 +106,7 @@ int main(int argc, char **argv) { z_null(&reply_channel_null_2); z_null(&str_null_2); z_null(&payload_null_2); - z_null(&shmbuf_null_2); - z_null(&shm_manager_null_2); - + // // Test that null macro works the same as direct call // @@ -131,9 +123,7 @@ int main(int argc, char **argv) { assert(!z_check(hello_null_2)); assert(!z_check(str_null_2)); assert(!z_check(payload_null_2)); - assert(!z_check(shmbuf_null_2)); - assert(!z_check(shm_manager_null_2)); - + // // Test drop null and double drop it // @@ -158,9 +148,7 @@ int main(int argc, char **argv) { z_drop(z_move(reply_channel_null_1)); z_drop(z_move(str_null_1)); z_drop(z_move(payload_null_1)); - z_drop(z_move(shmbuf_null_1)); - z_drop(z_move(shm_manager_null_1)); - + z_drop(z_move(session_null_2)); z_drop(z_move(publisher_null_2)); z_drop(z_move(keyexpr_null_2)); @@ -181,8 +169,6 @@ int main(int argc, char **argv) { z_drop(z_move(reply_channel_null_2)); z_drop(z_move(str_null_2)); z_drop(z_move(payload_null_2)); - z_drop(z_move(shmbuf_null_2)); - z_drop(z_move(shm_manager_null_2)); } return 0; diff --git a/tests/z_api_payload_test.c b/tests/z_api_payload_test.c new file mode 100644 index 000000000..3e2fed1b2 --- /dev/null +++ b/tests/z_api_payload_test.c @@ -0,0 +1,43 @@ +// +// Copyright (c) 2022 ZettaScale Technology +// +// This program and the accompanying materials are made available under the +// terms of the Eclipse Public License 2.0 which is available at +// http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 +// which is available at https://www.apache.org/licenses/LICENSE-2.0. +// +// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 +// +// Contributors: +// ZettaScale Zenoh Team, + +#include +#include +#include +#include + +#include "zenoh.h" + +#undef NDEBUG +#include + +void test_reader() { + uint8_t data[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; + uint8_t data_out[10] = {0}; + z_loaned_slice_t bytes = {.start = data, .len = 10 }; + + z_owned_bytes_t payload = z_bytes_encode_from_bytes(bytes); + z_bytes_reader reader; + z_bytes_reader_init(z_loan(payload), &reader); + assert(z_bytes_reader_remaining(&reader) == 10); + + z_bytes_reader_read(&reader, data_out, 5); + assert(z_bytes_reader_remaining(&reader) == 5); + z_bytes_reader_read(&reader, data_out, 5); + assert(z_bytes_reader_remaining(&reader) == 0); + assert(memcmp(data, data_out, 10)); +} + +int main(int argc, char **argv) { + test_reader(); +} diff --git a/tests/z_api_unitinialized_check.c b/tests/z_api_unitinialized_check.c index 5a4df764e..3b6f95da0 100644 --- a/tests/z_api_unitinialized_check.c +++ b/tests/z_api_unitinialized_check.c @@ -25,6 +25,6 @@ int main(int argc, char **argv) { z_owned_keyexpr_t owned_keyexpr = z_keyexpr_new(NULL); assert(!z_check(owned_keyexpr)); - z_keyexpr_t keyexpr = z_keyexpr(NULL); + z_loaned_keyexpr_t keyexpr = z_keyexpr(NULL); assert(!z_check(keyexpr)); } diff --git a/tests/z_int_pub_cache_query_sub_test.c b/tests/z_int_pub_cache_query_sub_test.c index 82c27b97f..742f2d656 100644 --- a/tests/z_int_pub_cache_query_sub_test.c +++ b/tests/z_int_pub_cache_query_sub_test.c @@ -61,7 +61,8 @@ int run_publisher() { // values for cache for (int i = 0; i < values_count / 2; ++i) { - z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)values[i], strlen(values[i]), NULL); + z_owned_bytes_t payload = z_bytes_encode_from_string(values[i]); + z_put(z_loan(s), z_keyexpr(keyexpr), z_move(payload), NULL); } SEM_POST(sem_pub); @@ -70,7 +71,8 @@ int run_publisher() { // values for subscribe for (int i = values_count / 2; i < values_count; ++i) { - z_put(z_loan(s), z_keyexpr(keyexpr), (const uint8_t *)values[i], strlen(values[i]), NULL); + z_owned_bytes_t payload = z_bytes_encode_from_string(values[i]); + z_put(z_loan(s), z_keyexpr(keyexpr), z_move(payload), NULL); } printf("wait: sem_sub\n"); @@ -83,16 +85,22 @@ int run_publisher() { return 0; } -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { static int val_num = 0; - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(sample)); if (strcmp(keyexpr, z_loan(keystr))) { perror("Unexpected key received"); exit(-1); } z_drop(z_move(keystr)); - - ASSERT_STR_BYTES_EQUAL(values[val_num], sample->payload); + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(z_sample_payload(sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { + perror("Unexpected value received"); + z_drop(z_move(payload_value)); + exit(-1); + } + z_drop(z_move(payload_value)); printf("data_handler: %i\n", val_num); if (++val_num == values_count) { diff --git a/tests/z_int_pub_sub_attachment_test.c b/tests/z_int_pub_sub_attachment_test.c index c7f502a59..a2dba9b6b 100644 --- a/tests/z_int_pub_sub_attachment_test.c +++ b/tests/z_int_pub_sub_attachment_test.c @@ -47,15 +47,16 @@ int run_publisher() { return -1; } - z_owned_bytes_map_t map = z_bytes_map_new(); - z_bytes_map_insert_by_copy(&map, z_bytes_from_str(K_CONST), z_bytes_from_str(V_CONST)); + z_owned_bytes_map_t map = z_slice_map_new(); + z_slice_map_insert_by_copy(&map, z_slice_from_str(K_CONST), z_slice_from_str(V_CONST)); z_publisher_put_options_t options = z_publisher_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - options.attachment = z_bytes_map_as_attachment(&map); + options.attachment = z_slice_map_as_attachment(&map); for (int i = 0; i < values_count; ++i) { - z_bytes_map_insert_by_copy(&map, z_bytes_from_str(K_VAR), z_bytes_from_str(values[i])); - z_publisher_put(z_loan(pub), (const uint8_t *)values[i], strlen(values[i]), &options); + z_slice_map_insert_by_copy(&map, z_slice_from_str(K_VAR), z_slice_from_str(values[i])); + z_owned_bytes_t payload = z_bytes_encode_from_string(values[i]); + z_publisher_put(z_loan(pub), z_move(payload), &options); } z_undeclare_publisher(z_move(pub)); @@ -64,24 +65,28 @@ int run_publisher() { return 0; } -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { static int val_num = 0; - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(sample)); if (strcmp(keyexpr, z_loan(keystr))) { perror("Unexpected key received"); exit(-1); } z_drop(z_move(keystr)); - if (strncmp(values[val_num], (const char *)sample->payload.start, (int)sample->payload.len)) { + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(z_sample_payload(sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { perror("Unexpected value received"); + z_drop(z_move(payload_value)); exit(-1); } + z_drop(z_move(payload_value)); - z_bytes_t v_const = z_attachment_get(sample->attachment, z_bytes_from_str(K_CONST)); + z_loaned_slice_t v_const = z_attachment_get(z_sample_attachment(sample), z_slice_from_str(K_CONST)); ASSERT_STR_BYTES_EQUAL(V_CONST, v_const); - z_bytes_t v_var = z_attachment_get(sample->attachment, z_bytes_from_str(K_VAR)); + z_loaned_slice_t v_var = z_attachment_get(z_sample_attachment(sample), z_slice_from_str(K_VAR)); ASSERT_STR_BYTES_EQUAL(values[val_num], v_var); if (++val_num == values_count) { diff --git a/tests/z_int_pub_sub_test.c b/tests/z_int_pub_sub_test.c index cf005a80f..4907af56e 100644 --- a/tests/z_int_pub_sub_test.c +++ b/tests/z_int_pub_sub_test.c @@ -49,7 +49,8 @@ int run_publisher() { for (int i = 0; i < values_count; ++i) { z_publisher_put_options_t options = z_publisher_put_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_publisher_put(z_loan(pub), (const uint8_t *)values[i], strlen(values[i]), &options); + z_owned_bytes_t payload = z_bytes_encode_from_string(values[i]); + z_publisher_put(z_loan(pub), z_move(payload), &options); } z_undeclare_publisher(z_move(pub)); @@ -57,23 +58,26 @@ int run_publisher() { return 0; } -void data_handler(const z_sample_t *sample, void *arg) { +void data_handler(const z_loaned_sample_t *sample, void *arg) { static int val_num = 0; - z_owned_str_t keystr = z_keyexpr_to_string(sample->keyexpr); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(sample)); if (strcmp(keyexpr, z_loan(keystr))) { perror("Unexpected key received"); exit(-1); } z_drop(z_move(keystr)); - if (strncmp(values[val_num], (const char *)sample->payload.start, (int)sample->payload.len)) { + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(z_sample_payload(sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { perror("Unexpected value received"); + z_drop(z_move(payload_value)); exit(-1); } + z_drop(z_move(payload_value)); - if (z_qos_get_congestion_control(sample->qos) != Z_CONGESTION_CONTROL_BLOCK - || z_qos_get_priority(sample->qos) != Z_PRIORITY_DATA - ) { + if (z_qos_get_congestion_control(z_sample_qos(sample)) != Z_CONGESTION_CONTROL_BLOCK || + z_qos_get_priority(z_sample_qos(sample)) != Z_PRIORITY_DATA) { perror("Unexpected QoS values"); exit(-1); } diff --git a/tests/z_int_queryable_attachment_test.c b/tests/z_int_queryable_attachment_test.c index ce1ac9f42..7582a9e92 100644 --- a/tests/z_int_queryable_attachment_test.c +++ b/tests/z_int_queryable_attachment_test.c @@ -29,29 +29,29 @@ const char *const K_VAR = "k_var"; const char *const K_CONST = "k_const"; const char *const V_CONST = "v const"; -void query_handler(const z_query_t *query, void *context) { +void query_handler(const z_loaned_query_t *query, void *context) { static int value_num = 0; - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - z_value_t payload_value = z_query_value(query); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_query_keyexpr(query)); + z_loaned_slice_t pred = z_query_parameters(query); + z_loaned_value_t payload_value = z_query_value(query); - z_attachment_t attachment = z_query_attachment(query); + z_loaned_bytes_t attachment = z_query_attachment(query); - z_bytes_t v_const = z_attachment_get(attachment, z_bytes_from_str(K_CONST)); + z_loaned_slice_t v_const = z_attachment_get(attachment, z_slice_from_str(K_CONST)); ASSERT_STR_BYTES_EQUAL(V_CONST, v_const); - z_bytes_t v_var = z_attachment_get(attachment, z_bytes_from_str(K_VAR)); + z_loaned_slice_t v_var = z_attachment_get(attachment, z_slice_from_str(K_VAR)); ASSERT_STR_BYTES_EQUAL(values[value_num], v_var); - z_owned_bytes_map_t map = z_bytes_map_new(); - z_bytes_map_insert_by_copy(&map, z_bytes_from_str(K_CONST), z_bytes_from_str(V_CONST)); + z_owned_bytes_map_t map = z_slice_map_new(); + z_slice_map_insert_by_copy(&map, z_slice_from_str(K_CONST), z_slice_from_str(V_CONST)); z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - options.attachment = z_bytes_map_as_attachment(&map); - z_query_reply(query, z_keyexpr((const char *)context), (const uint8_t *)values[value_num], - strlen(values[value_num]), &options); + options.attachment = z_slice_map_as_attachment(&map); + z_owned_bytes_t payload = z_bytes_encode_from_string(values[value_num]); + z_query_reply(query, z_keyexpr((const char *)context), z_move(payload), &options); z_drop(z_move(keystr)); z_drop(z_move(map)); @@ -93,14 +93,14 @@ int run_get() { return -1; } - z_owned_bytes_map_t map = z_bytes_map_new(); - z_bytes_map_insert_by_copy(&map, z_bytes_from_str(K_CONST), z_bytes_from_str(V_CONST)); + z_owned_bytes_map_t map = z_slice_map_new(); + z_slice_map_insert_by_copy(&map, z_slice_from_str(K_CONST), z_slice_from_str(V_CONST)); z_get_options_t opts = z_get_options_default(); - opts.attachment = z_bytes_map_as_attachment(&map); + opts.attachment = z_slice_map_as_attachment(&map); for (int val_num = 0; val_num < values_count; ++val_num) { - z_bytes_map_insert_by_copy(&map, z_bytes_from_str(K_VAR), z_bytes_from_str(values[val_num])); + z_slice_map_insert_by_copy(&map, z_slice_from_str(K_VAR), z_slice_from_str(values[val_num])); z_owned_reply_channel_t channel = zc_reply_fifo_new(16); z_get(z_loan(s), z_keyexpr(keyexpr), "", z_move(channel.send), &opts); @@ -108,15 +108,21 @@ int run_get() { for (z_call(channel.recv, &reply); z_check(reply); z_call(channel.recv, &reply)) { assert(z_reply_is_ok(&reply)); - z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - - ASSERT_STR_BYTES_EQUAL(values[val_num], sample.payload); - - z_bytes_t v_const = z_attachment_get(sample.attachment, z_bytes_from_str(K_CONST)); + z_loaned_sample_t sample = z_reply_ok(&reply); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(&sample)); + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(z_sample_payload(&sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { + perror("Unexpected value received"); + z_drop(z_move(payload_value)); + exit(-1); + } + + z_loaned_slice_t v_const = z_attachment_get(z_sample_attachment(&sample), z_slice_from_str(K_CONST)); ASSERT_STR_BYTES_EQUAL(V_CONST, v_const); z_drop(z_move(keystr)); + z_drop(z_move(payload_value)); } z_drop(z_move(reply)); z_drop(z_move(channel)); diff --git a/tests/z_int_queryable_test.c b/tests/z_int_queryable_test.c index 2999451c4..d22d5b6ab 100644 --- a/tests/z_int_queryable_test.c +++ b/tests/z_int_queryable_test.c @@ -25,17 +25,17 @@ const char *const keyexpr = "test/key"; const char *const values[] = {"test_value_1", "test_value_2", "test_value_3"}; const size_t values_count = sizeof(values) / sizeof(values[0]); -void query_handler(const z_query_t *query, void *context) { +void query_handler(const z_loaned_query_t *query, void *context) { static int value_num = 0; - z_owned_str_t keystr = z_keyexpr_to_string(z_query_keyexpr(query)); - z_bytes_t pred = z_query_parameters(query); - z_value_t payload_value = z_query_value(query); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_query_keyexpr(query)); + z_loaned_slice_t pred = z_query_parameters(query); + z_loaned_value_t payload_value = z_query_value(query); z_query_reply_options_t options = z_query_reply_options_default(); options.encoding = z_encoding(Z_ENCODING_PREFIX_TEXT_PLAIN, NULL); - z_query_reply(query, z_keyexpr((const char *)context), (const uint8_t *)values[value_num], - strlen(values[value_num]), &options); + z_owned_bytes_t payload = z_bytes_encode_from_string(values[value_num]); + z_query_reply(query, z_keyexpr((const char *)context), z_move(payload), &options); z_drop(z_move(keystr)); if (++value_num == values_count) { @@ -84,12 +84,18 @@ int run_get() { for (z_call(channel.recv, &reply); z_check(reply); z_call(channel.recv, &reply)) { assert(z_reply_is_ok(&reply)); - z_sample_t sample = z_reply_ok(&reply); - z_owned_str_t keystr = z_keyexpr_to_string(sample.keyexpr); - - ASSERT_STR_BYTES_EQUAL(values[val_num], sample.payload); + z_loaned_sample_t sample = z_reply_ok(&reply); + z_owned_str_t keystr = z_loaned_keyexpr_to_string(z_sample_keyexpr(&sample)); + z_owned_str_t payload_value = z_str_null(); + z_bytes_decode_into_string(z_sample_payload(&sample), &payload_value); + if (strcmp(values[val_num], z_loan(payload_value))) { + perror("Unexpected value received"); + z_drop(z_move(payload_value)); + exit(-1); + } z_drop(z_move(keystr)); + z_drop(z_move(payload_value)); } z_drop(z_move(reply)); z_drop(z_move(channel));