diff --git a/Cargo.lock b/Cargo.lock index e1d1c322..7f61a75c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aead" @@ -29,9 +29,9 @@ dependencies = [ [[package]] name = "aes" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", @@ -54,9 +54,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -67,18 +67,45 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "android-activity" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" +dependencies = [ + "android-properties", + "bitflags 2.6.0", + "cc", + "cesu8", + "jni", + "jni-sys", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "num_enum", + "thiserror", +] + +[[package]] +name = "android-properties" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "android-tzdata" @@ -121,9 +148,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "arbitrary" @@ -136,15 +163,15 @@ dependencies = [ [[package]] name = "arc-swap" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" [[package]] name = "argon2" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ba4cac0a46bc1d2912652a751c47f2a9f3a7fe89bcae2275d418f5270402f9" +checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" dependencies = [ "base64ct", "blake2", @@ -230,10 +257,13 @@ dependencies = [ "hex", "hex-literal", "hmac", - "itertools 0.12.0", + "itertools 0.12.1", + "lazy_static", "log", + "odbc-api", "once_cell", "percent-encoding", + "r2d2", "rand", "rmp-serde", "serde", @@ -249,9 +279,9 @@ dependencies = [ [[package]] name = "asn1-rs" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ad1373757efa0f70ec53939aabc7152e1591cb485208052993070ac8d2429d" +checksum = "5493c3bedbacf7fd7382c6346bbd66687d12bbaad3a89a2d2c303ee6cf20b048" dependencies = [ "asn1-rs-derive", "asn1-rs-impl", @@ -265,13 +295,13 @@ dependencies = [ [[package]] name = "asn1-rs-derive" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7378575ff571966e99a744addeff0bff98b8ada0dedf1956d59e634db95eaac1" +checksum = "965c2d33e53cb6b267e148a4cb0760bc01f4904c1cd4bb4002a085bb016d1490" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", "synstructure", ] @@ -283,25 +313,25 @@ checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] [[package]] name = "async-lock" -version = "3.2.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7125e42787d53db9dd54261812ef17e937c95a51e4d291373b670342fa44310c" +checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" dependencies = [ - "event-listener 4.0.1", + "event-listener 5.3.1", "event-listener-strategy", "pin-project-lite", ] [[package]] name = "async-stream" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ "async-stream-impl", "futures-core", @@ -310,13 +340,13 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] [[package]] @@ -329,34 +359,30 @@ dependencies = [ ] [[package]] -name = "atomic-write-file" -version = "0.1.2" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edcdbedc2236483ab103a53415653d6b4442ea6141baf1ffa85df29635e88436" -dependencies = [ - "nix", - "rand", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -367,9 +393,9 @@ checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64ct" @@ -385,9 +411,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -425,6 +451,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +dependencies = [ + "objc2", +] + [[package]] name = "bls12_381" version = "0.8.0" @@ -440,18 +475,18 @@ dependencies = [ [[package]] name = "bs58" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5353f36341f7451062466f0b755b96ac3a9547e4d7f6b70d603fc721a7d7896" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" dependencies = [ "tinyvec", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byteorder" @@ -461,9 +496,23 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "calloop" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +dependencies = [ + "bitflags 2.6.0", + "log", + "polling", + "rustix", + "slab", + "thiserror", +] [[package]] name = "cast" @@ -482,11 +531,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" dependencies = [ + "jobserver", "libc", + "shlex", ] [[package]] @@ -501,6 +552,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chacha20" version = "0.9.1" @@ -527,23 +584,23 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] name = "ciborium" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ "ciborium-io", "ciborium-ll", @@ -552,18 +609,18 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] name = "ciborium-ll" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ "ciborium-io", - "half", + "half 2.4.1", ] [[package]] @@ -579,18 +636,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.11" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.4.11" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstyle", "clap_lex", @@ -598,9 +655,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "combine" @@ -614,9 +671,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -639,24 +696,48 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-graphics-types", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "libc", +] [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] [[package]] name = "crc" -version = "3.0.1" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86ec7a15cbe22e59248fc7eadb1907dab5ba09372595da4d73dd805ed4417dfe" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" dependencies = [ "crc-catalog", ] @@ -705,45 +786,43 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.16" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if", "crossbeam-utils", - "memoffset", ] [[package]] name = "crossbeam-queue" -version = "0.3.9" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9bcf5bdbfdd6030fb4a1c497b5d5fc5921aa2f60d359a17e249c0e6df3de153" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.17" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" [[package]] name = "crypto-bigint" @@ -806,18 +885,23 @@ dependencies = [ "cipher", ] +[[package]] +name = "cursor-icon" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" + [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", "cpufeatures", "curve25519-dalek-derive", "digest", "fiat-crypto", - "platforms", "rustc_version", "subtle", "zeroize", @@ -831,7 +915,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] [[package]] @@ -842,9 +926,9 @@ checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "pem-rfc7468", @@ -865,6 +949,15 @@ dependencies = [ "rusticata-macros", ] +[[package]] +name = "deranged" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" +dependencies = [ + "powerfmt", +] + [[package]] name = "derive_arbitrary" version = "1.3.2" @@ -873,7 +966,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] [[package]] @@ -888,15 +981,30 @@ dependencies = [ "subtle", ] +[[package]] +name = "dispatch" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" + [[package]] name = "displaydoc" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", +] + +[[package]] +name = "dlib" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" +dependencies = [ + "libloading 0.8.5", ] [[package]] @@ -905,6 +1013,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" + [[package]] name = "ecdsa" version = "0.16.9" @@ -930,9 +1044,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", @@ -943,9 +1057,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" dependencies = [ "serde", ] @@ -973,9 +1087,9 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" +checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580" dependencies = [ "humantime", "is-terminal", @@ -992,9 +1106,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1019,9 +1133,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "event-listener" -version = "4.0.1" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f2cdcf274580f2d63697192d744727b3198894b1bf02923643bf59e2c26712" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" dependencies = [ "concurrent-queue", "parking", @@ -1030,19 +1144,19 @@ dependencies = [ [[package]] name = "event-listener-strategy" -version = "0.4.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "958e4d70b6d5e81971bebec42271ec641e7ff4e170a6fa605f2b8a8b65cb97d3" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" dependencies = [ - "event-listener 4.0.1", + "event-listener 5.3.1", "pin-project-lite", ] [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "ff" @@ -1066,15 +1180,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" - -[[package]] -name = "finl_unicode" -version = "1.2.0" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fcfdc7a0362c9f4444381a9e697c79d435fe65b52a37466fc2c1184cee9edc6" +checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "flume" @@ -1084,9 +1192,36 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ "futures-core", "futures-sink", - "spin 0.9.8", + "spin", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared", ] +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1098,9 +1233,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1108,15 +1243,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1136,15 +1271,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "futures-lite" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aeee267a1883f7ebef3700f262d2d54de95dfaf38189015a74fdc4e0c7ad8143" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" dependencies = [ "fastrand", "futures-core", @@ -1155,21 +1290,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-io", @@ -1194,9 +1329,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1205,9 +1340,9 @@ dependencies = [ [[package]] name = "ghash" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d930750de5717d2dd0b8c0d42c076c0e884c81a73e6cab859bbd2339c71e3e40" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" dependencies = [ "opaque-debug", "polyval", @@ -1215,9 +1350,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "glob" @@ -1238,27 +1373,43 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash", "allocator-api2", ] +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + [[package]] name = "hashlink" version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", ] [[package]] @@ -1272,9 +1423,15 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "hermit-abi" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "hex" @@ -1308,11 +1465,11 @@ dependencies = [ [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1323,9 +1480,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1356,12 +1513,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.0", ] [[package]] @@ -1376,13 +1533,13 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.9" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +checksum = "261f68e344040fbd0edea105bef17c66edf46f984ddb1115b775ce31be948f4b" dependencies = [ - "hermit-abi", - "rustix", - "windows-sys 0.48.0", + "hermit-abi 0.4.0", + "libc", + "windows-sys 0.52.0", ] [[package]] @@ -1396,24 +1553,24 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" dependencies = [ "either", ] [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "java-locator" -version = "0.1.5" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90003f2fd9c52f212c21d8520f1128da0080bad6fff16b68fe6e7f2f0c3780c2" +checksum = "d2abecabd9961c5e01405a6426687fcf1bd94a269927137e4c3cc1a7419b93fd" dependencies = [ "glob", "lazy_static", @@ -1450,7 +1607,7 @@ dependencies = [ "combine", "java-locator", "jni-sys", - "libloading", + "libloading 0.7.4", "log", "thiserror", "walkdir", @@ -1463,20 +1620,29 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" +dependencies = [ + "libc", +] + [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] [[package]] name = "k256" -version = "0.13.2" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f01b677d82ef7a676aa37e099defd83a28e15687112cafdd112d60236b6115b" +checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ "cfg-if", "ecdsa", @@ -1486,18 +1652,18 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] name = "libc" -version = "0.2.155" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libloading" @@ -1509,12 +1675,33 @@ dependencies = [ "winapi", ] +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + [[package]] name = "libm" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +[[package]] +name = "libredox" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +dependencies = [ + "bitflags 2.6.0", + "libc", + "redox_syscall 0.4.1", +] + [[package]] name = "libsqlite3-sys" version = "0.27.0" @@ -1528,15 +1715,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1544,9 +1731,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "md-5" @@ -1560,18 +1747,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.9.0" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minimal-lexical" @@ -1581,22 +1759,38 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "0.8.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ + "hermit-abi 0.3.9", "libc", "wasi", - "windows-sys 0.48.0", + "windows-sys 0.52.0", +] + +[[package]] +name = "ndk" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" +dependencies = [ + "bitflags 2.6.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle", + "thiserror", ] [[package]] @@ -1614,17 +1808,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.4.1", - "cfg-if", - "libc", -] - [[package]] name = "nom" version = "7.1.3" @@ -1637,11 +1820,10 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", ] @@ -1663,21 +1845,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -1686,59 +1873,302 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] [[package]] -name = "num_cpus" -version = "1.16.0" +name = "num_enum" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" +dependencies = [ + "num_enum_derive", +] + +[[package]] +name = "num_enum_derive" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" +dependencies = [ + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.79", +] + +[[package]] +name = "objc-sys" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" + +[[package]] +name = "objc2" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +dependencies = [ + "objc-sys", + "objc2-encode", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.0", + "block2", + "libc", + "objc2", + "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-image" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" dependencies = [ - "hermit-abi", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + +[[package]] +name = "objc2-encode" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.0", + "block2", + "dispatch", "libc", + "objc2", +] + +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", ] [[package]] name = "object" -version = "0.32.1" +version = "0.36.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" dependencies = [ "memchr", ] +[[package]] +name = "odbc-api" +version = "8.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc59611ab2d583ad4e419d5bfb72849bda357a91cf7b379ff95d86658865a0de" +dependencies = [ + "atoi", + "log", + "odbc-sys", + "thiserror", + "widestring", + "winit", +] + +[[package]] +name = "odbc-sys" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c219b6a4cd9eb167239d921d7348132cdff2eca05abbf1094e7f7ec9b8936b6" + [[package]] name = "oid-registry" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c958dd45046245b9c3c2547369bb634eb461670b2e7e0de552905801a648d1d" +checksum = "a8d8034d9489cdaf79228eb9f6a3b8d7bb32ba00d6645ebd48eef4077ceb5bd9" dependencies = [ "asn1-rs", ] [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "oorandom" -version = "11.1.3" +version = "11.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" +checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + +[[package]] +name = "orbclient" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" +dependencies = [ + "libredox", +] [[package]] name = "p256" @@ -1766,15 +2196,15 @@ dependencies = [ [[package]] name = "parking" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1782,15 +2212,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.5.7", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -1825,11 +2255,31 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pin-project" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.79", +] + [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -1860,21 +2310,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - -[[package]] -name = "platforms" -version = "3.2.0" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -1885,19 +2329,34 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] +[[package]] +name = "polling" +version = "3.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi 0.4.0", + "pin-project-lite", + "rustix", + "tracing", + "windows-sys 0.59.0", +] + [[package]] name = "poly1305" version = "0.8.0" @@ -1911,9 +2370,9 @@ dependencies = [ [[package]] name = "polyval" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52cff9d1d4dee5fe6d03729099f4a310a41179e0a10dbf542039873f2e826fb" +checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", "cpufeatures", @@ -1921,11 +2380,20 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "primeorder" @@ -1936,24 +2404,44 @@ dependencies = [ "elliptic-curve", ] +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + [[package]] name = "proc-macro2" -version = "1.0.82" +version = "1.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ad3d49ab951a01fbaafe34f2ec74122942fe18a3f9814c3268f1bb72042131b" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] +[[package]] +name = "r2d2" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot", + "scheduled-thread-pool", +] + [[package]] name = "rand" version = "0.8.5" @@ -1984,11 +2472,17 @@ dependencies = [ "getrandom", ] +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + [[package]] name = "rayon" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -1996,9 +2490,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -2013,11 +2507,20 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags 2.6.0", +] + [[package]] name = "regex" -version = "1.10.2" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", @@ -2027,9 +2530,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -2038,9 +2541,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rfc6979" @@ -2054,23 +2557,24 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", - "spin 0.9.8", + "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "rmp" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" +checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" dependencies = [ "byteorder", "num-traits", @@ -2079,9 +2583,9 @@ dependencies = [ [[package]] name = "rmp-serde" -version = "1.1.2" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" dependencies = [ "byteorder", "rmp", @@ -2110,15 +2614,15 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] @@ -2134,11 +2638,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -2147,9 +2651,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.11" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "ring", "rustls-webpki", @@ -2177,9 +2681,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "salsa20" @@ -2199,6 +2703,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scheduled-thread-pool" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +dependencies = [ + "parking_lot", +] + [[package]] name = "scopeguard" version = "1.2.0" @@ -2231,11 +2744,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -2244,9 +2757,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" dependencies = [ "core-foundation-sys", "libc", @@ -2254,15 +2767,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -2283,28 +2796,29 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ - "half", + "half 1.8.3", "serde", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] @@ -2331,6 +2845,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signature" version = "2.2.0" @@ -2352,25 +2872,28 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] -name = "socket2" -version = "0.5.5" +name = "smol_str" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ - "libc", - "windows-sys 0.48.0", + "serde", ] [[package]] -name = "spin" -version = "0.5.2" +name = "socket2" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] [[package]] name = "spin" @@ -2393,20 +2916,19 @@ dependencies = [ [[package]] name = "sqlformat" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce81b7bd7c4493975347ef60d8c7e8b742d4694f4c49f93e0a12ea263938176c" +checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" dependencies = [ - "itertools 0.12.0", "nom", "unicode_categories", ] [[package]] name = "sqlx" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba03c279da73694ef99763320dea58b51095dfe87d001b1d4b5fe78ba8763cf" +checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa" dependencies = [ "sqlx-core", "sqlx-macros", @@ -2417,9 +2939,9 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d84b0a3c3739e220d94b3239fd69fb1f74bc36e16643423bd99de3b43c21bfbd" +checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6" dependencies = [ "ahash", "atoi", @@ -2428,7 +2950,6 @@ dependencies = [ "chrono", "crc", "crossbeam-queue", - "dotenvy", "either", "event-listener 2.5.3", "futures-channel", @@ -2461,9 +2982,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89961c00dc4d7dffb7aee214964b065072bff69e36ddb9e2c107541f75e4f2a5" +checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127" dependencies = [ "proc-macro2", "quote", @@ -2474,11 +2995,10 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0bd4519486723648186a08785143599760f7cc81c52334a55d6a83ea1e20841" +checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8" dependencies = [ - "atomic-write-file", "dotenvy", "either", "heck", @@ -2501,13 +3021,13 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" +checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418" dependencies = [ "atoi", "base64", - "bitflags 2.4.1", + "bitflags 2.6.0", "byteorder", "bytes", "chrono", @@ -2544,13 +3064,13 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" +checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e" dependencies = [ "atoi", "base64", - "bitflags 2.4.1", + "bitflags 2.6.0", "byteorder", "chrono", "crc", @@ -2572,7 +3092,6 @@ dependencies = [ "rand", "serde", "serde_json", - "sha1", "sha2", "smallvec", "sqlx-core", @@ -2584,9 +3103,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "210976b7d948c7ba9fced8ca835b11cbb2d677c59c79de41ac0d397e14547490" +checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa" dependencies = [ "atoi", "chrono", @@ -2608,20 +3127,20 @@ dependencies = [ [[package]] name = "stringprep" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb41d74e231a107a1b4ee36bd1214b11285b77768d2e3824aedafa988fd36ee6" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" dependencies = [ - "finl_unicode", "unicode-bidi", "unicode-normalization", + "unicode-properties", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -2636,9 +3155,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.61" +version = "2.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c993ed8ccba56ae856363b1845da7266a7cb78e1d146c8a32d54b45a8b831fc9" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" dependencies = [ "proc-macro2", "quote", @@ -2653,58 +3172,61 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] [[package]] name = "tempfile" -version = "3.8.1" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", + "once_cell", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "termcolor" -version = "1.4.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] [[package]] name = "time" -version = "0.3.20" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ + "deranged", "itoa", + "num-conv", + "powerfmt", "serde", "time-core", "time-macros", @@ -2712,16 +3234,17 @@ dependencies = [ [[package]] name = "time-core" -version = "0.1.0" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.8" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ + "num-conv", "time-core", ] @@ -2737,9 +3260,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -2752,31 +3275,47 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", "libc", "mio", - "num_cpus", "pin-project-lite", "socket2", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-stream" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", "tokio", ] +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.40" @@ -2797,7 +3336,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] [[package]] @@ -2817,30 +3356,36 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode_categories" @@ -2866,9 +3411,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", "idna", @@ -2883,9 +3428,9 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "uuid" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ "getrandom", ] @@ -2898,15 +3443,15 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -2926,34 +3471,47 @@ checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2961,28 +3519,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -2990,20 +3558,26 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "whoami" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44ab49fad634e88f55bf8f9bb3abd2f27d7204172a112c7c9987e01c1c94ea9" +checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" dependencies = [ - "redox_syscall", + "redox_syscall 0.5.7", "wasite", ] +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + [[package]] name = "winapi" version = "0.3.9" @@ -3022,11 +3596,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -3037,11 +3611,11 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-core" -version = "0.51.1" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -3068,7 +3642,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -3103,17 +3686,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "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]] @@ -3130,9 +3714,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -3148,9 +3732,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -3166,9 +3750,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -3184,9 +3774,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -3202,9 +3792,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -3220,9 +3810,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -3238,15 +3828,64 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winit" +version = "0.30.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" +dependencies = [ + "android-activity", + "atomic-waker", + "bitflags 2.6.0", + "block2", + "calloop", + "cfg_aliases", + "concurrent-queue", + "core-foundation", + "core-graphics", + "cursor-icon", + "dpi", + "js-sys", + "libc", + "ndk", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", + "orbclient", + "pin-project", + "raw-window-handle", + "redox_syscall 0.4.1", + "rustix", + "smol_str", + "tracing", + "unicode-segmentation", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "web-time", + "windows-sys 0.52.0", + "xkbcommon-dl", +] + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] [[package]] name = "x25519-dalek" -version = "2.0.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb66477291e7e8d2b0ff1bcb900bf29489a9692816d79874bea351e7a8b6de96" +checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" dependencies = [ "curve25519-dalek", "rand_core", @@ -3270,31 +3909,51 @@ dependencies = [ "time", ] +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.6.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + [[package]] name = "zerocopy" -version = "0.7.31" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ + "byteorder", "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.31" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] @@ -3307,5 +3966,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.61", + "syn 2.0.79", ] diff --git a/Cargo.toml b/Cargo.toml index 0d7469d0..72fcf244 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ mobile_secure_element = ["askar-crypto/p256_hardware"] pg_test = ["askar-storage/pg_test"] postgres = ["askar-storage/postgres"] sqlite = ["askar-storage/sqlite"] +odbc = ["askar-storage/odbc"] [dependencies] async-lock = "3.0" diff --git a/askar-storage/Cargo.toml b/askar-storage/Cargo.toml index 1c138f90..e02b717c 100644 --- a/askar-storage/Cargo.toml +++ b/askar-storage/Cargo.toml @@ -24,6 +24,7 @@ migration = ["dep:rmp-serde", "dep:sqlx", "sqlx?/macros"] pg_test = ["postgres"] postgres = ["dep:sqlx", "sqlx?/postgres", "sqlx?/tls-rustls"] sqlite = ["dep:sqlx", "sqlx?/sqlite"] +odbc = ["dep:odbc-api", "dep:r2d2", "dep:lazy_static"] [dependencies] arc-swap = "1.6" @@ -48,6 +49,9 @@ tokio = { version = "1.5", features = ["rt-multi-thread", "time"] } url = { version = "2.1", default-features = false } uuid = { version = "1.2", features = ["v4"] } zeroize = "1.5" +odbc-api = { version = "8.1.4", optional = true } +r2d2 = { version = "0.8.10", optional = true } +lazy_static = { version = "1.5.0", optional = true } [dependencies.askar-crypto] default-features = false diff --git a/askar-storage/src/any.rs b/askar-storage/src/any.rs index 3a0d8ad6..44b1be93 100644 --- a/askar-storage/src/any.rs +++ b/askar-storage/src/any.rs @@ -18,6 +18,9 @@ use super::postgres; #[cfg(feature = "sqlite")] use super::sqlite; +#[cfg(feature = "odbc")] +use super::odbc; + /// A dynamic store backend instance #[derive(Clone, Debug)] pub struct AnyBackend(Arc>); @@ -288,6 +291,13 @@ impl<'a> ManageBackend<'a> for &'a str { Ok(into_any_backend(mgr)) } + #[cfg(feature = "odbc")] + "odbc" => { + let opts = odbc::OdbcStoreOptions::new(opts)?; + let mgr = opts.open(method, pass_key, profile).await?; + Ok(into_any_backend(mgr)) + } + _ => Err(err_msg!( Unsupported, "Unsupported backend: {}", @@ -323,6 +333,13 @@ impl<'a> ManageBackend<'a> for &'a str { Ok(into_any_backend(mgr)) } + #[cfg(feature = "odbc")] + "odbc" => { + let opts = odbc::OdbcStoreOptions::new(opts)?; + let mgr = opts.provision(method, pass_key, profile, recreate).await?; + Ok(into_any_backend(mgr)) + } + _ => Err(err_msg!( Unsupported, "Unsupported backend: {}", @@ -350,6 +367,12 @@ impl<'a> ManageBackend<'a> for &'a str { Ok(opts.remove().await?) } + #[cfg(feature = "odbc")] + "odbc" => { + let opts = odbc::OdbcStoreOptions::new(opts)?; + Ok(opts.remove().await?) + } + _ => Err(err_msg!( Unsupported, "Unsupported backend: {}", diff --git a/askar-storage/src/backend/mod.rs b/askar-storage/src/backend/mod.rs index 4393a5db..7a7d0812 100644 --- a/askar-storage/src/backend/mod.rs +++ b/askar-storage/src/backend/mod.rs @@ -9,7 +9,7 @@ use crate::{ protect::{PassKey, StoreKeyMethod}, }; -#[cfg(any(feature = "postgres", feature = "sqlite"))] +#[cfg(any(feature = "postgres", feature = "sqlite", feature = "odbc"))] pub(crate) mod db_utils; #[cfg(feature = "postgres")] @@ -22,6 +22,11 @@ pub mod postgres; /// Sqlite database support pub mod sqlite; +#[cfg(feature = "odbc")] +#[cfg_attr(docsrs, doc(cfg(feature = "odbc")))] +/// odbc database support +pub mod odbc; + /// Enum to support custom ordering in record queries #[derive(Debug)] pub enum OrderBy { diff --git a/askar-storage/src/backend/odbc/db2.sql b/askar-storage/src/backend/odbc/db2.sql new file mode 100644 index 00000000..ac70cb6d --- /dev/null +++ b/askar-storage/src/backend/odbc/db2.sql @@ -0,0 +1,51 @@ + +-- This SQL file contains the database schema for a DB2 server. +-- + +CREATE TABLE config ( + name VARCHAR(1022) NOT NULL, + value CLOB, + PRIMARY KEY(name) +); + +CREATE TABLE profiles ( + id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY, + name VARCHAR(1022) NOT NULL, + reference CLOB NULL, + profile_key BLOB NULL, + PRIMARY KEY(id) +); + +CREATE UNIQUE INDEX ix_profile_name ON profiles(name); + +CREATE TABLE items ( + id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY, + profile_id BIGINT NOT NULL, + kind SMALLINT NOT NULL, + category VARCHAR(500) NOT NULL, + name VARCHAR(500) NOT NULL, + value BLOB NOT NULL, + expiry TIMESTAMP NULL, + PRIMARY KEY(id), + FOREIGN KEY(profile_id) REFERENCES profiles(id) + ON DELETE CASCADE +); + +CREATE UNIQUE INDEX ix_items_uniq ON items(profile_id, kind, category, name); +CREATE INDEX ix_items_profile_id ON items(profile_id); + +CREATE TABLE items_tags ( + id BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY, + item_id BIGINT NOT NULL, + name VARCHAR(500) NOT NULL, + value VARCHAR(500) NOT NULL, + plaintext SMALLINT NOT NULL, + PRIMARY KEY(id), + FOREIGN KEY(item_id) REFERENCES items(id) + ON DELETE CASCADE +); + +CREATE INDEX ix_items_tags_item_id ON items_tags(item_id); +CREATE INDEX ix_items_tags_name ON items_tags(name, value); + +COMMIT; diff --git a/askar-storage/src/backend/odbc/mod.rs b/askar-storage/src/backend/odbc/mod.rs new file mode 100644 index 00000000..3cf5504c --- /dev/null +++ b/askar-storage/src/backend/odbc/mod.rs @@ -0,0 +1,1044 @@ +/// This module provides a backend capability for ODBC drivers. Please note +/// that this driver introduces a dependency on the ODBC shared library and as +/// such the correct version of the aries-askar shared library must be used +/// in order to utilise the ODBC functionality. +/// +/// Limitation: +/// There is currently a limitation with the ODBC implementation +/// which prevents the streaming of records. This means that if the 'copy' +/// API is used, to copy the current database into a different database, the +/// entire database will be read into memory before it is written to the +/// destination database. +/// +/// Example Connection String: +/// "odbc://Driver=/opt/db2/lib/libdb2o.so.1;\ +/// Database=testdb;\ +/// Hostname=10.10.10.200;\ +/// Port=50000;\ +/// Protocol=TCPIP;\ +/// Uid=db2inst1;\ +/// Pwd=passw0rd1;\ +/// Security=;\ +/// ?max_connections=21&min_connections=11&schema_file=/var/schemas/db2.sql" + +use std::fmt::{self, Debug, Formatter}; +use std::sync::Arc; +use std::collections::BTreeMap; +use async_stream::try_stream; +use futures_lite::Stream; + +use odbc_api::{ + buffers::RowVec, + Cursor, + IntoParameter, + parameter::{InputParameter, VarCharArray}, + Preallocated, +}; + +use super::{ + db_utils::{ + encode_profile_key, + expiry_timestamp, + PAGE_SIZE, + prepare_tags, + random_profile_name + }, + Backend, BackendSession +}; +use crate::{ + backend::OrderBy, + entry::{EncEntryTag, Entry, EntryKind, EntryOperation, EntryTag, Scan, TagFilter}, + error::Error, + future::{BoxFuture, unblock}, + protect::{EntryEncryptor, KeyCache, PassKey, ProfileId, ProfileKey, StoreKeyMethod}, + wql::{ + sql::TagSqlEncoder, + tags::{tag_query, TagQueryEncoder}, + }, +}; + +use r2d2::PooledConnection; + +mod provision; +pub use self::provision::OdbcStoreOptions; + +mod r2d2_connection_pool; +use crate::odbc::r2d2_connection_pool::OdbcConnectionManager; + +// All of our SQL queries. Each of these queries conform to the SQL-92 standard. +const UPDATE_CONFIG_PROFILE: &str = "UPDATE config SET value = ? WHERE name='default_profile'"; +const UPDATE_CONFIG_KEY: &str = "UPDATE config SET value=? WHERE name='key'"; +const GET_DEFAULT_PROFILE: &str = "SELECT value FROM config WHERE name='default_profile'"; + +const GET_PROFILE_ID: &str = "SELECT id from profiles WHERE name=? and profile_key=?"; +const GET_PROFILE_NAMES: &str = "SELECT name FROM profiles"; +const GET_PROFILE_COUNT_FOR_NAME: &str = "SELECT COUNT(name) from profiles WHERE name=?"; +const GET_PROFILES: &str = "SELECT id, profile_key FROM profiles"; +const GET_PROFILE: &str = "SELECT id, profile_key FROM profiles WHERE name=?"; +const INSERT_PROFILE: &str = "INSERT INTO profiles (name, profile_key) VALUES (?, ?)"; +const UPDATE_PROFILE: &str = "UPDATE profiles SET profile_key=? WHERE id=?"; +const DELETE_PROFILE: &str = "DELETE FROM profiles WHERE name=?"; + +const GET_ITEM_ID: &str = "SELECT id FROM items WHERE profile_id=? AND kind=? AND category=? AND name=?"; +const INSERT_ITEM: &str = "INSERT INTO items (profile_id, kind, category, name, value, expiry) VALUES (?, ?, ?, ?, ?, NULL)"; +const INSERT_ITEM_WITH_EXPIRY: &str = "INSERT INTO items (profile_id, kind, category, name, value, expiry) VALUES (?, ?, ?, ?, ?, ?)"; +const UPDATE_ITEM: &str = "UPDATE items SET value=?, expiry=NULL WHERE profile_id=? AND kind=? + AND category=? AND name=?"; +const UPDATE_ITEM_WITH_EXPIRY: &str = "UPDATE items SET value=?, expiry=? WHERE profile_id=? AND kind=? + AND category=? AND name=?"; +const DELETE_ITEM: &str = "DELETE FROM items WHERE profile_id = ? AND kind = ? AND category = ? AND name = ?"; +const COUNT_ITEMS: &str = "SELECT COUNT(*) FROM items i + WHERE profile_id = ? + AND (category = ? OR ? IS NULL) + AND (expiry IS NULL OR expiry > CURRENT_TIMESTAMP)"; +const DELETE_ALL_ITEMS: &str = "DELETE FROM items AS i + WHERE i.profile_id = ? + AND (i.category = ? OR ? IS NULL)"; +const GET_ITEM: &str = "SELECT id, value + FROM items WHERE profile_id = ? AND kind = ? + AND category = ? AND name = ? + AND (expiry IS NULL OR expiry > CURRENT_TIMESTAMP)"; +const GET_ALL_ITEMS: &str = "SELECT i.id, i.kind, i.category, i.name, i.value + FROM items i WHERE i.profile_id = ? + AND (i.category = ? OR ? IS NULL) + AND (i.expiry IS NULL OR i.expiry > CURRENT_TIMESTAMP)"; + +const INSERT_TAG: &str = "INSERT INTO items_tags (item_id, name, value, plaintext) VALUES (?, ?, ?, ?)"; +const DELETE_TAG: &str = "DELETE FROM items_tags WHERE item_id=?"; +const GET_TAGS_FOR_ITEM: &str = "select name, value, plaintext from items_tags where item_id = ?"; + +/// A ODBC database store +pub struct OdbcBackend { + pool: r2d2::Pool, + active_profile: String, + key_cache: Arc, +} + +impl OdbcBackend { + pub(crate) fn new( + pool: r2d2::Pool, + active_profile: String, + key_cache: KeyCache, + ) -> Self { + Self { + pool, + active_profile, + key_cache: Arc::new(key_cache), + } + } + + fn create_stream(&self, entries: Vec) -> impl Stream, Error>> + 'static { + try_stream! { + yield entries; + } + } +} + +impl Debug for OdbcBackend { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("OdbcStore") + .field("active_profile", &self.active_profile) + .finish() + } +} + +impl Backend for OdbcBackend { + type Session = OdbcSession; + + fn create_profile(&self, name: Option) -> BoxFuture<'_, Result> { + let name = name.unwrap_or_else(random_profile_name); + + Box::pin(async move { + // Create the profile key. + let store_key = self.key_cache.store_key.clone(); + let (profile_key, enc_key) = unblock(move || { + let profile_key = ProfileKey::new()?; + let enc_key = encode_profile_key(&profile_key, &store_key)?; + Result::<_, Error>::Ok((profile_key, enc_key)) + }) + .await?; + + let mut pid: i64 = 0; + + // Store the profile name and key. + { + let connection = self.pool.get()?; + let mut statement = connection.raw().preallocate()?; + + statement.execute(INSERT_PROFILE, + (&name.clone().into_parameter(), &enc_key.clone().into_parameter())) + .map_err(err_map!(Backend, "Error inserting profile"))?; + + if statement.row_count()?.unwrap() == 0 { + return Err(err_msg!(Duplicate, "Duplicate profile name")); + } + + // Retrieve the profile ID from the table. + statement.execute(GET_PROFILE_ID, + (&name.clone().into_parameter(), &enc_key.clone().into_parameter())) + .map_err(err_map!(Backend, "Error retrieving profile"))? + .unwrap() + .next_row() + .map_err(err_map!(Backend, "Error retrieving profile"))? + .unwrap() + .get_data(1, &mut pid)?; + } + + // Add the details to the key cache. + self.key_cache + .add_profile(name.clone(), pid, Arc::new(profile_key)) + .await; + + Ok(name) + }) + } + + fn get_active_profile(&self) -> String { + self.active_profile.clone() + } + + fn get_default_profile(&self) -> BoxFuture<'_, Result> { + Box::pin(async move { + let mut profile_buf = Vec::new(); + + self.pool.get()?.raw().execute(GET_DEFAULT_PROFILE, ()) + .map_err(err_map!(Backend, "Error fetching default profile name"))? + .unwrap() + .next_row() + .map_err(err_map!(Backend, "Error fetching default profile name"))? + .unwrap() + .get_text(1, &mut profile_buf)?; + + Ok(String::from_utf8(profile_buf)?) + }) + } + + fn set_default_profile(&self, profile: String) -> BoxFuture<'_, Result<(), Error>> { + Box::pin(async move { + self.pool.get()?.raw().execute(UPDATE_CONFIG_PROFILE, &profile.into_parameter()) + .map_err(err_map!(Backend, "Error setting default profile name"))?; + Ok(()) + }) + } + + fn list_profiles(&self) -> BoxFuture<'_, Result, Error>> { + Box::pin(async move { + let mut names: Vec = Vec::new(); + + match self.pool.get()?.raw().execute(GET_PROFILE_NAMES, ()) { + Ok(cursor) => { + let row_set_buffer = RowVec::<(VarCharArray<1024>,)>::new(64); + let mut block_cursor = cursor.unwrap().bind_buffer(row_set_buffer)?; + let batch = block_cursor.fetch()?.unwrap(); + + for idx in 0..batch.num_rows() { + names.push(batch[idx].0.as_str()?.unwrap().to_string()); + } + } + Err(_error) => { + return Err(err_msg!(Backend, "Error fetching profile list")); + } + }; + Ok(names) + }) + } + + fn remove_profile(&self, name: String) -> BoxFuture<'_, Result> { + Box::pin(async move { + let binding = self.pool.get()?; + let mut statement = binding.raw().preallocate()?; + + statement.execute(DELETE_PROFILE, &name.into_parameter()) + .map_err(err_map!(Backend, "Error removing profile"))?; + + let ret = statement.row_count()?.unwrap() != 0; + + Ok(ret) + }) + } + + fn rekey( + &mut self, + method: StoreKeyMethod, + pass_key: PassKey<'_>, + ) -> BoxFuture<'_, Result<(), Error>> { + let pass_key = pass_key.into_owned(); + + Box::pin(async move { + let (store_key, store_key_ref) = unblock(move || method.resolve(pass_key)).await?; + let store_key = Arc::new(store_key); + let binding = self.pool.get()?; + let mut upd_keys = BTreeMap::>::new(); + + // Retrieve and temporarily store the current keys for each + // of the profiles. + match binding.raw().execute(GET_PROFILES, ()) { + Ok(cursor) => { + let mut unwrapped = cursor.unwrap(); + + while let Some(mut row) = unwrapped.next_row()? { + let mut pid: i64 = 0; + let mut enc_key = Vec::new(); + + row.get_data(1, &mut pid)?; + row.get_binary(2, &mut enc_key)?; + + upd_keys.insert(pid, enc_key); + } + } + Err(_error) => { + return Err(err_msg!(NotFound, "Configuration data not found")); + } + }; + + // Iterate over the cached keys, updating the profile with the new + // key. + for (pid, key) in upd_keys { + let profile_key = self.key_cache.load_key(key).await?; + let upd_key = unblock({ + let store_key = store_key.clone(); + move || encode_profile_key(&profile_key, &store_key) + }) + .await?; + + binding.raw().execute(UPDATE_PROFILE, + (&upd_key.into_parameter(), &pid.into_parameter()))?; + } + + // We finally need to save the new store key. + binding.raw().execute(UPDATE_CONFIG_KEY, + &store_key_ref.into_uri().into_parameter()) + .map_err(err_map!(Backend, "Error updating the store key"))?; + + self.key_cache = Arc::new(KeyCache::new(store_key)); + + Ok(()) + }) + } + + fn scan( + &self, + profile: Option, + kind: Option, + category: Option, + tag_filter: Option, + offset: Option, + limit: Option, + order_by: Option, + descending: bool, + ) -> BoxFuture<'_, Result, Error>> { + Box::pin(async move { + // Create a new session, fetch all of the matching records for the + // session and create a stream from the fetched records. Unfortunately + // we cannot stream directly from the database (there appear to be issues + // with the ODBC API/Drivers which prevent thread swapping), which means + // that the database copy functionality will need to pull the entire + // database into memory before writing the new database. This is a + // pretty severe limitation, but can't be helped, and means that + // you won't be able to use this API to copy large databases. + + let mut session = OdbcSession::new( + self.key_cache.clone(), + profile.unwrap_or_else(|| self.active_profile.clone()), + self.pool.get()?, + false, + ); + + let entries = session.perform_scan( + kind, + category, + tag_filter, + offset, + limit, + order_by, + descending).await?; + + let stream = self.create_stream(entries); + + session.close(true).await?; + + Ok(Scan::new(stream, PAGE_SIZE)) + }) + } + + fn session(&self, profile: Option, transaction: bool) -> Result { + Ok(OdbcSession::new( + self.key_cache.clone(), + profile.unwrap_or_else(|| self.active_profile.clone()), + self.pool.get()?, + transaction, + )) + } + + fn close(&self) -> BoxFuture<'_, Result<(), Error>> { + Box::pin(async move { Ok(()) }) + } +} + +/// A ODBC session +#[derive(Debug)] +pub struct OdbcSession { + cache: Arc, + profile: String, + connection: PooledConnection, + transaction: bool, +} + +impl OdbcSession { + pub(crate) fn new( + cache: Arc, + profile: String, + connection: PooledConnection, + transaction: bool, + ) -> Self + { + let _ = connection.raw().set_autocommit(!transaction); + + Self { + cache: cache, + profile: profile, + connection: connection, + transaction: transaction, + } + } + + async fn acquire_key(&mut self) -> Result<(ProfileId, Arc), Error> { + // Check to see whether the key already exists in our cache... + if let Some((pid, key)) = self.cache.get_profile(self.profile.as_str()).await { + Ok((pid, key)) + } else { + // The key isn't already cached and so we need to try and load the key + // from the database. + let mut pid: i64 = 0; + let mut enc_key = Vec::new(); + + if let Some(mut cursor) = self.connection.raw().execute(GET_PROFILE, &self.profile.clone().into_parameter()) + .map_err(err_map!(Backend, "Error fetching profile key"))? + { + let mut row = cursor.next_row() + .map_err(err_map!(Backend, "Error fetching profile key"))? + .unwrap(); + row.get_data(1, &mut pid)?; + row.get_binary(2, &mut enc_key)?; + } else { + return Err(err_msg!(NotFound, "Profile not found")); + } + + // Load and cache the key. + let key = Arc::new(self.cache.load_key(enc_key).await?); + self.cache.add_profile(self.profile.clone(), pid, key.clone()).await; + + Ok((pid, key)) + } + } + + fn get_decoded_tags(&self, item_id: i64, statement: &mut Preallocated<'_>, key: &Arc) -> Result, Error> { + // Retrieve the tags from the database. + if let Some(cursor) = statement.execute(GET_TAGS_FOR_ITEM, &item_id)? { + // We use a RowVec buffer to iterate over the rows as it is more efficent + // than retrieving the rows one at a time. This just means that we need + // to limit the size of the name and value columns to 1K. + type Row = (VarCharArray<1024>, VarCharArray<1024>, i32); + let max_rows_in_batch = 64; + let buffer = RowVec::::new(max_rows_in_batch); + + let mut block_cursor = cursor.bind_buffer(buffer)?; + + let mut enc_tags: Vec = Vec::new(); + while let Some(batch) = block_cursor.fetch()? { + // Iterate over each row, retrieving the name, value and + // plaintext fields. + for (name, value, plaintext) in batch.iter() { + enc_tags.push(EncEntryTag { + name: name.as_bytes().ok_or_else(|| err_msg!(Backend, "Failed to retrieve the tag name"))?.to_vec(), + value: value.as_bytes().ok_or_else(|| err_msg!(Backend, "Failed to retrieve the tag value"))?.to_vec(), + plaintext: (*plaintext == 1), + }); + } + } + + Ok(key.decrypt_entry_tags(enc_tags)?) + } else { + let tags: Vec = Vec::new(); + Ok(tags) + } + } + + async fn create_query( + &mut self, + query: &str, + profile_id: ProfileId, + key: Arc, + kind: Option, + category: Option, + tag_filter: Option, + order_by: Option, + descending: bool, + ) -> Result<(String, Vec>), Error> + { + // Get an encrypted version of the category and tag filter. + let (enc_category, tag_filter) = unblock({ + let key = key.clone(); + let enc_category = category.as_ref().map(|c| ProfileKey::prepare_input(c.as_bytes())); + move || { + Result::<_, Error>::Ok(( + enc_category.map(|c| key.encrypt_entry_category(c)).transpose()?, + encode_odbc_tag_filter(tag_filter, &key)?, + )) + } + }).await?; + + let mut query = query.to_string(); + + // Construct the full list of parameters for the query. + let mut args: Vec> = Vec::new(); + + args.push(Box::new(profile_id.clone().into_parameter())); + args.push(Box::new(enc_category.clone().into_parameter())); + args.push(Box::new(enc_category.clone().into_parameter())); + + if let Some(sql_kind) = kind { + args.push(Box::new(sql_kind as i16)); + args.push(Box::new(sql_kind as i16)); + + query.push_str(" AND (i.kind = ? OR ? IS NULL)"); + } + + // Extend the query to include any required tags. + if let Some((filter_clause, filter_args)) = tag_filter { + for arg in filter_args.iter() { + args.push(Box::new(arg.clone().into_parameter())); + } + query.push_str(" AND "); // assumes WHERE already occurs + query.push_str(&filter_clause); + }; + + // Only add ordering if the query starts with SELECT + if query.trim_start().to_uppercase().starts_with("SELECT") { + if let Some(order_by_value) = order_by { + query.push_str(" ORDER BY "); + match order_by_value { + OrderBy::Id => query.push_str("id"), + } + if descending { + query.push_str(" DESC"); + } + }; + } + + Ok((query, args)) + } + + async fn perform_scan( + &mut self, + kind: Option, + category: Option, + tag_filter: Option, + offset: Option, + limit: Option, + order_by: Option, + descending: bool, + ) -> Result, Error> { + let (profile_id, key) = self.acquire_key().await?; + + // Create the query which is to be executed. + let (query, params) = self.create_query( + GET_ALL_ITEMS, + profile_id, + key.clone(), + kind, + category, + tag_filter, + order_by, + descending).await?; + + // Execute the query. + let mut statement = self.connection.raw().preallocate()?; + let mut tag_statement = self.connection.raw().preallocate()?; + + let mut items: Vec = Vec::new(); + + if let Some(mut cursor) = statement.execute(&query, params.as_slice())? { + // Set up the offset and limit parameters. It would have been nice + // to include these parameters in the SQL query - but this is not + // ansi-sql compliant, and so we need to manually process these + // values within our for loop. This is going to be slow, but can't + // be helped. + let offset: i64 = offset.unwrap_or(0); + let limit: i64 = limit.unwrap_or(-1); + let mut row_number: i64 = 0; + + // Process each row in the response. + while let Some(mut row) = cursor.next_row()? { + // Check the offset value to determine whether we should skip this + // row. + row_number += 1; + + if row_number <= offset { + continue; + } + + // Check to see if we have reached the limit. + if (limit != -1) && ((row_number - offset) > limit) { + break; + } + + // Retrieve the fields for this row. The order of the fields are: + // id, kind, category, name, value + let mut item_id: i64 = 0; + row.get_data(1, &mut item_id)?; + + let mut kind_buf: i64 = 0; + row.get_data(2, &mut kind_buf)?; + + let mut category_buf = Vec::new(); + row.get_text(3, &mut category_buf)?; + + let mut name_buf = Vec::new(); + row.get_text(4, &mut name_buf)?; + + let mut value_buf = Vec::new(); + row.get_binary(5, &mut value_buf)?; + + let tags: Vec = self.get_decoded_tags(item_id, &mut tag_statement, &key)?; + let category = key.decrypt_entry_category(category_buf)?; + let name = key.decrypt_entry_name(name_buf)?; + let value = key.decrypt_entry_value(category.as_bytes(), name.as_bytes(), value_buf)?; + + items.push(Entry { + kind: EntryKind::try_from(kind_buf as usize)?, + category, + name, + value, + tags + }); + } + } + + Ok(items) + } +} + +impl BackendSession for OdbcSession { + fn count<'q>( + &'q mut self, + kind: Option, + category: Option<&'q str>, + tag_filter: Option, + ) -> BoxFuture<'q, Result> { + Box::pin(async move { + // Create the tag filter and parameters. + let (profile_id, key) = self.acquire_key().await?; + + // Create the query which is to be executed. + let (query, params) = self.create_query( + COUNT_ITEMS, + profile_id, + key.clone(), + kind, + category.map(str::to_string), + tag_filter, + None, + false).await?; + + let mut count: i64 = 0; + + // Execute the query. + self.connection.raw().execute(&query, params.as_slice()) + .map_err(err_map!(Backend, "Error performing count query"))? + .unwrap() + .next_row() + .map_err(err_map!(Backend, "Error performing count query"))? + .unwrap() + .get_data(1, &mut count)?; + + Ok(count) + }) + } + + fn fetch( + &mut self, + kind: EntryKind, + category: &str, + name: &str, + _for_update: bool, + ) -> BoxFuture<'_, Result, Error>> { + let category = category.to_string(); + let name = name.to_string(); + + Box::pin(async move { + // Create the 'select' fields. + let (pid, key) = self.acquire_key().await?; + let (enc_category, enc_name) = unblock({ + let key = key.clone(); + let category = ProfileKey::prepare_input(category.as_bytes()); + let name = ProfileKey::prepare_input(name.as_bytes()); + move || { + Result::<_, Error>::Ok(( + key.encrypt_entry_category(category)?, + key.encrypt_entry_name(name)?, + )) + } + }) + .await?; + + let mut statement = self.connection.raw().preallocate()?; + + // Retrieve the item from the database. + let mut item_id: i64 = 0; + let mut value: Vec = Vec::new(); + + if let Ok(Some(mut row)) = statement.execute(GET_ITEM, ( + &pid.into_parameter(), + &(kind as i16).into_parameter(), + &enc_category.clone().into_parameter(), + &enc_name.clone().into_parameter() + )).map_err(err_map!(Backend, "Error performing fetch query"))? + .unwrap().next_row() { + row.get_binary(2, &mut value)?; + row.get_data(1, &mut item_id)?; + } else { + return Ok(None); + } + + // Build up the response. + let dvalue = key.decrypt_entry_value(category.as_ref(), name.as_ref(), value)?; + let tags: Vec = self.get_decoded_tags(item_id, &mut statement, &key)?; + + Ok(Some(Entry::new(kind, category, name, dvalue, tags))) + }) + } + + fn fetch_all<'q>( + &'q mut self, + kind: Option, + category: Option<&'q str>, + tag_filter: Option, + limit: Option, + order_by: Option, + descending: bool, + _for_update: bool, + ) -> BoxFuture<'q, Result, Error>> { + let category = category.map(|c| c.to_string()); + + Box::pin(async move { + Ok(self.perform_scan( + kind, + category.clone(), + tag_filter, + None, + limit, + order_by, + descending + ).await?) + }) + } + + fn remove_all<'q>( + &'q mut self, + kind: Option, + category: Option<&'q str>, + tag_filter: Option, + ) -> BoxFuture<'q, Result> { + Box::pin(async move { + // Create the tag filter and parameters. + let (profile_id, key) = self.acquire_key().await?; + + // Create the query which is to be executed. + let (query, params) = self.create_query( + DELETE_ALL_ITEMS, + profile_id, + key.clone(), + kind, + category.map(str::to_string), + tag_filter, + None, + false).await?; + + // Execute the query. + let mut statement = self.connection.raw().preallocate()?; + statement.execute(&query, params.as_slice()) + .map_err(err_map!(Backend, "Error removing entry"))?; + + let removed = statement.row_count()?.unwrap(); + + Ok(removed as i64) + }) + } + + fn update<'q>( + &'q mut self, + kind: EntryKind, + operation: EntryOperation, + category: &'q str, + name: &'q str, + value: Option<&'q [u8]>, + tags: Option<&'q [EntryTag]>, + expiry_ms: Option, + ) -> BoxFuture<'q, Result<(), Error>> { + let category = ProfileKey::prepare_input(category.as_bytes()); + let name = ProfileKey::prepare_input(name.as_bytes()); + + match operation { + op @ EntryOperation::Insert | op @ EntryOperation::Replace => { + let value = ProfileKey::prepare_input(value.unwrap_or_default()); + let tags = tags.map(prepare_tags); + Box::pin(async move { + // Locate the correct key and then encrypt our various fields. + let (pid, key) = self.acquire_key().await?; + let (enc_category, enc_name, enc_value, enc_tags) = unblock(move || { + let enc_value = + key.encrypt_entry_value(category.as_ref(), name.as_ref(), value)?; + Result::<_, Error>::Ok(( + key.encrypt_entry_category(category)?, + key.encrypt_entry_name(name)?, + enc_value, + tags.transpose()? + .map(|t| key.encrypt_entry_tags(t)) + .transpose()?, + )) + }) + .await?; + + let mut statement = self.connection.raw().preallocate()?; + + // Work out the expiry time. + let mut expiry_str: String = String::new(); + + if let Some(expiry) = expiry_ms.map(expiry_timestamp).transpose()? { + // ODBC expects the time stamp to be in a string, of the format: + // YYYY-MM-DD HH:MM:SS.MSEC + expiry_str = format!("{}", expiry.format("%Y-%m-%d %H:%M:%S.%6f")); + } + + // Now we need to store the fields in the database. + if op == EntryOperation::Insert { + if expiry_str.is_empty() { + statement.execute(INSERT_ITEM, + ( + &pid.into_parameter(), + &(kind as i16).into_parameter(), + &enc_category.clone().into_parameter(), + &enc_name.clone().into_parameter(), + &enc_value.into_parameter() + )).map_err(err_map!(Backend, "Error inserting new entry"))?; + } else { + statement.execute(INSERT_ITEM_WITH_EXPIRY, + ( + &pid.into_parameter(), + &(kind as i16).into_parameter(), + &enc_category.clone().into_parameter(), + &enc_name.clone().into_parameter(), + &enc_value.into_parameter(), + &expiry_str.into_parameter() + )).map_err(err_map!(Backend, "Error inserting new entry"))?; + } + + if statement.row_count()?.unwrap() == 0 { + return Err(err_msg!(Duplicate, "Duplicate entry")); + } + } else { + if expiry_str.is_empty() { + statement.execute(UPDATE_ITEM, + ( + &enc_value.into_parameter(), + &pid.into_parameter(), + &(kind as i16).into_parameter(), + &enc_category.clone().into_parameter(), + &enc_name.clone().into_parameter() + )).map_err(|_| err_msg!(NotFound, "Error updating existing entry"))?; + } else { + statement.execute(UPDATE_ITEM_WITH_EXPIRY, + ( + &enc_value.into_parameter(), + &expiry_str.into_parameter(), + &pid.into_parameter(), + &(kind as i16).into_parameter(), + &enc_category.clone().into_parameter(), + &enc_name.clone().into_parameter() + )).map_err(|_| err_msg!(NotFound, "Error updating existing entry"))?; + } + + // We also want to delete all existing tags for this + // item. + + statement.execute(DELETE_TAG, &pid.into_parameter()) + .map_err(err_map!(Backend, "Error removing existing entry tags"))?; + } + + // Now we need to update the tags table. + if let Some(tags) = enc_tags { + // Retrieve the item identifier. + let mut item_id: i64 = 0; + + statement.execute(GET_ITEM_ID, + ( + &pid.into_parameter(), + &(kind as i16).into_parameter(), + &enc_category.clone().into_parameter(), + &enc_name.clone().into_parameter() + )) + .map_err(err_map!(Backend, "Error retrieving item"))? + .unwrap() + .next_row() + .map_err(err_map!(Backend, "Error retrieving item"))? + .unwrap() + .get_data(1, &mut item_id)?; + + // Update each of the tags. + let mut prepared = self.connection.raw().prepare(INSERT_TAG)?; + + for tag in tags { + prepared.execute( + ( + &item_id.into_parameter(), + &tag.name.into_parameter(), + &tag.value.into_parameter(), + &(tag.plaintext as i16).into_parameter() + )).map_err(err_map!(Backend, "Error inserting entry tags"))?; + } + } + + Ok(()) + }) + } + + EntryOperation::Remove => Box::pin(async move { + // Create the encrypted category and name. + let (pid, key) = self.acquire_key().await?; + let (enc_category, enc_name) = unblock(move || { + Result::<_, Error>::Ok(( + key.encrypt_entry_category(category)?, + key.encrypt_entry_name(name)?, + )) + }) + .await?; + + // Issue the delete. We don't return an error if the + // item doesn't currently exist. + let mut statement = self.connection.raw().preallocate()?; + + statement.execute(DELETE_ITEM, + ( + &pid.into_parameter(), + &(kind as i16).into_parameter(), + &enc_category.into_parameter(), + &enc_name.into_parameter() + )) + .map_err(err_map!(Backend, "Error deleting item"))?; + + let deleted = statement.row_count()?.unwrap(); + + if deleted == 0 { + return Err(err_msg!(NotFound, "Entry not found")); + } + + Ok(()) + }), + } + } + + fn ping(&mut self) -> BoxFuture<'_, Result<(), Error>> { + Box::pin(async move { + let mut count: i64 = 0; + + self.connection.raw().execute(GET_PROFILE_COUNT_FOR_NAME, + &self.profile.clone().into_parameter()) + .map_err(err_map!(Backend, "Error pinging session"))? + .unwrap() + .next_row() + .map_err(err_map!(Backend, "Error pinging session"))? + .unwrap() + .get_data(1, &mut count)?; + if count == 0 { + Err(err_msg!(NotFound, "Session profile has been removed")) + } else { + Ok(()) + } + }) + } + + fn close(&mut self, commit: bool) -> BoxFuture<'_, Result<(), Error>> { + Box::pin(async move { + if self.transaction { + if commit { + self.connection.raw().commit()?; + } else { + self.connection.raw().rollback()?; + } + let _ = self.connection.raw().set_autocommit(true); + } + Ok(()) + }) + } +} + +fn encode_odbc_tag_filter( + tag_filter: Option, + key: &ProfileKey, +) -> Result>)>, Error> { + if let Some(tag_filter) = tag_filter { + let tag_query = tag_query(tag_filter.query)?; + let mut enc = TagSqlEncoder::new( + |name| key.encrypt_tag_name(ProfileKey::prepare_input(name.as_bytes())), + |value| key.encrypt_tag_value(ProfileKey::prepare_input(value.as_bytes())), + ); + if let Some(filter) = enc.encode_query(&tag_query)? { + let filter = replace_odbc_arg_placeholders(&filter); + Ok(Some((filter, enc.arguments))) + } else { + Ok(None) + } + } else { + Ok(None) + } +} + +fn replace_odbc_arg_placeholders( + filter: &str, +) -> String { + let mut buffer: String = String::with_capacity(filter.len()); + let mut remain = filter; + while let Some(start_offs) = remain.find('$') { + let mut iter = remain[(start_offs + 1)..].chars(); + if let Some(end_offs) = iter.next().and_then(|c| match c { + '$' => Some(start_offs + 2), + '0'..='9' => { + let mut end_offs = start_offs + 2; + for c in iter { + if c.is_ascii_digit() { + end_offs += 1; + } else { + break; + } + } + Some( + end_offs, + ) + } + _ => None, + }) { + buffer.push_str(&remain[..start_offs]); + buffer.push_str("?"); + remain = &remain[end_offs..]; + } else { + buffer.push_str(&remain[..=start_offs]); + remain = &remain[(start_offs + 1)..]; + } + } + buffer.push_str(remain); + buffer +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn odbc_simple_and_convert_args_works() { + assert_eq!( + &replace_odbc_arg_placeholders("This $1 is $2 a $3 string!"), + "This ? is ? a ? string!", + ); + } +} diff --git a/askar-storage/src/backend/odbc/provision.rs b/askar-storage/src/backend/odbc/provision.rs new file mode 100644 index 00000000..023a7dcd --- /dev/null +++ b/askar-storage/src/backend/odbc/provision.rs @@ -0,0 +1,417 @@ +use std::time::Duration; +use std::fs; +use odbc_api::{Cursor, IntoParameter}; + +use crate::{ + backend::{ + db_utils::{init_keys, random_profile_name}, + ManageBackend, + }, + error::Error, + future::{unblock, BoxFuture}, + options::IntoOptions, + protect::{KeyCache, PassKey, StoreKeyMethod, StoreKeyReference}, +}; + +use super::OdbcBackend; +use crate::odbc::OdbcConnectionManager; + +/// Allow the aries-askar error object to handle ODBC API errors. +impl From for Error { + fn from(err: odbc_api::Error) -> Self { + err_msg!(Backend, "Error returned from the database").with_cause(err) + } +} + +/// Allow the aries-askar error object to handle r2d2 errors. +impl From for Error { + fn from(err: r2d2::Error) -> Self { + err_msg!(Backend, "Error returned from the database pool").with_cause(err) + } +} + +/// Defaults. +const DEFAULT_CONNECT_TIMEOUT: u64 = 30; +const DEFAULT_IDLE_TIMEOUT: u64 = 300; +const DEFAULT_MAX_LIFETIME: u64 = 300; +const DEFAULT_MIN_CONNECTIONS: u32 = 0; +const DEFAULT_MAX_CONNECTIONS: u32 = 10; + +/// Configuration options for ODBC stores +#[derive(Debug)] +pub struct OdbcStoreOptions { + pub(crate) connect_timeout: Duration, + pub(crate) idle_timeout: Duration, + pub(crate) max_lifetime: Duration, + pub(crate) max_connections: u32, + pub(crate) min_connections: u32, + pub(crate) connection_string: String, + pub(crate) schema_file: String, +} + +impl OdbcStoreOptions { + /// Initialize `OdbcStoreOptions` from a generic set of options + pub fn new<'a, O>(options: O) -> Result + where + O: IntoOptions<'a>, + { + let mut opts = options.into_options()?; + let connect_timeout = if let Some(timeout) = opts.query.remove("connect_timeout") { + timeout + .parse() + .map_err(err_map!(Input, "Error parsing 'connect_timeout' parameter"))? + } else { + DEFAULT_CONNECT_TIMEOUT + }; + let idle_timeout = if let Some(timeout) = opts.query.remove("idle_timeout") { + timeout + .parse() + .map_err(err_map!(Input, "Error parsing 'idle_timeout' parameter"))? + } else { + DEFAULT_IDLE_TIMEOUT + }; + let max_lifetime = if let Some(timeout) = opts.query.remove("max_lifetime") { + timeout + .parse() + .map_err(err_map!(Input, "Error parsing 'max_lifetime' parameter"))? + } else { + DEFAULT_MAX_LIFETIME + }; + let max_connections = if let Some(max_conn) = opts.query.remove("max_connections") { + max_conn + .parse() + .map_err(err_map!(Input, "Error parsing 'max_connections' parameter"))? + } else { + DEFAULT_MAX_CONNECTIONS + }; + let min_connections = if let Some(min_conn) = opts.query.remove("min_connections") { + min_conn + .parse() + .map_err(err_map!(Input, "Error parsing 'min_connections' parameter"))? + } else { + DEFAULT_MIN_CONNECTIONS + }; + + let schema_file = opts.query.remove("schema_file"); + if !schema_file.is_some() { + return Err(err_msg!(Input, "Missing 'schema_file' parameter")); + } + + let mut connection_string = opts.host.to_string(); + connection_string.push_str(&opts.path); + + Ok(Self { + connect_timeout: Duration::from_secs(connect_timeout), + idle_timeout: Duration::from_secs(idle_timeout), + max_lifetime: Duration::from_secs(max_lifetime), + max_connections, + min_connections, + connection_string, + schema_file: schema_file.unwrap(), + }) + } + + /// Provision an Odbc store from this set of configuration options + pub async fn provision( + self, + method: StoreKeyMethod, + pass_key: PassKey<'_>, + profile: Option, + recreate: bool, + ) -> Result { + // Create the pool to the database server. + let pool = self.open_pool().await?; + + if self.config_exists(&pool)? { + if !recreate { + // If the database has already been created we just open + // it now. + return Ok(self.open(Some(method), pass_key, profile).await?); + } else { + self.drop_tables(&pool)?; + } + } + + // If we get this far it means that the database has not yet been provisioned. + + // Initialise the key store. + let (profile_key, enc_profile_key, store_key, store_key_ref) = unblock({ + let pass_key = pass_key.into_owned(); + move || init_keys(method, pass_key) + }) + .await?; + + // Work out the profile. + let default_profile = profile.unwrap_or_else(random_profile_name); + + // We need to provision the database now. We do this by applying the database + // schema which has been provided in the schema file. We need to execute each + // SQL statement one at a time as the ODBC API does not appear to support the + // execution of multiple statements in a single API call. + let schema: String = fs::read_to_string(self.schema_file) + .map_err(err_map!(Backend, "Failed to read the schema file"))?; + + let connection = pool.get()?; + let mut statement = connection.raw().preallocate()?; + + let definitions = schema.split(";"); + for definition in definitions { + let trimmed_definition = definition.trim(); + + if trimmed_definition.len() > 0 { + statement.execute(trimmed_definition, ())?; + } + } + + // Save the configuration information. + statement.execute("INSERT INTO config (name, value) VALUES + ('default_profile', ?), + ('key', ?), + ('version', ?)", ( + &default_profile.clone().into_parameter(), + &store_key_ref.into_parameter(), + &"1".into_parameter() + )) + .map_err(err_map!(Backend, "Failed to insert the configuration data"))?; + + statement.execute("INSERT INTO profiles (name, profile_key) VALUES (?, ?)", ( + &default_profile.clone().into_parameter(), + &enc_profile_key.clone().into_parameter() + )) + .map_err(err_map!(Backend, "Failed to insert the default profile"))?; + + // Retrieve the profile ID from the table. + let mut profile_id: i64 = 0; + + statement.execute( + "SELECT id from profiles WHERE name=? and profile_key=?", ( + &default_profile.clone().into_parameter(), + &enc_profile_key.clone().into_parameter() + )) + .map_err(err_map!(Backend, "Failed to retrieve the default profile"))? + .unwrap() + .next_row() + .map_err(err_map!(Backend, "Failed to retrieve the default profile"))? + .unwrap() + .get_data(1, &mut profile_id)?; + + let mut key_cache = KeyCache::new(store_key); + key_cache.add_profile_mut(default_profile.clone(), profile_id, profile_key); + + // Return a newly created backend for the database server. + Ok(OdbcBackend::new( + pool, + default_profile, + key_cache, + )) + } + + /// Open an existing Odbc store from this set of configuration options + pub async fn open( + self, + method: Option, + pass_key: PassKey<'_>, + profile: Option, + ) -> Result { + // Create the pool to the database server. + let pool = self.open_pool().await?; + + // We need to retrieve the profile, key and version from the + // config table. + let mut ver_ok = false; + let mut default_profile: Option = None; + let mut store_key_ref: Option = None; + + match pool.get()?.raw().execute( + "SELECT name, value FROM config WHERE name IN ('default_profile', 'key', 'version')", ()) { + Ok(cursor) => { + let mut unwrapped = cursor.unwrap(); + + while let Some(mut row) = unwrapped.next_row()? { + // Retrieve the name and value in the row. + let mut name_buf = Vec::new(); + row.get_text(1, &mut name_buf)?; + let name = String::from_utf8(name_buf)?; + + let mut value_buf = Vec::new(); + row.get_text(2, &mut value_buf)?; + let value = String::from_utf8(value_buf)?; + + // Check the name and process the value. + match name.as_str() { + "default_profile" => { + default_profile.replace(value); + } + "key" => { + store_key_ref.replace(value); + } + "version" => { + if value != "1" { + return Err(err_msg!(Unsupported, "Unsupported store version")); + } + ver_ok = true; + } + _ => (), + } + } + } + Err(_error) => { + return Err(err_msg!(Unsupported, "Configuration data not found")); + } + }; + + if !ver_ok { + return Err(err_msg!(Unsupported, "Store version not found")); + } + + // Work out our profile and store key. + let profile = profile + .or(default_profile) + .ok_or_else(|| err_msg!(Unsupported, "Default store profile not found"))?; + + let store_key = if let Some(store_key_ref) = store_key_ref { + let wrap_ref = StoreKeyReference::parse_uri(&store_key_ref)?; + if let Some(method) = method { + if !wrap_ref.compare_method(&method) { + return Err(err_msg!(Input, "Store key method mismatch")); + } + } + unblock({ + let pass_key = pass_key.into_owned(); + move || wrap_ref.resolve(pass_key) + }) + .await? + } else { + return Err(err_msg!(Unsupported, "Store key not found")); + }; + + // Retrieve the key from the database. + let mut profile_id: i64 = 0; + let mut profile_key_buf = Vec::new(); + + if let Ok(Some(mut cursor)) = pool.get()?.raw().execute( + "SELECT id, profile_key from profiles WHERE name=?", + &profile.clone().into_parameter()) { + let mut row = cursor.next_row()?.unwrap(); + + row.get_data(1, &mut profile_id)?; + row.get_binary(2, &mut profile_key_buf)?; + } + + let mut key_cache = KeyCache::new(store_key); + + let profile_key = key_cache.load_key(profile_key_buf).await?; + + key_cache.add_profile_mut(profile.clone(), profile_id, profile_key); + + // Return a newly created backend for the database server. + Ok(OdbcBackend::new( + pool, + profile, + key_cache, + )) + } + + /// Remove an existing Odbc store defined by these configuration options + pub async fn remove(self) -> Result { + // Create the pool to the database server. + let pool = self.open_pool().await?; + + // If the config table exists we attempt to drop all of the tables now. + if self.config_exists(&pool)? { + self.drop_tables(&pool)?; + } + + Ok(true) + } + + /// Create a pool of connections to the database server. + async fn open_pool(&self) -> Result, Error> { + let manager = OdbcConnectionManager::new(self.connection_string.clone()); + Ok(r2d2::Pool::builder() + .max_size(self.max_connections) + .min_idle(Some(self.min_connections)) + .max_lifetime(Some(self.max_lifetime)) + .connection_timeout(self.connect_timeout) + .idle_timeout(Some(self.idle_timeout)) + .build(manager) + .map_err(err_map!(Backend, "Failed to open the database pool"))?) + } + + // Drop all of our tables from the database server. + fn drop_tables(&self, pool: &r2d2::Pool) -> Result<(), Error> { + let table_names: [&str; 4] = ["items_tags", "items", "profiles", "config"]; + + for table_name in &table_names { + let _ = pool.get()?.raw().execute(format!("DROP TABLE {}", table_name).as_str(), ()) + .map_err(err_map!(Backend, "Failed to drop a database table"))?; + } + + Ok(()) + } + + // Check to see whether our config table exists or not. + fn config_exists(&self, pool: &r2d2::Pool) -> Result { + // Check to see if the config table currently exists. + Ok(pool.get()?.raw().execute("select count(name) from config", ()).is_ok()) + } + +} + +impl<'a> ManageBackend<'a> for OdbcStoreOptions { + type Backend = OdbcBackend; + + /// Open a connection to the backend. + fn open_backend( + self, + method: Option, + pass_key: PassKey<'a>, + profile: Option, + ) -> BoxFuture<'a, Result> { + let pass_key = pass_key.into_owned(); + Box::pin(self.open(method, pass_key, profile)) + } + + /// Provision the backend with our schema. + fn provision_backend( + self, + method: StoreKeyMethod, + pass_key: PassKey<'a>, + profile: Option, + recreate: bool, + ) -> BoxFuture<'a, Result> { + let pass_key = pass_key.into_owned(); + Box::pin(self.provision(method, pass_key, profile, recreate)) + } + + /// Clean out the backend of our data/schema. + fn remove_backend(self) -> BoxFuture<'a, Result> { + Box::pin(self.remove()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Ensure that the ODBC URI is parsed correctly. + #[test] + fn odbc_parse_uri() { + let uri = "odbc://test_connection_string\ + ?connect_timeout=10\ + &idle_timeout=11\ + &max_lifetime=12\ + &max_connections=13\ + &min_connections=14\ + &schema_file=test.sql"; + let opts = OdbcStoreOptions::new(uri).unwrap(); + + assert_eq!(opts.connect_timeout, Duration::from_secs(10)); + assert_eq!(opts.idle_timeout, Duration::from_secs(11)); + assert_eq!(opts.max_lifetime, Duration::from_secs(12)); + assert_eq!(opts.max_connections, 13); + assert_eq!(opts.min_connections, 14); + assert_eq!(opts.connection_string, "test_connection_string"); + assert_eq!(opts.schema_file, "test.sql"); + } +} diff --git a/askar-storage/src/backend/odbc/r2d2_connection_pool.rs b/askar-storage/src/backend/odbc/r2d2_connection_pool.rs new file mode 100644 index 00000000..43d86e57 --- /dev/null +++ b/askar-storage/src/backend/odbc/r2d2_connection_pool.rs @@ -0,0 +1,97 @@ +// ODBC support for the `r2d2` connection pool. +use r2d2; +use std::fmt; +use std::error::Error; +use odbc_api::{ + Environment, + ConnectionOptions +}; + +use lazy_static::lazy_static; + +// We create a static ODBC environment reference so that +// it never goes out of scope. +lazy_static! { + static ref ENV: Environment = Environment::new().unwrap(); +} + +/// Define the OdbcError type, which will handle mappings from +/// an odbc_api::Error. +/// +#[derive(Debug)] +pub struct OdbcError(Box); + +impl Error for OdbcError { + fn description(&self) -> &str { + "Error connecting to the database via the ODBC driver" + } +} + +impl fmt::Display for OdbcError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +impl From for OdbcError { + fn from(err: odbc_api::Error) -> Self { + OdbcError(Box::new(err)) + } +} + +/// Define the connection, which simply wraps an +/// odbc_api::Connection object. +#[derive(Debug)] +pub struct OdbcConnection<'a>(odbc_api::Connection<'a>); + +impl <'a> OdbcConnection<'a> { + pub fn raw(&self) -> &odbc_api::Connection<'a> { + &self.0 + } +} + +/// Define the connection manager which manages the +/// pool of connections. The r2d2::ManageConnection +/// object is used to actually manage the pool of +/// connections. +#[derive(Debug)] +pub struct OdbcConnectionManager { + connection_string: String +} + +impl OdbcConnectionManager { + /// Creates a new `OdbcConnectionManager`. + pub fn new>(connection_string: S) -> OdbcConnectionManager + { + OdbcConnectionManager { + connection_string: connection_string.into() + } + } +} + +impl r2d2::ManageConnection for OdbcConnectionManager { + type Connection = OdbcConnection<'static>; + type Error = OdbcError; + + /// Create a new connection to the server. + fn connect(&self) -> std::result::Result { + let env = &ENV; + let conn = env.connect_with_connection_string(&self.connection_string, ConnectionOptions::default())?; + Ok(OdbcConnection(conn)) + } + + /// Check to see whether the connection is still valid or not. We use + /// the ODBC is_dead function, which will return true if a request to the + /// database server failed. + fn is_valid(&self, _conn: &mut Self::Connection) -> std::result::Result<(), Self::Error> { + if _conn.0.is_dead()? { + Err(OdbcError("The connection to the database is no longer valid.".into())) + } else { + Ok(()) + } + } + + fn has_broken(&self, _conn: &mut Self::Connection) -> bool { + false + } +} diff --git a/askar-storage/src/error.rs b/askar-storage/src/error.rs index 6d0232ec..db0b8ea9 100644 --- a/askar-storage/src/error.rs +++ b/askar-storage/src/error.rs @@ -144,7 +144,12 @@ impl From for Error { // FIXME would be preferable to remove this auto-conversion and handle // all sqlx errors manually, to ensure there is some context around the error -#[cfg(any(feature = "indy_compat", feature = "postgres", feature = "sqlite"))] +#[cfg(any( + feature = "indy_compat", + feature = "postgres", + feature = "sqlite", + feature = "odbc" +))] impl From for Error { fn from(err: sqlx::Error) -> Self { Error::from(ErrorKind::Backend).with_cause(err) @@ -168,6 +173,24 @@ impl From for Error { } } +impl From for Error { + fn from(err: std::string::FromUtf8Error) -> Self { + Error::from(ErrorKind::Backend).with_cause(err) + } +} + +impl From for Error { + fn from(err: std::str::Utf8Error) -> Self { + Error::from(ErrorKind::Backend).with_cause(err) + } +} + +impl From for Error { + fn from(err: std::io::Error) -> Self { + Error::from(ErrorKind::Input).with_cause(err) + } +} + macro_rules! err_msg { () => { $crate::error::Error::from($crate::error::ErrorKind::Input) diff --git a/askar-storage/src/lib.rs b/askar-storage/src/lib.rs index a744a9f6..b8ba0454 100644 --- a/askar-storage/src/lib.rs +++ b/askar-storage/src/lib.rs @@ -36,6 +36,9 @@ pub use self::backend::postgres; #[cfg(feature = "sqlite")] pub use self::backend::sqlite; +#[cfg(feature = "odbc")] +pub use self::backend::odbc; + pub mod entry; #[doc(hidden)] diff --git a/wrappers/javascript/packages/aries-askar-nodejs/tests/store.test.ts b/wrappers/javascript/packages/aries-askar-nodejs/tests/store.test.ts index 6808bd99..d3f51b3a 100644 --- a/wrappers/javascript/packages/aries-askar-nodejs/tests/store.test.ts +++ b/wrappers/javascript/packages/aries-askar-nodejs/tests/store.test.ts @@ -226,7 +226,6 @@ describe('Store and Session', () => { test('Profile', async () => { const session = await store.openSession() - await session.insert(firstEntry) await session.close() const profile = await store.createProfile() diff --git a/wrappers/javascript/packages/aries-askar-shared/src/ariesAskar/AriesAskar.ts b/wrappers/javascript/packages/aries-askar-shared/src/ariesAskar/AriesAskar.ts index f24063a1..5e380173 100644 --- a/wrappers/javascript/packages/aries-askar-shared/src/ariesAskar/AriesAskar.ts +++ b/wrappers/javascript/packages/aries-askar-shared/src/ariesAskar/AriesAskar.ts @@ -212,7 +212,7 @@ export type ScanStartOptions = { offset?: number limit?: number orderBy?: string - descending: boolean + descending?: boolean } export type SessionCloseOptions = { @@ -236,7 +236,7 @@ export type SessionFetchAllOptions = { tagFilter?: Record limit?: number orderBy?: string - descending: boolean + descending?: boolean forUpdate: boolean } export type SessionFetchAllKeysOptions = { diff --git a/wrappers/javascript/packages/aries-askar-shared/src/store/Scan.ts b/wrappers/javascript/packages/aries-askar-shared/src/store/Scan.ts index 529b1180..8aea9085 100644 --- a/wrappers/javascript/packages/aries-askar-shared/src/store/Scan.ts +++ b/wrappers/javascript/packages/aries-askar-shared/src/store/Scan.ts @@ -17,7 +17,7 @@ export class Scan { private offset?: number private limit?: number private orderBy?: string - private descending: boolean + private descending?: boolean public constructor({ category, @@ -35,7 +35,7 @@ export class Scan { offset?: number limit?: number orderBy?: string - descending: boolean + descending?: boolean store: Store }) { this.category = category diff --git a/wrappers/javascript/packages/aries-askar-shared/src/store/Session.ts b/wrappers/javascript/packages/aries-askar-shared/src/store/Session.ts index 493b7bef..ad102f56 100644 --- a/wrappers/javascript/packages/aries-askar-shared/src/store/Session.ts +++ b/wrappers/javascript/packages/aries-askar-shared/src/store/Session.ts @@ -70,7 +70,7 @@ export class Session { tagFilter?: Record limit?: number orderBy?: string - descending: boolean + descending?: boolean forUpdate?: boolean isJson?: boolean }) { diff --git a/wrappers/javascript/packages/aries-askar-shared/src/store/Store.ts b/wrappers/javascript/packages/aries-askar-shared/src/store/Store.ts index ac442674..3b0bb951 100644 --- a/wrappers/javascript/packages/aries-askar-shared/src/store/Store.ts +++ b/wrappers/javascript/packages/aries-askar-shared/src/store/Store.ts @@ -121,7 +121,7 @@ export class Store { offset?: number limit?: number orderBy?: string - descending: boolean + descending?: boolean profile?: string }) { return new Scan({ ...options, store: this })