From 09ef35e56faa02c71c10036193c5667d31e8539a Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 17 Nov 2025 12:45:55 -0500 Subject: [PATCH 01/10] Update crate versions and editions --- Cargo.lock | 1282 +++++++++++++++++++++--------- Cargo.toml | 8 +- examples/async-sqlite/Cargo.toml | 6 +- examples/cpu-count/Cargo.toml | 4 +- examples/gzip-stream/Cargo.toml | 4 +- examples/gzip-stream/src/lib.rs | 6 +- examples/hello-world/Cargo.toml | 4 +- examples/tokio-fetch/Cargo.toml | 6 +- 8 files changed, 910 insertions(+), 410 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 606861d..bff8dc0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,23 +1,12 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - -[[package]] -name = "ahash" -version = "0.7.6" +name = "adler2" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" -dependencies = [ - "getrandom", - "once_cell", - "version_check", -] +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "async-sqlite" @@ -28,52 +17,56 @@ dependencies = [ ] [[package]] -name = "autocfg" -version = "1.1.0" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "base64" -version = "0.13.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" -version = "1.3.2" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" [[package]] name = "bytes" -version = "1.1.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" [[package]] name = "cc" -version = "1.0.73" +version = "1.2.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "cd405d82c84ff7f35739f175f67d8b9fb7687a0e84ccdc78bd3568839827cf07" +dependencies = [ + "find-msvc-tools", + "shlex", +] [[package]] name = "cfg-if" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[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", @@ -81,9 +74,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpu-count" @@ -95,27 +88,60 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "encoding_rs" -version = "0.8.31" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + [[package]] name = "fallible-iterator" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fallible-streaming-iterator" @@ -125,18 +151,21 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" [[package]] name = "fastrand" -version = "1.7.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" -dependencies = [ - "instant", -] +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "find-msvc-tools" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844" [[package]] name = "flate2" -version = "1.0.24" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", "miniz_oxide", @@ -148,6 +177,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + [[package]] name = "foreign-types" version = "0.3.2" @@ -165,46 +200,45 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", ] [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-task", @@ -214,15 +248,27 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ "cfg-if", "libc", "wasi", ] +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi", + "wasip2", +] + [[package]] name = "gzip-stream" version = "0.1.0" @@ -233,15 +279,15 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.17" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66b91535aa35fea1523ad1b86cb6b53c28e0ae566ba4a460f4457e936cad7c6f" +checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http", "indexmap", "slab", @@ -252,26 +298,26 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ - "ahash", + "foldhash", ] [[package]] name = "hashbrown" -version = "0.12.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "hashlink" -version = "0.7.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7249a3129cbc1ffccd74857f81464a323a152173cdb134e0fd81bc803b29facf" +checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" dependencies = [ - "hashbrown 0.11.2", + "hashbrown 0.15.5", ] [[package]] @@ -283,222 +329,376 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.19" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "http" -version = "0.2.8" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] [[package]] name = "http-body" -version = "0.4.5" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http", - "pin-project-lite", ] [[package]] -name = "httparse" -version = "1.7.1" +name = "http-body-util" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] [[package]] -name = "httpdate" -version = "1.0.2" +name = "httparse" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "0.14.20" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ + "atomic-waker", "bytes", "futures-channel", "futures-core", - "futures-util", "h2", "http", "http-body", "httparse", - "httpdate", "itoa", "pin-project-lite", - "socket2", + "pin-utils", + "smallvec", "tokio", - "tower-service", - "tracing", "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-tls" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", + "http-body-util", "hyper", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", ] [[package]] name = "idna" -version = "0.2.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "idna_adapter", + "smallvec", + "utf8_iter", ] [[package]] -name = "indexmap" -version = "1.9.1" +name = "idna_adapter" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" dependencies = [ - "autocfg", - "hashbrown 0.12.1", + "icu_normalizer", + "icu_properties", ] [[package]] -name = "instant" -version = "0.1.12" +name = "indexmap" +version = "2.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" dependencies = [ - "cfg-if", + "equivalent", + "hashbrown 0.16.1", ] [[package]] name = "ipnet" -version = "2.5.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +dependencies = [ + "memchr", + "serde", +] [[package]] name = "itoa" -version = "1.0.2" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "js-sys" -version = "0.3.58" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +checksum = "b011eec8cc36da2aab2d5cff675ec18454fad408585853910a202391cf9f8e65" dependencies = [ + "once_cell", "wasm-bindgen", ] -[[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.152" +version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" +checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-link", ] [[package]] name = "libsqlite3-sys" -version = "0.22.2" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290b64917f8b0cb885d9de0f9959fe1f775d7fa12f1da2db9001c1c8ab60f89d" +checksum = "133c182a6a2c87864fe97778797e46c7e999672690dc9fa3ee8e241aa4a9c13f" dependencies = [ "pkg-config", "vcpkg", ] [[package]] -name = "log" -version = "0.4.17" +name = "linkme" +version = "0.3.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +checksum = "5e3283ed2d0e50c06dd8602e0ab319bb048b6325d0bba739db64ed8205179898" dependencies = [ - "cfg-if", + "linkme-impl", ] [[package]] -name = "matches" -version = "0.1.9" +name = "linkme-impl" +version = "0.3.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" +checksum = "e5cec0ec4228b4853bb129c84dbf093a27e6c7a20526da046defc334a1b017f7" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "linux-raw-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "log" +version = "0.4.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" [[package]] name = "memchr" -version = "2.5.0" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "mime" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ - "adler", + "adler2", + "simd-adler32", ] [[package]] name = "mio" -version = "0.8.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873" dependencies = [ "libc", - "log", "wasi", - "windows-sys 0.36.1", + "windows-sys 0.61.2", ] [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -512,33 +712,38 @@ dependencies = [ [[package]] name = "neon" -version = "1.0.0" -source = "git+https://github.com/neon-bindings/neon.git#d6db6ed51008d358e9de9933080793325029d5a4" +version = "1.2.0-alpha.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b369318a3f63d9fbc7e663bb04be2fbf13ab4c8bbc8b185ea9dc7988529295e8" dependencies = [ - "getrandom", + "either", + "getrandom 0.2.16", "libloading", + "linkme", "neon-macros", "once_cell", "semver", "send_wrapper", "smallvec", + "tokio", ] [[package]] name = "neon-macros" -version = "1.0.0" -source = "git+https://github.com/neon-bindings/neon.git#d6db6ed51008d358e9de9933080793325029d5a4" +version = "1.2.0-alpha.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89e910c030108900f00779b4326f02c022b28e765382d32487b6d091a6cad48" dependencies = [ + "proc-macro2", "quote", - "syn 2.0.48", - "syn-mid", + "syn", ] [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ "hermit-abi", "libc", @@ -546,15 +751,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ "bitflags", "cfg-if", @@ -567,28 +772,27 @@ dependencies = [ [[package]] name = "openssl-macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 1.0.98", + "syn", ] [[package]] name = "openssl-probe" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.74" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ - "autocfg", "cc", "libc", "pkg-config", @@ -597,15 +801,15 @@ dependencies = [ [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -615,119 +819,183 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" [[package]] -name = "proc-macro2" -version = "1.0.78" +name = "potential_utf" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ - "unicode-ident", + "zerovec", ] [[package]] -name = "quote" -version = "1.0.35" +name = "proc-macro2" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8" dependencies = [ - "proc-macro2", + "unicode-ident", ] [[package]] -name = "redox_syscall" -version = "0.2.13" +name = "quote" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f" dependencies = [ - "bitflags", + "proc-macro2", ] [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "r-efi" +version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi", -] +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" [[package]] name = "reqwest" -version = "0.11.11" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" dependencies = [ "base64", "bytes", "encoding_rs", "futures-core", - "futures-util", "h2", "http", "http-body", + "http-body-util", "hyper", + "hyper-rustls", "hyper-tls", - "ipnet", + "hyper-util", "js-sys", - "lazy_static", "log", "mime", "native-tls", "percent-encoding", "pin-project-lite", + "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "tokio", "tokio-native-tls", + "tower", + "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", ] [[package]] name = "rusqlite" -version = "0.25.4" +version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c4b1eaf239b47034fb450ee9cdedd7d0226571689d8823030c4b6c2cb407152" +checksum = "165ca6e57b20e1351573e3729b958bc62f0e48025386970b6e4d29e7a7e71f3f" dependencies = [ "bitflags", "fallible-iterator", "fallible-streaming-iterator", "hashlink", "libsqlite3-sys", - "memchr", "smallvec", ] +[[package]] +name = "rustix" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e" +dependencies = [ + "bitflags", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "lazy_static", - "windows-sys 0.36.1", + "windows-sys 0.61.2", ] [[package]] name = "security-framework" -version = "2.6.1" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ "bitflags", "core-foundation", @@ -738,9 +1006,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -748,9 +1016,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.21" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "send_wrapper" @@ -760,33 +1028,45 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.138" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1578c6245786b9d168c5447eeacfb96856573ca56c9d68fdcf394be134882a47" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.138" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "023e9b1467aef8a10fb88f25611870ada9800ef7e22afce356bb0d2387b6f27c" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 1.0.98", + "syn", ] [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "itoa", + "memchr", "ryu", "serde", + "serde_core", ] [[package]] @@ -801,33 +1081,57 @@ dependencies = [ "serde", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "simd-adler32" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" + [[package]] name = "slab" -version = "0.4.6" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" [[package]] name = "smallvec" -version = "1.13.1" +version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.4.4" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "winapi", + "windows-sys 0.60.2", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" -version = "1.0.98" +version = "2.0.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87" dependencies = [ "proc-macro2", "quote", @@ -835,71 +1139,81 @@ dependencies = [ ] [[package]] -name = "syn" -version = "2.0.48" +name = "sync_wrapper" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", + "futures-core", ] [[package]] -name = "syn-mid" -version = "0.6.0" +name = "synstructure" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5dc35bb08dd1ca3dfb09dce91fd2d13294d6711c88897d9a9d60acf39bce049" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.48", + "syn", ] [[package]] -name = "tempfile" -version = "3.3.0" +name = "system-configuration" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" dependencies = [ - "cfg-if", - "fastrand", + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", "libc", - "redox_syscall", - "remove_dir_all", - "winapi", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tempfile" +version = "3.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16" dependencies = [ - "tinyvec_macros", + "fastrand", + "getrandom 0.3.4", + "once_cell", + "rustix", + "windows-sys 0.61.2", ] [[package]] -name = "tinyvec_macros" -version = "0.1.0" +name = "tinystr" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] [[package]] name = "tokio" -version = "1.20.3" +version = "1.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "664cf6576f16c0ad68184998f3c2d4be9903ede6b291a5b5cfc97d29e0057283" +checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ - "autocfg", "bytes", "libc", - "memchr", "mio", - "num_cpus", "pin-project-lite", "socket2", - "winapi", + "windows-sys 0.61.2", ] [[package]] @@ -915,163 +1229,198 @@ dependencies = [ [[package]] name = "tokio-native-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", +] + [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.28" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" dependencies = [ "once_cell", ] [[package]] name = "try-lock" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" - -[[package]] -name = "unicode-bidi" -version = "0.3.8" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" [[package]] -name = "unicode-normalization" -version = "0.1.21" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" -dependencies = [ - "tinyvec", -] +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.2.2" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", + "serde", ] [[package]] -name = "vcpkg" -version = "0.2.15" +name = "utf8_iter" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] -name = "version_check" -version = "0.9.4" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] [[package]] name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" +version = "0.11.1+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasm-bindgen" -version = "0.2.81" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "cfg-if", - "wasm-bindgen-macro", + "wit-bindgen", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.81" +name = "wasm-bindgen" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ - "bumpalo", - "lazy_static", - "log", - "proc-macro2", - "quote", - "syn 1.0.98", + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.31" +version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" +checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.81" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +checksum = "04264334509e04a7bf8690f2384ef5265f05143a4bff3889ab7a3269adab59c2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1079,169 +1428,318 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.81" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +checksum = "420bc339d9f322e562942d52e115d57e950d12d88983a14c79b86859ee6c7ebc" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 1.0.98", - "wasm-bindgen-backend", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.81" +version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +checksum = "76f218a38c84bcb33c25ec7059b07847d465ce0e0a76b995e134a45adcb6af76" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.58" +version = "0.3.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" +checksum = "3a1f95c0d03a47f4ae1f7a64643a6bb97465d9b740f0fa8f90ea33915c99a9a1" dependencies = [ "js-sys", "wasm-bindgen", ] [[package]] -name = "winapi" -version = "0.3.9" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-registry" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", + "windows-link", ] [[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" +name = "windows-strings" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link", +] [[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] [[package]] name = "windows-sys" -version = "0.36.1" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.48.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-targets", + "windows-link", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "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", - "windows_x86_64_msvc 0.48.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" -version = "0.36.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "wit-bindgen" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" + +[[package]] +name = "writeable" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" [[package]] -name = "winreg" -version = "0.10.1" +name = "zerotrie" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ - "winapi", + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] diff --git a/Cargo.toml b/Cargo.toml index 972500d..9b84d7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "3" members = [ "examples/async-sqlite", "examples/cpu-count", @@ -7,8 +8,9 @@ members = [ "examples/tokio-fetch", ] +[workspace.dependencies.neon] +version = "1.2.0-alpha.0" +features = ["tokio"] + [profile.release] lto = true - -[patch.crates-io] -neon = { git = "https://github.com/neon-bindings/neon.git" } diff --git a/examples/async-sqlite/Cargo.toml b/examples/async-sqlite/Cargo.toml index ebc9cb3..e5ef213 100644 --- a/examples/async-sqlite/Cargo.toml +++ b/examples/async-sqlite/Cargo.toml @@ -3,12 +3,12 @@ name = "async-sqlite" version = "0.1.0" description = "Neon Async SQLite" license = "MIT" -edition = "2018" +edition = "2024" exclude = ["index.node"] [lib] crate-type = ["cdylib"] [dependencies] -neon = "1" -rusqlite = "0.25" +neon.workspace = true +rusqlite = "0.37.0" diff --git a/examples/cpu-count/Cargo.toml b/examples/cpu-count/Cargo.toml index e32f9ef..6f40f30 100644 --- a/examples/cpu-count/Cargo.toml +++ b/examples/cpu-count/Cargo.toml @@ -3,12 +3,12 @@ name = "cpu-count" version = "0.1.0" description = "CPU Count" license = "MIT" -edition = "2018" +edition = "2024" exclude = ["index.node"] [lib] crate-type = ["cdylib"] [dependencies] -neon = "1" +neon.workspace = true num_cpus = "1" diff --git a/examples/gzip-stream/Cargo.toml b/examples/gzip-stream/Cargo.toml index 1c63c44..0dc24e0 100644 --- a/examples/gzip-stream/Cargo.toml +++ b/examples/gzip-stream/Cargo.toml @@ -3,7 +3,7 @@ name = "gzip-stream" version = "0.1.0" description = "Neon Stream Example" license = "MIT" -edition = "2018" +edition = "2024" exclude = ["index.node"] [lib] @@ -11,4 +11,4 @@ crate-type = ["cdylib"] [dependencies] flate2 = "1" -neon = "1" +neon.workspace = true diff --git a/examples/gzip-stream/src/lib.rs b/examples/gzip-stream/src/lib.rs index 910f9f9..546e94d 100644 --- a/examples/gzip-stream/src/lib.rs +++ b/examples/gzip-stream/src/lib.rs @@ -3,9 +3,9 @@ use std::fmt; use std::io::{self, Write}; use std::sync::{Arc, Mutex, MutexGuard, TryLockError}; -use flate2::{write::GzEncoder, Compression}; +use flate2::{Compression, write::GzEncoder}; use neon::prelude::*; -use neon::types::{buffer::TypedArray, JsUint8Array}; +use neon::types::{JsUint8Array, buffer::TypedArray}; use std::fmt::Debug; #[derive(Clone)] @@ -31,7 +31,7 @@ impl CompressStream { } // Attempt to obtain a mutable reference to the stream - fn lock(&self) -> Result>>, CompressError> { + fn lock(&self) -> Result>>, CompressError> { // Use `try_lock` instead of `lock` because multiple concurrent calls // to the encoder is undefined. The caller *must* be careful to serially // write to the stream. `Transform` provides this guarantee by applying diff --git a/examples/hello-world/Cargo.toml b/examples/hello-world/Cargo.toml index a28786a..63a11d9 100644 --- a/examples/hello-world/Cargo.toml +++ b/examples/hello-world/Cargo.toml @@ -3,11 +3,11 @@ name = "hello-world" version = "0.1.0" description = "Neon Hello World" license = "MIT" -edition = "2018" +edition = "2024" exclude = ["index.node"] [lib] crate-type = ["cdylib"] [dependencies] -neon = "1" +neon.workspace = true diff --git a/examples/tokio-fetch/Cargo.toml b/examples/tokio-fetch/Cargo.toml index 5cbbfcc..0c6ba89 100644 --- a/examples/tokio-fetch/Cargo.toml +++ b/examples/tokio-fetch/Cargo.toml @@ -3,15 +3,15 @@ name = "tokio-fetch" version = "0.1.0" description = "Neon Tokio and Rust Async Example" license = "MIT" -edition = "2018" +edition = "2024" exclude = ["index.node"] [lib] crate-type = ["cdylib"] [dependencies] -neon = "1" +neon.workspace = true once_cell = "1" -reqwest = { version = "0.11", features = ["json"] } +reqwest = { version = "0.12.24", features = ["json"] } tokio = { version = "1", features = ["rt-multi-thread"] } serde = { version = "1", features = ["derive"] } From ef0f9c8cde445d086556d21da956d6590ae5e602 Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 24 Nov 2025 15:34:54 -0500 Subject: [PATCH 02/10] Remove references to legacy branch --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index ebfcf72..706f87c 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,7 @@ Examples and common patterns for [Neon][neon]. -All examples are for [`napi-backend`][napi-migration]. For examples using `legacy-backend` see the [`legacy`][legacy] branch. - [neon]: https://github.com/neon-bindings/neon -[napi-migration]: https://github.com/neon-bindings/neon/blob/main/MIGRATION_GUIDE.md#n-api-migration-guide -[legacy]: https://github.com/neon-bindings/examples/tree/legacy ## Table of Contents From 30c73cf390d3909df3ed2dbe0f416a4071d0f5a9 Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 17 Nov 2025 13:03:58 -0500 Subject: [PATCH 03/10] Update cargo-cp-artifact version --- package-lock.json | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index c4bbea7..72ad69b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -173,10 +173,11 @@ } }, "node_modules/cargo-cp-artifact": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz", - "integrity": "sha512-CQw0doK/aaF7j041666XzuilHxqMxaKkn+I5vmBsd8SAwS0cO5CqVEVp0xJwOKstyqWZ6WK4Ww3O6p26x/Goyg==", + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.9.tgz", + "integrity": "sha512-6F+UYzTaGB+awsTXg0uSJA1/b/B3DDJzpKVRu0UmyI7DmNeaAl2RFHuTGIN6fEgpadRxoXGb7gbC1xo4C3IdyA==", "dev": true, + "license": "MIT", "bin": { "cargo-cp-artifact": "bin/cargo-cp-artifact.js" } @@ -1087,9 +1088,9 @@ "dev": true }, "cargo-cp-artifact": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.6.tgz", - "integrity": "sha512-CQw0doK/aaF7j041666XzuilHxqMxaKkn+I5vmBsd8SAwS0cO5CqVEVp0xJwOKstyqWZ6WK4Ww3O6p26x/Goyg==", + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/cargo-cp-artifact/-/cargo-cp-artifact-0.1.9.tgz", + "integrity": "sha512-6F+UYzTaGB+awsTXg0uSJA1/b/B3DDJzpKVRu0UmyI7DmNeaAl2RFHuTGIN6fEgpadRxoXGb7gbC1xo4C3IdyA==", "dev": true }, "chalk": { From 13ac5eed64b8123f28677ecfd298a76825f0a0f8 Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 17 Nov 2025 12:47:17 -0500 Subject: [PATCH 04/10] Update hello-world --- examples/hello-world/src/lib.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/examples/hello-world/src/lib.rs b/examples/hello-world/src/lib.rs index 9fd52d6..34aca52 100644 --- a/examples/hello-world/src/lib.rs +++ b/examples/hello-world/src/lib.rs @@ -1,11 +1,4 @@ -use neon::prelude::*; - -fn hello(mut cx: FunctionContext) -> JsResult { - Ok(cx.string("hello node")) -} - -#[neon::main] -fn main(mut cx: ModuleContext) -> NeonResult<()> { - cx.export_function("hello", hello)?; - Ok(()) +#[neon::export] +fn hello() -> &'static str { + "hello node" } From dda8646907cc6d12c1641effb70bc4447651cfcd Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 17 Nov 2025 12:48:49 -0500 Subject: [PATCH 05/10] Update cpu-count --- examples/cpu-count/README.md | 4 ++-- examples/cpu-count/src/lib.rs | 13 +++---------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/examples/cpu-count/README.md b/examples/cpu-count/README.md index 7b2e79c..7444d01 100644 --- a/examples/cpu-count/README.md +++ b/examples/cpu-count/README.md @@ -5,7 +5,7 @@ The `cpu-count` example exposes a single function named `get` that returns the n ## Usage ```js -const cpuCount = require("."); +const { getNumCpus } = require("."); -console.log(cpuCount.get()); +console.log(getNumCpus()); ``` diff --git a/examples/cpu-count/src/lib.rs b/examples/cpu-count/src/lib.rs index f8b79bd..42385c1 100644 --- a/examples/cpu-count/src/lib.rs +++ b/examples/cpu-count/src/lib.rs @@ -1,11 +1,4 @@ -use neon::prelude::*; - -fn get_num_cpus(mut cx: FunctionContext) -> JsResult { - Ok(cx.number(num_cpus::get() as f64)) -} - -#[neon::main] -fn main(mut cx: ModuleContext) -> NeonResult<()> { - cx.export_function("get", get_num_cpus)?; - Ok(()) +#[neon::export] +fn get_num_cpus() -> f64 { + num_cpus::get() as f64 } From 3566ca52332bc619ecb11e8a17ab0cc0569c3cf6 Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 17 Nov 2025 13:06:07 -0500 Subject: [PATCH 06/10] Update tokio-fetch --- Cargo.lock | 2 - examples/tokio-fetch/Cargo.toml | 2 - examples/tokio-fetch/src/lib.rs | 85 +++++++-------------------------- 3 files changed, 16 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bff8dc0..0a8a0fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1221,10 +1221,8 @@ name = "tokio-fetch" version = "0.1.0" dependencies = [ "neon", - "once_cell", "reqwest", "serde", - "tokio", ] [[package]] diff --git a/examples/tokio-fetch/Cargo.toml b/examples/tokio-fetch/Cargo.toml index 0c6ba89..f112154 100644 --- a/examples/tokio-fetch/Cargo.toml +++ b/examples/tokio-fetch/Cargo.toml @@ -11,7 +11,5 @@ crate-type = ["cdylib"] [dependencies] neon.workspace = true -once_cell = "1" reqwest = { version = "0.12.24", features = ["json"] } -tokio = { version = "1", features = ["rt-multi-thread"] } serde = { version = "1", features = ["derive"] } diff --git a/examples/tokio-fetch/src/lib.rs b/examples/tokio-fetch/src/lib.rs index 672249b..096b7d8 100644 --- a/examples/tokio-fetch/src/lib.rs +++ b/examples/tokio-fetch/src/lib.rs @@ -1,7 +1,5 @@ -use neon::prelude::*; -use once_cell::sync::OnceCell; +use neon::{prelude::*, types::extract::Error}; use serde::Deserialize; -use tokio::runtime::Runtime; #[derive(Deserialize)] struct NodeRelease { @@ -9,24 +7,6 @@ struct NodeRelease { date: String, } -// Return a global tokio runtime or create one if it doesn't exist. -// Throws a JavaScript exception if the `Runtime` fails to create. -fn runtime<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static Runtime> { - static RUNTIME: OnceCell = OnceCell::new(); - - RUNTIME.get_or_try_init(|| Runtime::new().or_else(|err| cx.throw_error(err.to_string()))) -} - -// Get the version of the currently running node process from [`process.version`](https://nodejs.org/api/process.html#processversion) -fn node_version<'a, C: Context<'a>>(cx: &mut C) -> NeonResult { - let version = cx - .global::("process")? - .get::(cx, "version")? - .value(cx); - - Ok(version) -} - // Asynchronously fetch the list of Node releases. This will execute on the `tokio` // thread pool. async fn fetch_node_releases() -> Result, reqwest::Error> { @@ -46,55 +26,22 @@ async fn fetch_node_release(version: &str) -> Result, reqwes Ok(version) } -// Get the release date of the currently running Node process. -// Returns a `Promise` and executes asynchronously on the `tokio` -// thread pool. -fn node_release_date(mut cx: FunctionContext) -> JsResult { - let rt = runtime(&mut cx)?; - let version = node_version(&mut cx)?; - let channel = cx.channel(); - - // Create a JavaScript promise and a `deferred` handle for resolving it. - // It is important to be careful not to perform failable actions after - // creating the promise to avoid an unhandled rejection. - let (deferred, promise) = cx.promise(); - - // Spawn an `async` task on the tokio runtime. Only Rust types that are - // `Send` may be moved into this block. `Context` may not be passed and all - // JavaScript values must first be converted to Rust types. - // - // This task will _not_ block the JavaScript main thread. - rt.spawn(async move { - // Inside this block, it is possible to `await` Rust `Future` - let release = fetch_node_release(&version).await; - - // Settle the promise from the result of a closure. JavaScript exceptions - // will be converted to a Promise rejection. - // - // This closure will execute on the JavaScript main thread. It should be - // limited to converting Rust types to JavaScript values. Expensive operations - // should be performed outside of it. - deferred.settle_with(&channel, move |mut cx| { - // Convert a `reqwest::Error` to a JavaScript exception - let release = release.or_else(|err| cx.throw_error(err.to_string()))?; - - match release { - // Resolve the promise with the release date - Some(release) => Ok(cx.string(release.date)), - - // Reject the `Promise` if the version could not be found - None => cx.throw_error(format!("Could not find version: {}", version)), - } - }); - }); - - // Return the promise back to JavaScript - Ok(promise) +// Get the version of the currently running node process from [`process.version`](https://nodejs.org/api/process.html#processversion) +fn node_version(cx: &mut Cx) -> NeonResult { + cx.global::("process")?.prop(cx, "version").get() } -#[neon::main] -fn main(mut cx: ModuleContext) -> NeonResult<()> { - cx.export_function("nodeReleaseDate", node_release_date)?; +#[neon::export(async)] +fn node_release_date( + cx: &mut Cx, +) -> NeonResult> + use<>> { + let version = node_version(cx)?; + + Ok(async move { + let release = fetch_node_release(&version) + .await? + .ok_or_else(|| format!("Could not find version: {version}"))?; - Ok(()) + Ok(release.date) + }) } From 0eca658930f132f76910bdb0ce65b932acb22082 Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 17 Nov 2025 13:57:12 -0500 Subject: [PATCH 07/10] Update gzip-stream --- examples/gzip-stream/README.md | 69 +++--------- examples/gzip-stream/index.js | 10 +- examples/gzip-stream/src/lib.rs | 184 ++++++-------------------------- 3 files changed, 55 insertions(+), 208 deletions(-) diff --git a/examples/gzip-stream/README.md b/examples/gzip-stream/README.md index fa75537..8c6ba42 100644 --- a/examples/gzip-stream/README.md +++ b/examples/gzip-stream/README.md @@ -25,17 +25,19 @@ The `flush` method allows any internally buffered data to be processed before co ```js function compress() { - const compressor = compressNew(); + const stream = new CompressStream(); return new Transform({ transform(chunk, encoding, callback) { - compressChunk(compressor, encoding, chunk) + stream + .compress(encoding, chunk) .then(data => callback(null, data)) .catch(callback); }, flush(callback) { - compressFinish(compressor) + stream + .finish() .then(data => callback(null, data)) .catch(callback); } @@ -43,64 +45,23 @@ function compress() { } ``` -The glue code exports a single function `compress` that creates a `Transform` stream delegating the implementation to Neon functions. Since these functions return promises, they are adapted to the `callback` style continuation that `Transform` expects. +The glue code exports a single function `compress` responsible for creating a `Transform` stream, delegating to the `CompressStream` class and adapting [`Promise`s](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) to callbacks. ## Neon -The Neon module exports three functions: +The Neon module exports a `CompressSteam` class with two methods: -* [`compressNew`](#compressnew) -* [`compressChunk`](#compresschunkcompressstream-chunk-encoding-callback) -* [`compressFinish`](#compressfinishcompressstream-callback) +* [`compress`](#compresschunk-encoding) +* [`finish`](#finish) -### `compressNew()` +### `new CompressStream(level)` -```rust -fn compress_new(mut cx: FunctionContext) -> JsResult> { - let stream = CompressStream::new(Compression::best()); +Creates a new instance of the `CompressStream` class with an optional gzip level. - Ok(cx.boxed(stream)) -} -``` - -`compressNew` creates an instance of the stateful Rust struct, `CompressStream`, and returns it wrapped in a [`JsBox`](https://docs.rs/neon/latest/neon/types/struct.JsBox.html). Each of the other two methods expects `CompressStream` as the first argument. This pattern is similar to using [`Function.prototype.call`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call) on a class method to manually bind `this`. - -### `compressChunk(compressStream, chunk, encoding, callback)` - -```rust -fn compress_chunk(mut cx: FunctionContext) -> JsResult { - let stream = (&**cx.argument::>(0)?).clone(); - let chunk = cx.argument::>(2)? - .as_slice(&cx) - .to_vec(); - - let promise = cx - .task(move || stream.write(chunk)) - .promise(CompressStream::and_buffer); - - Ok(promise) -} -``` - -`compressChunk` accepts the instance of the `CompressStream` struct and the other arguments to the [`transform`](#transformchunk-encoding-callback) function. The chunk is cloned to a `Vec` and passed to a task to execute on the Node worker pool. The asynchronous task compresses the data and passes the compressed data to the `.promise(|cx, result| { ... })` callback. The callback to `promise` is executed on the JavaScript main thread and converts the compressed `Vec` to a `JsBuffer` and resolves the promise. - -`CompressChunk::and_buffer` is used to create a `Buffer`. `ArrayBuffer` cannot be used because stream chunks are required to be an instance of `Uint8Array`. `Buffer` is a subclass of `Uint8Array`. - -### `compressFinish(compressStream, callback)` +### `compress(chunk, encoding)` -fn compress_finish(mut cx: FunctionContext) -> JsResult { -let stream = (&**cx.argument::>(0)?).clone(); +Compresses a chunk, returning flushed data as an `ArrayBuffer`. -```rust -fn compress_finish(mut cx: FunctionContext) -> JsResult { - let stream = (&**cx.argument::>(0)?).clone(); - - let promise = cx - .task(move || stream.finish()) - .promise(CompressStream::and_buffer); - - Ok(promise) -} -``` +### `finish()` -`compressFinish` works very similar to [`compressChunkl`](#compresschunkcompressstream-chunk-encoding-callback), except it is provided the arguments to [`flush`](#flushcallback) which does not include any data. Instead, the remaining buffered data is compressed, a CRC is calculated, and the compressed gzip data is completed. +`finish` works very similar to [`compress`](#compresschunk-encoding), except it is provided the arguments to [`flush`](#flushcallback) which does not include any data. Instead, the remaining buffered data is compressed, a CRC is calculated, and the compressed gzip data is completed. diff --git a/examples/gzip-stream/index.js b/examples/gzip-stream/index.js index 5bad914..82092e3 100644 --- a/examples/gzip-stream/index.js +++ b/examples/gzip-stream/index.js @@ -4,24 +4,26 @@ // source and produces new bytes for a destination sink. const { Transform } = require("stream"); -const { compressNew, compressChunk, compressFinish } = require("./index.node"); +const { CompressStream } = require("./index.node"); // Creates a gzip compression transform stream, implemented asynchronously in Rust function compress() { // Create a native streaming gzip compressing with Neon - const compressor = compressNew(); + const stream = new CompressStream(); return new Transform({ // Compress a chunk of data by delegating to `compressChunk` transform(chunk, encoding, callback) { - compressChunk(compressor, encoding, chunk) + stream + .compress(encoding, chunk) .then(data => callback(null, data)) .catch(callback); }, // Complete the compression by delegating to `compressFinish` flush(callback) { - compressFinish(compressor) + stream + .finish() .then(data => callback(null, data)) .catch(callback); } diff --git a/examples/gzip-stream/src/lib.rs b/examples/gzip-stream/src/lib.rs index 546e94d..cfca9ff 100644 --- a/examples/gzip-stream/src/lib.rs +++ b/examples/gzip-stream/src/lib.rs @@ -1,12 +1,10 @@ -use std::error::Error; -use std::fmt; -use std::io::{self, Write}; -use std::sync::{Arc, Mutex, MutexGuard, TryLockError}; +use std::{ + io::Write, + sync::{Arc, Mutex, MutexGuard}, +}; use flate2::{Compression, write::GzEncoder}; -use neon::prelude::*; -use neon::types::{JsUint8Array, buffer::TypedArray}; -use std::fmt::Debug; +use neon::types::extract::Error; #[derive(Clone)] // Holds state for a gzip compression stream @@ -20,9 +18,10 @@ struct CompressStream { encoder: Arc>>>, } +#[neon::export(class)] impl CompressStream { - // Create a new instance of a `CompressStream` - fn new(level: Compression) -> Self { + fn new(level: Option) -> Self { + let level = Compression::new(level.unwrap_or(9)); let encoder = GzEncoder::new(Vec::new(), level); Self { @@ -30,153 +29,38 @@ impl CompressStream { } } - // Attempt to obtain a mutable reference to the stream - fn lock(&self) -> Result>>, CompressError> { - // Use `try_lock` instead of `lock` because multiple concurrent calls - // to the encoder is undefined. The caller *must* be careful to serially - // write to the stream. `Transform` provides this guarantee by applying - // backpressure and buffering. The `Mutex` should always be unlocked. - Ok(self.encoder.try_lock()?) - } - - // Write a chunk of data to the encoder - fn write(self, data: Vec) -> Result { - self.lock()?.write_all(&data)?; - Ok(self) - } - - // Finish compressing. Multiple calls to this function will error or panic. - fn finish(self) -> Result { - self.lock()?.try_finish()?; - Ok(self) - } - - // After each call to `write` or `finish`, data may be written to the internal - // buffer. This function copies the written data out and resets the buffer - // to empty. - fn and_buffer( - mut cx: TaskContext, - // Return value from `cx.task(..)` closure - result: Result, - ) -> JsResult { - let stream = result.or_else(|err| cx.throw_error(err))?; - let mut guard = stream.lock().or_else(|err| cx.throw_error(err))?; - - let data = guard.get_mut(); - let output = JsUint8Array::from_slice(&mut cx, data)?; - - data.truncate(0); - - Ok(output) - } -} - -// Types placed in a `JsBox`, an opaque pointer for passing Rust data from Rust to -// JavaScript and back, must implement the `Finalize` trait. -// -// The `Finalize` trait optionally provides a hook for executing code when the value -// is garbage collected. -impl Finalize for CompressStream {} - -#[derive(Debug)] -// All errors will be converted to JavaScript exceptions with the `Display` -// implementation as the `Error` message. -struct CompressError(String); - -impl From for CompressError { - fn from(err: io::Error) -> Self { - Self(err.to_string()) - } -} - -impl From> for CompressError { - fn from(err: TryLockError) -> Self { - Self(err.to_string()) + #[neon(task)] + fn compress(self, _encoding: (), chunk: Vec) -> Result, Error> { + let mut guard = self.lock()?; + guard.write_all(&chunk)?; + Ok(next_chunk(&mut guard)) } -} -impl fmt::Display for CompressError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(&self.0) + #[neon(task)] + fn finish(self) -> Result, Error> { + let mut guard = self.lock()?; + guard.try_finish()?; + Ok(next_chunk(&mut guard)) } } -impl Error for CompressError {} - -impl AsRef for CompressError { - fn as_ref(&self) -> &str { - &self.0 +// Rust allows multiple `impl` blocks. Rust methods that should not be exposed to JavaScript +// can be written here. +impl CompressStream { + // Attempt to obtain a mutable reference to the stream + fn lock(&self) -> Result>>, Error> { + // Use `try_lock` instead of `lock` because multiple concurrent calls + // to the encoder is undefined. The caller *must* be careful to serially + // write to the stream. `Transform` provides this guarantee by applying + // backpressure and buffering. The `Mutex` should always be unlocked. + self.encoder + .try_lock() + .map_err(|_| Error::new("GzEncoder already locked")) } } -// Create a boxed `CompressStream` that can be passed to JavaScript and back -fn compress_new(mut cx: FunctionContext) -> JsResult> { - // Best compression because why not? - let stream = CompressStream::new(Compression::best()); - - // `cx.boxed` creates an opaque pointer that can cross the FFI boundary - Ok(cx.boxed(stream)) -} - -// Compress a chunk of data on the Node worker thread pool, returning a promise -// that may contain compressed data. -fn compress_chunk(mut cx: FunctionContext) -> JsResult { - // This is some funky syntax, but it's taking the first argument to the function, - // attempting to downcast it as a `JsBox` and finally calling - // the `Clone` implementation on `CompressStream`. The `&**` is due to a couple - // of smart pointers. Smart pointers are types that implement the - // [`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) trait. - // - // The outer type is `neon::handle::Handle`. `Handle` is a type used by Neon for - // ensuring that references to JavaScript values cannot be held after they have - // been garbage collected. The next type is `JsBox` which is a smart pointer for - // holding a reference to Rust data in JavaScript. The `**` dereferences these two - // types, giving a `CompressStream`. However, it's impossible to move out of a - // `JsBox`, so a reference is immediately taken with `&`. Finally, we can call the - // `clone` implementation on `CompressStream`. - let stream = (**cx.argument::>(0)?).clone(); - - // The 2nd argument is `encoding`. However, gzip is encoding agnostic and we do not need it. - // let encoding = cx.argument::(1)?; - - // Grab the 3rd argument as a `Uint8Array`. The data is immediately converted to a - // `Vec` by borrowing as a `&[u8]` and cloning. - let chunk = cx.argument::>(2)?.as_slice(&cx).to_vec(); - - let promise = cx - // Create a task to execute on the Node worker pool - .task(move || stream.write(chunk)) - // Convert the result of the task into an `ArrayBuffer` and resolve the promise - // on the JavaScript main thread. - .promise(CompressStream::and_buffer); - - Ok(promise) -} - -// Complete compressing the data and get the remaining output -fn compress_finish(mut cx: FunctionContext) -> JsResult { - // Get a shallow clone of `CompressStream`; same as in `compress_chunk` - // This is an alternative to the `**` syntax used earlier. Instead, it uses auto-deref - // and universal call syntax for the `clone` call to coerce to proper type. - let stream = CompressStream::clone(&*cx.argument::>(0)?); - - let promise = cx - // Finish the stream on the Node worker pool - .task(move || stream.finish()) - // Convert the remaining output into an `ArrayBuffer` and resolve the promise - // on the JavaScript main thread. - .promise(CompressStream::and_buffer); - - Ok(promise) -} - -#[neon::main] -// Called once when the module is loaded -fn main(mut cx: ModuleContext) -> NeonResult<()> { - // Export each of the Neon functions as part of the module - cx.export_function("compressNew", compress_new)?; - cx.export_function("compressChunk", compress_chunk)?; - cx.export_function("compressFinish", compress_finish)?; - - Ok(()) +fn next_chunk(encoder: &mut GzEncoder>) -> Vec { + let chunk = encoder.get_mut().clone(); + encoder.get_mut().truncate(0); + chunk } From 041e252fa437c4aee3e12ce3a5444e77f5226e58 Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Thu, 20 Nov 2025 08:03:51 -0500 Subject: [PATCH 08/10] Update async-sqlite --- examples/async-sqlite/README.md | 15 +- examples/async-sqlite/index.js | 29 --- examples/async-sqlite/package.json | 2 +- examples/async-sqlite/src/lib.rs | 244 +++++++++----------------- examples/async-sqlite/test/db.test.js | 7 +- 5 files changed, 90 insertions(+), 207 deletions(-) delete mode 100644 examples/async-sqlite/index.js diff --git a/examples/async-sqlite/README.md b/examples/async-sqlite/README.md index 5874479..218a2f9 100644 --- a/examples/async-sqlite/README.md +++ b/examples/async-sqlite/README.md @@ -5,7 +5,7 @@ The Async SQLite example implements a simple database in Rust with a JavaScript ## Usage ```js -const Database = require("."); +const { Database } = require("."); (async () => { const db = new Database(); @@ -31,25 +31,18 @@ Since SQLite is naturally single threaded, our application does not benefit from Once the database thread is spawned, the JavaScript main thread needs a way to communicate with it. A [multi-producer, single-consumer (mpsc)][mpsc] channel is created. The receiving end is owned by the database thread and the sender is held by JavaScript. -#### `JsBox` +#### `#[neon::export(class)]` -Rust data cannot be directly held by JavaScript. The [`JsBox`][jsbox] provides a mechanism for allowing JavaScript to hold a reference to Rust data and later access it again from Rust. +The Rust sender side of the channel is held in a JavaScript [class][class]. It can be referenced later in methods. #### Rust and Neon Channels The mpsc channel provides a way for the JavaScript main thread to communicate with the database thread, but it is one-way. In order to complete the callback, the database thread must be able to communicate with the JavaScript main thread. [`neon::event::Channel`][channel] provides a channel for sending these events back. -#### `Root` - -The last issue to solve is sending a reference to the JavaScript callback to the database thread and back again before finally calling it. [Handles][handle] to JavaScript values are not `Send`; they cannot escape the scope that created them. The reason they cannot be passed to other threads is because when control is returned back to the JavaScript engine, the garbage collector may determine they are no longer used and free the value. - -A [`Root`][root] is a special handle to a JavaScript value that prevents the value from being freed as long as the `Root` has not been dropped. By placing the callback in a `Root`, it can be safely sent across threads and finally accessed and called when back on the JavaScript main thread. - ### JavaScript [thread]: https://doc.rust-lang.org/std/thread/ [mpsc]: https://doc.rust-lang.org/std/sync/mpsc/index.html -[jsbox]: https://docs.rs/neon/latest/neon/types/struct.JsBox.html +[class]: https://docs.rs/neon/latest/neon/attr.class.html [channel]: https://docs.rs/neon/latest/neon/event/struct.Channel.html [handle]: https://docs.rs/neon/latest/neon/handle/struct.Handle.html -[root]: https://docs.rs/neon/latest/neon/handle/struct.Root.html diff --git a/examples/async-sqlite/index.js b/examples/async-sqlite/index.js deleted file mode 100644 index dccd726..0000000 --- a/examples/async-sqlite/index.js +++ /dev/null @@ -1,29 +0,0 @@ -"use strict"; - -const { promisify } = require("util"); - -const { databaseNew, databaseClose, databaseInsert, databaseGetById } = require("./index.node"); - -// Wrapper class for the boxed `Database` for idiomatic JavaScript usage -class Database { - constructor() { - this.db = databaseNew(); - } - - // Wrap each method with a delegate to `this.db` - // This could be done in several other ways, for example binding assignment - // in the constructor - insert(name) { - return databaseInsert.call(this.db, name); - } - - byId(id) { - return databaseGetById.call(this.db, id); - } - - close() { - databaseClose.call(this.db); - } -} - -module.exports = Database; diff --git a/examples/async-sqlite/package.json b/examples/async-sqlite/package.json index 2f3ef0f..0e40c32 100644 --- a/examples/async-sqlite/package.json +++ b/examples/async-sqlite/package.json @@ -2,7 +2,7 @@ "name": "async-sqlite", "version": "0.1.0", "description": "Neon Async SQLite", - "main": "index.js", + "main": "index.node", "scripts": { "build": "cargo-cp-artifact -nc index.node -- cargo build --message-format=json-render-diagnostics", "install": "npm run build", diff --git a/examples/async-sqlite/src/lib.rs b/examples/async-sqlite/src/lib.rs index 5a7293e..53347b9 100644 --- a/examples/async-sqlite/src/lib.rs +++ b/examples/async-sqlite/src/lib.rs @@ -1,44 +1,70 @@ -use std::sync::mpsc; -use std::thread; +use std::{ops::ControlFlow, sync::mpsc, thread}; + +use neon::{ + prelude::*, + types::Deferred, + types::extract::{Error, TryIntoJs}, +}; -use neon::{prelude::*, types::Deferred}; use rusqlite::Connection; -type DbCallback = Box; +type DbCallback = + Box ControlFlow<(), ()> + Send>; // Wraps a SQLite connection a channel, allowing concurrent access struct Database { - tx: mpsc::Sender, -} - -// Messages sent on the database channel -enum DbMessage { - // Promise to resolve and callback to be executed - // Deferred is threaded through the message instead of moved to the closure so that it - // can be manually rejected. - Callback(Deferred, DbCallback), - // Indicates that the thread should be stopped and connection closed - Close, + tx: mpsc::Sender<(Deferred, DbCallback)>, } -// Clean-up when Database is garbage collected, could go here -// but, it's not needed, -impl Finalize for Database {} - // Internal implementation impl Database { - // Creates a new instance of `Database` - // - // 1. Creates a connection and a channel - // 2. Spawns a thread and moves the channel receiver and connection to it - // 3. On a separate thread, read closures off the channel and execute with access - // to the connection. - fn new<'a, C>(cx: &mut C) -> rusqlite::Result + fn exec<'cx, O, V, F>(&self, cx: &mut Cx<'cx>, f: F) -> JsResult<'cx, JsPromise> where - C: Context<'a>, + F: FnOnce(&mut Connection) -> O + Send + 'static, + for<'a> O: TryIntoJs<'a, Value = V> + Send + 'static, + V: Value, { + self.send(cx, |conn| ControlFlow::Continue(f(conn))) + } + + fn send<'cx, O, V, F>(&self, cx: &mut Cx<'cx>, f: F) -> JsResult<'cx, JsPromise> + where + F: FnOnce(&mut Connection) -> ControlFlow<(), O> + Send + 'static, + for<'a> O: TryIntoJs<'a, Value = V> + Send + 'static, + V: Value, + { + let (d, promise) = cx.promise(); + let Err(mpsc::SendError((d, _))) = self.tx.send(( + d, + Box::new(move |conn, ch, d| { + let output = f(conn).continue_value(); + let should_break = output.is_none(); + let res = d.try_settle_with(ch, move |mut cx| output.try_into_js(&mut cx)); + + // If we can no longer settle promises, we can stop the worker thread + if res.is_err() || should_break { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }), + )) else { + return Ok(promise); + }; + + let err = cx.error("Database is closed")?; + d.reject(cx, err); + + Ok(promise) + } +} + +#[neon::export(class)] +// JavaScript class +impl Database { + fn new(cx: &mut Cx) -> Result { // Channel for sending callbacks to execute on the sqlite connection thread - let (tx, rx) = mpsc::channel::(); + let (tx, rx) = mpsc::channel(); // Open a connection sqlite, this will be moved to the thread let mut conn = Connection::open_in_memory()?; @@ -48,6 +74,7 @@ impl Database { // The JavaScript process will not exit as long as this channel has not been // dropped. let channel = cx.channel(); + let db = Self { tx }; // Create a table in the in-memory database // In production code, this would likely be handled somewhere else @@ -69,155 +96,48 @@ impl Database { // When the instance of `Database` is dropped, the channel will be closed // and `rx.recv()` will return an `Err`, ending the loop and terminating // the thread. - while let Ok(message) = rx.recv() { - match message { - DbMessage::Callback(deferred, f) => { - // The connection and channel are owned by the thread, but _lent_ to - // the callback. The callback has exclusive access to the connection - // for the duration of the callback. - f(&mut conn, &channel, deferred); - } - // Immediately close the connection, even if there are pending messages - DbMessage::Close => break, + while let Ok((d, callback)) = rx.recv() { + // Returning `true` means to _stop_ + if callback(&mut conn, &channel, d).is_break() { + break; } } }); - Ok(Self { tx }) - } - - // Idiomatic rust would take an owned `self` to prevent use after close - // However, it's not possible to prevent JavaScript from continuing to hold a closed database - fn close(&self) -> Result<(), mpsc::SendError> { - self.tx.send(DbMessage::Close) - } - - fn send( - &self, - deferred: Deferred, - callback: impl FnOnce(&mut Connection, &Channel, Deferred) + Send + 'static, - ) -> Result<(), mpsc::SendError> { - self.tx - .send(DbMessage::Callback(deferred, Box::new(callback))) - } -} - -// Methods exposed to JavaScript -// The `JsBox` boxed `Database` is expected as the `this` value on all methods except `js_new` -impl Database { - // Create a new instance of `Database` and place it inside a `JsBox` - // JavaScript can hold a reference to a `JsBox`, but the contents are opaque - fn js_new(mut cx: FunctionContext) -> JsResult> { - let db = Database::new(&mut cx).or_else(|err| cx.throw_error(err.to_string()))?; - - Ok(cx.boxed(db)) - } - - // Manually close a database connection - // After calling `close`, all other methods will fail - // It is not necessary to call `close` since the database will be closed when the wrapping - // `JsBox` is garbage collected. However, calling `close` allows the process to exit - // immediately instead of waiting on garbage collection. This is useful in tests. - fn js_close(mut cx: FunctionContext) -> JsResult { - // Get the `this` value as a `JsBox` - cx.this::>()? - .close() - .or_else(|err| cx.throw_error(err.to_string()))?; - - Ok(cx.undefined()) + Ok(db) } // Inserts a `name` into the database // Accepts a `name` and returns a `Promise` - fn js_insert(mut cx: FunctionContext) -> JsResult { - // Get the first argument as a `JsString` and convert to a Rust `String` - let name = cx.argument::(0)?.value(&mut cx); - - // Get the `this` value as a `JsBox` - let db = cx.this::>()?; - let (deferred, promise) = cx.promise(); - - db.send(deferred, move |conn, channel, deferred| { - let result = conn - .execute( - "INSERT INTO person (name) VALUES (?)", - rusqlite::params![name], - ) - .map(|_| conn.last_insert_rowid()); - - deferred.settle_with(channel, move |mut cx| { - let id = result.or_else(|err| cx.throw_error(err.to_string()))?; - - Ok(cx.number(id as f64)) - }); + fn insert<'cx>(&self, cx: &mut Cx<'cx>, name: String) -> JsResult<'cx, JsPromise> { + self.exec(cx, move |conn| -> Result<_, Error> { + conn.execute( + "INSERT INTO person (name) VALUES (?)", + rusqlite::params![name], + )?; + + Ok(conn.last_insert_rowid() as f64) }) - .into_rejection(&mut cx)?; - - Ok(promise) } // Get a `name` by `id` value // Accepts an `id` and callback as parameters - fn js_get_by_id(mut cx: FunctionContext) -> JsResult { - // Get the first argument as a `JsNumber` and convert to an `f64` - let id = cx.argument::(0)?.value(&mut cx); - - // Get the `this` value as a `JsBox` - let db = cx.this::>()?; - let (deferred, promise) = cx.promise(); - - db.send(deferred, move |conn, channel, deferred| { - let result: Result = conn - .prepare("SELECT name FROM person WHERE id = ?") - .and_then(|mut stmt| stmt.query_row(rusqlite::params![id], |row| row.get(0))); - - deferred.settle_with(channel, move |mut cx| -> JsResult { - // If the row was not found, return `undefined` as a success instead - // of throwing an exception - if matches!(result, Err(rusqlite::Error::QueryReturnedNoRows)) { - return Ok(cx.undefined().upcast()); - } - - let name = result.or_else(|err| cx.throw_error(err.to_string()))?; - - Ok(cx.string(name).upcast()) - }); - }) - .into_rejection(&mut cx)?; - - Ok(promise) - } -} - -trait SendResultExt { - // Sending a query closure to execute may fail if the channel has been closed. - // This method converts the failure into a promise rejection. - fn into_rejection<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult<()>; -} - -impl SendResultExt for Result<(), mpsc::SendError> { - fn into_rejection<'a, C: Context<'a>>(self, cx: &mut C) -> NeonResult<()> { - self.or_else(|err| { - let msg = err.to_string(); - - match err.0 { - DbMessage::Callback(deferred, _) => { - let err = cx.error(msg)?; - deferred.reject(cx, err); - Ok(()) - } - DbMessage::Close => cx.throw_error("Expected DbMessage::Callback"), + fn by_id<'cx>(&self, cx: &mut Cx<'cx>, id: f64) -> JsResult<'cx, JsPromise> { + self.exec(cx, move |conn| -> Result, Error> { + match conn + .prepare("SELECT name FROM person WHERE id = ?")? + .query_row(rusqlite::params![id], |row| row.get(0)) + { + Ok(name) => Ok(Some(name)), + Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None), + Err(err) => Err(Error::from(err)), } }) } -} - -#[neon::main] -fn main(mut cx: ModuleContext) -> NeonResult<()> { - cx.export_function("databaseNew", Database::js_new)?; - cx.export_function("databaseClose", Database::js_close)?; - cx.export_function("databaseInsert", Database::js_insert)?; - cx.export_function("databaseGetById", Database::js_get_by_id)?; - Ok(()) + // Idiomatic rust would take an owned `self` to prevent use after close + // However, it's not possible to prevent JavaScript from continuing to hold a closed database + fn close<'cx>(&self, cx: &mut Cx<'cx>) -> JsResult<'cx, JsPromise> { + self.send(cx, |_| ControlFlow::<(), ()>::Break(())) + } } diff --git a/examples/async-sqlite/test/db.test.js b/examples/async-sqlite/test/db.test.js index 2ac1e12..fb4783d 100644 --- a/examples/async-sqlite/test/db.test.js +++ b/examples/async-sqlite/test/db.test.js @@ -2,7 +2,7 @@ const assert = require("assert"); -const Database = require(".."); +const { Database } = require(".."); describe("SQLite Database", () => { it("should insert and return name", async () => { @@ -27,8 +27,7 @@ describe("SQLite Database", () => { it("should reject calls to a closed database", async () => { const db = new Database(); - db.close(); - - await assert.rejects(() => db.byId(5), /closed channel/); + await db.close(); + await assert.rejects(() => db.byId(5), /closed/); }); }); From 67b4bc7f7d838acb2385ba0b8f37a78116d05978 Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 24 Nov 2025 13:04:19 -0500 Subject: [PATCH 09/10] Update tokio fetch --- examples/tokio-fetch/README.md | 72 +++++---------------------------- examples/tokio-fetch/src/lib.rs | 25 ++++++++---- 2 files changed, 28 insertions(+), 69 deletions(-) diff --git a/examples/tokio-fetch/README.md b/examples/tokio-fetch/README.md index 02d41b1..21eb6f1 100644 --- a/examples/tokio-fetch/README.md +++ b/examples/tokio-fetch/README.md @@ -2,77 +2,27 @@ Example of spawning a Rust async task on the [tokio][tokio] thread pool and resolving a JavaScript [Promise][promise] after it completes. -_**Note:** This example uses a pre-release version of Neon._ - [tokio]: https://tokio.rs [promise]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise ## Methods -#### `function nodeReleaseDate(): Promise` - -Asynchronously fetch the release date for the currently running Node process from nodejs.org. - -## Design - -### Executor - -For optimum task scheduling, it is best to have a single Rust task executor (e.g., tokio runtime). To make the runtime singleton available to Neon functions, it is stored in a global using `OnceCell`. - -```rust -use once_cell::sync::OnceCell; -use tokio::runtime::Runtime; - -static RUNTIME: OnceCell = OnceCell::new(); -``` +### `function nodeReleaseDate(version: string): Promise` -A small helper is provided to lazily initialize the runtime and throw an exception on failure. +Asynchronously fetch the release date for a given Node release from nodejs.org. -```rust -fn runtime<'a, C: Context<'a>>(cx: &mut C) -> NeonResult<&'static Runtime> { - RUNTIME.get_or_try_init(|| Runtime::new().or_else(|err| cx.throw_error(err.to_string()))) -} -``` +`nodeReleaseDate` is a Rust `async fn`. The argument uses [`TryFromJs`][tryfromjs] and return value uses [`TryIntoJs`][tryintojs] for ergonomic conversions. -### Spawning Tasks +### `function currentNodeReleaseDate(): Promise` -Tasks may be spawned on the tokio runtime by using the `RUNTIME` handle. Spawning a task does *not* block the current thread. Inside a task the `await` keyword may be used and typical async Rust patterns may be used. - -```rust -let rt = runtime(&mut cx)?; - -rt.spawn(async move { - // Asynchronous Rust may used in here -}); -``` - -### Promises - -When a task is spawned on the tokio runtime, it will be executed at a later time. JavaScript needs to be notified when the task completes. - -* Neon [`Channel`][channel] may be created for moving an operation from the tokio thread pool back to the JavaScript main thread. -* [`cx.promise()`][cx-promise] creates a [`JsPromise`][js-promise] and [`Deferred`][deferred] for signaling JavaScript. -* [`JsPromise`][js-promise] is synchronously returned and may be used with `await` in JavaScript -* [`Deferred`][deferred] is used to settle the [`JsPromise`][js-promise] from the [`Channel`][channel] callback. - -```rust -let channel = cx.channel(); -let (deferred, promise) = cx.promise(); - -rt.spawn(async move { - // Code here executes non-blocking on the tokio thread pool +Asynchronously fetch the release date for the currently running Node process from nodejs.org. - deferred.settle_with(&channel, move |mut cx| { - // Code here executes blocking on the JavaScript main thread +`currentNodeReleaseDate` needs to access the JavaScript VM synchronously in order to get the current Node version before spawning an async tokio task. - Ok(cx.undefined()) - }); -}); +Writing a _synchronous_ Rust `fn`, that returns a Rust future, allows synchronous setup code that uses [`Cx`][cx]. -Ok(promise) -``` +**Note**: The returned future is still required to be `Send + 'static`. -[channel]: https://docs.rs/neon/0.10.0-alpha.3/neon/event/struct.Channel.html -[cx-promise]: https://docs.rs/neon/0.10.0-alpha.3/neon/context/trait.Context.html#method.promise -[js-promise]: https://docs.rs/neon/0.10.0-alpha.3/neon/types/struct.JsPromise.html -[deferred]: https://docs.rs/neon/0.10.0-alpha.3/neon/types/struct.Deferred.html +[tryfromjs]: https://docs.rs/neon/latest/neon/types/extract/trait.TryFromJs.html +[tryintojs]: https://docs.rs/neon/latest/neon/types/extract/trait.TryIntoJs.html +[cx]: https://docs.rs/neon/latest/neon/context/struct.Cx.html diff --git a/examples/tokio-fetch/src/lib.rs b/examples/tokio-fetch/src/lib.rs index 096b7d8..98bc395 100644 --- a/examples/tokio-fetch/src/lib.rs +++ b/examples/tokio-fetch/src/lib.rs @@ -31,17 +31,26 @@ fn node_version(cx: &mut Cx) -> NeonResult { cx.global::("process")?.prop(cx, "version").get() } +// Export an async JavaScript function where the body is executed on the tokio thread pool +#[neon::export] +async fn node_release_date(version: String) -> Result { + let release = fetch_node_release(&version) + .await? + .ok_or_else(|| format!("Could not find version: {version}"))?; + + Ok(release.date) +} + +// Similar to `node_release_date`, but includes some setup code synchronously executed +// on the JavaScript main thread before return a task for tokio. Since this is not +// an `async fn`, we need to explicitly tell the export macro that it returns a future. #[neon::export(async)] -fn node_release_date( +fn current_node_release_date( cx: &mut Cx, ) -> NeonResult> + use<>> { + // Executes synchronously on the JavaScript main thread let version = node_version(cx)?; - Ok(async move { - let release = fetch_node_release(&version) - .await? - .ok_or_else(|| format!("Could not find version: {version}"))?; - - Ok(release.date) - }) + // This task is executed asynchronously on the tokio thread pool + Ok(node_release_date(version)) } From 8c5b3c6fb642335dd9f2860b6385a1db4211babc Mon Sep 17 00:00:00 2001 From: "K.J. Valencik" Date: Mon, 26 Jan 2026 12:28:12 -0500 Subject: [PATCH 10/10] Review comments --- examples/async-sqlite/src/lib.rs | 91 +++++++++++++++++----------- examples/gzip-stream/bin/compress.js | 2 - 2 files changed, 56 insertions(+), 37 deletions(-) diff --git a/examples/async-sqlite/src/lib.rs b/examples/async-sqlite/src/lib.rs index 53347b9..c852a55 100644 --- a/examples/async-sqlite/src/lib.rs +++ b/examples/async-sqlite/src/lib.rs @@ -8,12 +8,14 @@ use neon::{ use rusqlite::Connection; -type DbCallback = - Box ControlFlow<(), ()> + Send>; +// `DbTask` is a low level task that is executed on the database event loop thread. It +// is responsible for executing user-provided functions as well as terminating the event loop. +type DbTask = Box ControlFlow<(), ()> + Send>; -// Wraps a SQLite connection a channel, allowing concurrent access +// Wraps a channel to a SQLite connection, allowing concurrent access +// Note: The connection will be dropped when all senders have been dropped. struct Database { - tx: mpsc::Sender<(Deferred, DbCallback)>, + tx: mpsc::Sender<(Deferred, DbTask)>, } // Internal implementation @@ -33,29 +35,43 @@ impl Database { for<'a> O: TryIntoJs<'a, Value = V> + Send + 'static, V: Value, { - let (d, promise) = cx.promise(); - let Err(mpsc::SendError((d, _))) = self.tx.send(( - d, - Box::new(move |conn, ch, d| { - let output = f(conn).continue_value(); - let should_break = output.is_none(); - let res = d.try_settle_with(ch, move |mut cx| output.try_into_js(&mut cx)); - - // If we can no longer settle promises, we can stop the worker thread - if res.is_err() || should_break { - ControlFlow::Break(()) - } else { - ControlFlow::Continue(()) - } - }), - )) else { - return Ok(promise); - }; - - let err = cx.error("Database is closed")?; - d.reject(cx, err); + let (deferred, promise) = cx.promise(); + + // Create a callback that will execute on the database worker thread + let callback: DbTask = Box::new(move |conn, channel, deferred| { + // Execute the user's function + let control_flow_result = f(conn); + + // Check if the function requested to break the loop before extracting the value + let should_stop_worker = control_flow_result.is_break(); + + // Extract the output value + let output = control_flow_result.continue_value(); + + // Settle the promise with the output value + let settle_result = + deferred.try_settle_with(channel, move |mut cx| output.try_into_js(&mut cx)); + + // Stop the worker thread if: + // 1. We can no longer settle promises (channel closed), or + // 2. The function explicitly requested to break + if settle_result.is_err() || should_stop_worker { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }); - Ok(promise) + // Send the callback to the worker thread + match self.tx.send((deferred, callback)) { + Ok(_) => Ok(promise), + Err(mpsc::SendError((deferred, _))) => { + // Database is closed, reject the promise + let err = cx.error("Database is closed")?; + deferred.reject(cx, err); + Ok(promise) + } + } } } @@ -69,7 +85,7 @@ impl Database { // Open a connection sqlite, this will be moved to the thread let mut conn = Connection::open_in_memory()?; - // Create an `Channel` for calling back to JavaScript. It is more efficient + // Create a `Channel` for calling back to JavaScript. It is more efficient // to create a single channel and re-use it for all database callbacks. // The JavaScript process will not exit as long as this channel has not been // dropped. @@ -88,16 +104,16 @@ impl Database { [], )?; - // Spawn a thread for processing database queries + // Spawn a thread to act as the database event loop. // This will not block the JavaScript main thread and will continue executing // concurrently. thread::spawn(move || { - // Blocks until a callback is available - // When the instance of `Database` is dropped, the channel will be closed - // and `rx.recv()` will return an `Err`, ending the loop and terminating + // Blocks until a callback is available. + // When the instance of the `Database` class is dropped, the channel will be + // closed and `rx.recv()` will return an `Err`, ending the loop and terminating // the thread. while let Ok((d, callback)) = rx.recv() { - // Returning `true` means to _stop_ + // Returning `ControlFlow::Break` means to immediately _stop_ the loop and close the database connection if callback(&mut conn, &channel, d).is_break() { break; } @@ -108,9 +124,9 @@ impl Database { } // Inserts a `name` into the database - // Accepts a `name` and returns a `Promise` + // Accepts a `name` and returns a `Promise` fn insert<'cx>(&self, cx: &mut Cx<'cx>, name: String) -> JsResult<'cx, JsPromise> { - self.exec(cx, move |conn| -> Result<_, Error> { + self.exec(cx, move |conn| -> Result { conn.execute( "INSERT INTO person (name) VALUES (?)", rusqlite::params![name], @@ -135,8 +151,13 @@ impl Database { }) } + // Many more methods can be added here by using the simple `self.send(..)` pattern. + // Idiomatic rust would take an owned `self` to prevent use after close - // However, it's not possible to prevent JavaScript from continuing to hold a closed database + // However, it's not possible to prevent JavaScript from continuing to hold a closed database. + // Instead, we send a `ControlFlow::Break` to stop the loop and drop the `mpsc` channel. Once + // dropped, the channel will be closed and sending messages will result in an error. These + // errors will be converted into a `Promise` rejection. fn close<'cx>(&self, cx: &mut Cx<'cx>) -> JsResult<'cx, JsPromise> { self.send(cx, |_| ControlFlow::<(), ()>::Break(())) } diff --git a/examples/gzip-stream/bin/compress.js b/examples/gzip-stream/bin/compress.js index 611fba0..f3fdc2e 100755 --- a/examples/gzip-stream/bin/compress.js +++ b/examples/gzip-stream/bin/compress.js @@ -1,5 +1,3 @@ -#!/usr/bin/env node - "use strict"; const { pipeline } = require("stream");