diff --git a/Cargo.lock b/Cargo.lock index 05bd80213..087b7f87f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,11 +4,11 @@ version = 3 [[package]] name = "actix-codec" -version = "0.5.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" +checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8" dependencies = [ - "bitflags 2.6.0", + "bitflags 1.3.2", "bytes", "futures-core", "futures-sink", @@ -56,7 +56,7 @@ dependencies = [ "flate2", "futures-core", "h2", - "http 0.2.12", + "http 0.2.11", "httparse", "httpdate", "itoa", @@ -80,7 +80,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -91,7 +91,7 @@ checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" dependencies = [ "bytestring", "cfg-if", - "http 0.2.12", + "http 0.2.11", "regex-lite", "serde", "tracing", @@ -110,9 +110,9 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.4.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b02303ce8d4e8be5b855af6cf3c3a08f3eff26880faad82bab679c22d3650cb5" +checksum = "3e8613a75dd50cc45f473cee3c34d59ed677c0f7b44480ce3b8247d7dc519327" dependencies = [ "actix-rt", "actix-service", @@ -120,7 +120,8 @@ dependencies = [ "futures-core", "futures-util", "mio", - "socket2", + "num_cpus", + "socket2 0.4.9", "tokio", "tracing", ] @@ -152,7 +153,7 @@ dependencies = [ "tokio-rustls 0.24.1", "tokio-util", "tracing", - "webpki-roots 0.25.4", + "webpki-roots 0.25.3", ] [[package]] @@ -201,7 +202,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "smallvec", - "socket2", + "socket2 0.5.5", "time", "url", ] @@ -215,14 +216,14 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] name = "addr2line" -version = "0.22.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f4fa78e18c64fce05e902adecd7a5eed15a5e0a3439f7b0e169f0252214865e3" dependencies = [ "gimli", ] @@ -262,6 +263,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "const-random", "getrandom", "once_cell", "version_check", @@ -294,9 +296,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.18" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" [[package]] name = "anes" @@ -306,51 +308,50 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", - "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.48.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.48.0", ] [[package]] @@ -410,20 +411,20 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] name = "autocfg" -version = "1.3.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "4319208da049c43661739c5fade2ba182f09d1dc2299b32298d3a31692b17e12" dependencies = [ "addr2line", "cc", @@ -512,7 +513,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -597,7 +598,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", "syn_derive", ] @@ -683,9 +684,9 @@ dependencies = [ [[package]] name = "bytecount" -version = "0.6.8" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce89b21cab1437276d2650d57e971f9d548a2d9037cc231abdc0562b97498ce" +checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" [[package]] name = "bytemuck" @@ -698,13 +699,13 @@ dependencies = [ [[package]] name = "bytemuck_derive" -version = "1.7.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee891b04274a59bd38b412188e24b849617b2e45a0fd8d057deb63e7403761b" +checksum = "4da9a32f3fed317401fa3c862968128267c3106685286e15d5aaa3d7389c2f60" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -721,9 +722,9 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "bytestring" -version = "1.3.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d80203ea6b29df88012294f62733de21cfeab47f17b41af3a38bc30a03ee72" +checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae" dependencies = [ "bytes", ] @@ -751,9 +752,9 @@ dependencies = [ [[package]] name = "camino" -version = "1.1.7" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0ec6b951b160caa93cc0c7b209e5a3bff7aae9062213451ac99493cd844c239" +checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c" dependencies = [ "serde", ] @@ -768,7 +769,7 @@ dependencies = [ "candle-kernels", "cudarc", "gemm", - "half", + "half 2.4.0", "memmap2", "num-traits", "num_cpus", @@ -797,7 +798,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b006b30f66a0d94fc9cef0ac4de6ce510565f35ae2c6c35ce5d4aacfb0fc8eeb" dependencies = [ "candle-core", - "half", + "half 2.4.0", "num-traits", "rayon", "safetensors", @@ -826,9 +827,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.8" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +checksum = "ceed8ef69d8518a5dda55c07425450b58a4e1946f4951eab6d7191ee86c2443d" dependencies = [ "serde", ] @@ -865,9 +866,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.0" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaff6f8ce506b9773fa786672d63fc7a191ffea1be33f72bbd4aeacefca9ffc8" +checksum = "74b6a57f98764a267ff415d50a25e6e166f3831a5071af4995296ea97d210490" dependencies = [ "jobserver", "libc", @@ -942,9 +943,9 @@ dependencies = [ [[package]] name = "ciborium" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +checksum = "effd91f6c78e5a4ace8a5d3c0b6bfaec9e2baaef55f3efc00e45fb2e477ee926" dependencies = [ "ciborium-io", "ciborium-ll", @@ -953,18 +954,18 @@ dependencies = [ [[package]] name = "ciborium-io" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" +checksum = "cdf919175532b369853f5d5e20b26b43112613fd6fe7aee757e35f7a44642656" [[package]] name = "ciborium-ll" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +checksum = "defaa24ecc093c77630e6c15e17c51f5e187bf35ee514f4e2d67baaa96dae22b" dependencies = [ "ciborium-io", - "half", + "half 1.8.2", ] [[package]] @@ -979,9 +980,9 @@ dependencies = [ [[package]] name = "clang-sys" -version = "1.8.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1" dependencies = [ "glob", "libc", @@ -1019,7 +1020,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -1042,9 +1043,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" [[package]] name = "concat-arrays" @@ -1059,15 +1060,35 @@ dependencies = [ [[package]] name = "console" -version = "0.15.8" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.52.0", + "windows-sys 0.45.0", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom", + "once_cell", + "tiny-keccak", ] [[package]] @@ -1104,15 +1125,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cow-utils" -version = "0.1.3" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "417bef24afe1460300965a25ff4a24b8b45ad011948302ec221e8a0a81eb2c79" +checksum = "79bb3adfaf5f75d24b01aee375f7555907840fa2800e5ec8fa3b9e2031830173" [[package]] name = "cpufeatures" @@ -1282,7 +1303,7 @@ version = "0.11.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ee2a3fbbd981e1c7ea73cc2af136e754eb22d17436de37155227ee4dbe0cf4" dependencies = [ - "half", + "half 2.4.0", "libloading", ] @@ -1298,12 +1319,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" dependencies = [ - "darling_core 0.20.10", - "darling_macro 0.20.10", + "darling_core 0.20.9", + "darling_macro 0.20.9", ] [[package]] @@ -1322,16 +1343,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -1347,13 +1368,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" dependencies = [ - "darling_core 0.20.10", + "darling_core 0.20.9", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -1389,7 +1410,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -1428,10 +1449,10 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" dependencies = [ - "darling 0.20.10", + "darling 0.20.9", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -1451,20 +1472,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core 0.20.0", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] name = "derive_more" -version = "0.99.18" +version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case 0.4.0", "proc-macro2", "quote", "rustc_version", - "syn 2.0.70", + "syn 1.0.109", ] [[package]] @@ -1493,7 +1514,7 @@ dependencies = [ "convert_case 0.6.0", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -1563,7 +1584,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -1696,9 +1717,9 @@ checksum = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] @@ -1721,7 +1742,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -1741,7 +1762,7 @@ checksum = "a1ab991c1362ac86c61ab6f556cff143daa22e5a15e4e189df818b2fd19fe65b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -1752,9 +1773,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1805,14 +1826,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "redox_syscall 0.3.5", + "windows-sys 0.48.0", ] [[package]] @@ -1926,7 +1947,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -2053,7 +2074,7 @@ checksum = "a2e7ea062c987abcd8db95db917b4ffb4ecdfd0668471d8dc54734fdff2354e8" dependencies = [ "bytemuck", "dyn-stack", - "half", + "half 2.4.0", "num-complex", "num-traits", "once_cell", @@ -2074,7 +2095,7 @@ dependencies = [ "dyn-stack", "gemm-common", "gemm-f32", - "half", + "half 2.4.0", "num-complex", "num-traits", "paste", @@ -2131,9 +2152,9 @@ checksum = "36d244a08113319b5ebcabad2b8b7925732d15eec46d7e7ac3c11734f3b7a6ad" [[package]] name = "getrandom" -version = "0.2.15" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c" dependencies = [ "cfg-if", "js-sys", @@ -2156,9 +2177,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.27.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" [[package]] name = "git2" @@ -2202,7 +2223,7 @@ dependencies = [ "futures-core", "futures-sink", "futures-util", - "http 0.2.12", + "http 0.2.11", "indexmap", "slab", "tokio", @@ -2212,9 +2233,15 @@ dependencies = [ [[package]] name = "half" -version = "2.4.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + +[[package]] +name = "half" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e" dependencies = [ "bytemuck", "cfg-if", @@ -2244,9 +2271,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" dependencies = [ "ahash 0.8.11", "allocator-api2", @@ -2350,9 +2377,9 @@ dependencies = [ [[package]] name = "http" -version = "0.2.12" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -2395,15 +2422,15 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.4" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" @@ -2439,7 +2466,7 @@ dependencies = [ "tokio", "tokio-rustls 0.26.0", "tower-service", - "webpki-roots 0.26.3", + "webpki-roots 0.26.1", ] [[package]] @@ -2455,7 +2482,7 @@ dependencies = [ "http-body", "hyper", "pin-project-lite", - "socket2", + "socket2 0.5.5", "tokio", "tower", "tower-service", @@ -2525,15 +2552,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown 0.14.5", + "hashbrown 0.14.3", "serde", ] [[package]] name = "indicatif" -version = "0.17.8" +version = "0.17.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" +checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" dependencies = [ "console", "instant", @@ -2568,18 +2595,18 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.13" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if", ] [[package]] name = "ipnet" -version = "2.9.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "irg-kvariants" @@ -2603,12 +2630,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "is_terminal_polyfill" -version = "1.70.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" - [[package]] name = "itertools" version = "0.10.5" @@ -2778,7 +2799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.52.4", ] [[package]] @@ -2808,21 +2829,11 @@ dependencies = [ "libc", ] -[[package]] -name = "libredox" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" -dependencies = [ - "bitflags 2.6.0", - "libc", -] - [[package]] name = "libz-sys" -version = "1.1.18" +version = "1.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15da26e5af7e25c90b37a2d75cdbf940cf4a55316de9d84c679c9b8bfabf82e" +checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" dependencies = [ "cc", "libc", @@ -3151,9 +3162,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" [[package]] name = "liquid" @@ -3194,7 +3205,7 @@ checksum = "915f6d0a2963a27cd5205c1902f32ddfe3bc035816afd268cf88c0fc0f8d287e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -3231,26 +3242,27 @@ dependencies = [ [[package]] name = "local-channel" -version = "0.1.5" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" +checksum = "7f303ec0e94c6c54447f84f3b0ef7af769858a9c4ef56ef2a986d3dcd4c3fc9c" dependencies = [ "futures-core", "futures-sink", + "futures-util", "local-waker", ] [[package]] name = "local-waker" -version = "0.1.4" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" +checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1" [[package]] name = "lock_api" -version = "0.4.12" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -3264,9 +3276,9 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] name = "log" -version = "0.4.22" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lzma-rs" @@ -3303,7 +3315,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -3536,6 +3548,8 @@ dependencies = [ "ordered-float", "rand", "rayon", + "rayon-par-bridge", + "rhai", "roaring", "rstar", "serde", @@ -3572,9 +3586,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.5" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime", "unicase", @@ -3588,9 +3602,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -3609,9 +3623,9 @@ dependencies = [ [[package]] name = "monostate" -version = "0.1.13" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d208407d7552cd041d8cdb69a1bc3303e029c598738177a3d87082004dc0e1e" +checksum = "15f370ae88093ec6b11a710dec51321a61d420fafd1bad6e30d01bd9c920e8ee" dependencies = [ "monostate-impl", "serde", @@ -3619,13 +3633,13 @@ dependencies = [ [[package]] name = "monostate-impl" -version = "0.1.13" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7ce64b975ed4f123575d11afd9491f2e37bbd5813fbfbc0f09ae1fbddea74e0" +checksum = "371717c0a5543d6a800cac822eac735aa7d2d2fbb41002e9856a4089532dbdce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -3676,19 +3690,20 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" dependencies = [ + "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.6" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" dependencies = [ "bytemuck", "num-traits", @@ -3702,18 +3717,19 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" [[package]] name = "num-integer" -version = "0.1.46" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ + "autocfg", "num-traits", ] [[package]] name = "num-traits" -version = "0.2.19" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", @@ -3747,7 +3763,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -3767,9 +3783,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.36.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "8bda667d9f2b5051b8833f59f3bf748b28ef54f850f4fcb389a252aa383866d1" dependencies = [ "memchr", ] @@ -3810,9 +3826,9 @@ dependencies = [ [[package]] name = "oorandom" -version = "11.1.4" +version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b410bbe7e14ab526a0e86877eb47c6996a2bd7746f027ba551028c925390e4e9" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "option-ext" @@ -3863,22 +3879,22 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.10" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.2", + "redox_syscall 0.3.5", "smallvec", - "windows-targets 0.52.6", + "windows-targets 0.48.1", ] [[package]] name = "paste" -version = "1.0.15" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "path-matchers" @@ -3907,11 +3923,11 @@ dependencies = [ [[package]] name = "pem" -version = "3.0.4" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" +checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ - "base64 0.22.1", + "base64 0.21.7", "serde", ] @@ -3931,20 +3947,19 @@ dependencies = [ [[package]] name = "pest" -version = "2.7.11" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd53dff83f26735fdc1ca837098ccf133605d794cdae66acfc2bfac3ec809d95" +checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a" dependencies = [ - "memchr", "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.11" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a548d2beca6773b1c244554d36fcf8548a8a58e74156968211567250e48e49a" +checksum = "666d00490d4ac815001da55838c500eafb0320019bbaa44444137c48b443a853" dependencies = [ "pest", "pest_generator", @@ -3952,22 +3967,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.11" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c93a82e8d145725dcbaf44e5ea887c8a869efdcc28706df2d08c69e17077183" +checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] name = "pest_meta" -version = "2.7.11" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a941429fea7e08bedec25e4f6785b6ffaacc6b755da98df5ef3e7dcf4a124c4f" +checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" dependencies = [ "once_cell", "pest", @@ -4014,7 +4029,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -4028,22 +4043,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -4081,9 +4096,9 @@ dependencies = [ [[package]] name = "plotters" -version = "0.3.6" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ "num-traits", "plotters-backend", @@ -4094,24 +4109,24 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.6" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "plotters-svg" -version = "0.3.6" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ "plotters-backend", ] [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "3bccab0e7fd7cc19f820a1c8c91720af652d0c88dc9664dd72aef2614f04af3b" [[package]] name = "powerfmt" @@ -4131,7 +4146,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit 0.21.1", + "toml_edit 0.21.0", ] [[package]] @@ -4160,9 +4175,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] @@ -4235,9 +4250,9 @@ dependencies = [ [[package]] name = "pulp" -version = "0.18.21" +version = "0.18.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ec8d02258294f59e4e223b41ad7e81c874aa6b15bc4ced9ba3965826da0eed5" +checksum = "03457ac216146f43f921500bac4e892d5cd32b0479b929cbfc90f95cd6c599c2" dependencies = [ "bytemuck", "libm", @@ -4287,7 +4302,7 @@ checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" dependencies = [ "libc", "once_cell", - "socket2", + "socket2 0.5.5", "tracing", "windows-sys 0.52.0", ] @@ -4387,6 +4402,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rayon-par-bridge" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb6a14d8f65834aca6b0fe4cbbd7a27e639cd3efb1f2a32de9942368f1991de8" +dependencies = [ + "rayon", +] + [[package]] name = "reborrow" version = "0.5.5" @@ -4395,30 +4419,30 @@ checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags 2.6.0", + "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "libredox", + "redox_syscall 0.2.16", "thiserror", ] @@ -4436,9 +4460,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -4453,9 +4477,9 @@ checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "rend" @@ -4507,10 +4531,39 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.26.3", + "webpki-roots 0.26.1", "winreg", ] +[[package]] +name = "rhai" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61797318be89b1a268a018a92a7657096d83f3ecb31418b9e9c16dcbb043b702" +dependencies = [ + "ahash 0.8.11", + "bitflags 2.6.0", + "instant", + "num-traits", + "once_cell", + "rhai_codegen", + "serde", + "smallvec", + "smartstring", + "thin-vec", +] + +[[package]] +name = "rhai_codegen" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5a11a05ee1ce44058fa3d5961d05194fdbe3ad6b40f904af764d81b86450e6b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.60", +] + [[package]] name = "ring" version = "0.17.8" @@ -4596,9 +4649,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.24" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc-hash" @@ -4617,9 +4670,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ "bitflags 2.6.0", "errno", @@ -4709,15 +4762,15 @@ checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "ryu" -version = "1.0.18" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "safetensors" -version = "0.4.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ced76b22c7fba1162f11a5a75d9d8405264b467a07ae0c9c29be119b9297db9" +checksum = "8d980e6bfb34436fb0a81e42bc41af43f11805bbbca443e7f68e9faaabe669ed" dependencies = [ "serde", "serde_json", @@ -4770,9 +4823,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918" dependencies = [ "serde", ] @@ -4809,7 +4862,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -4904,9 +4957,9 @@ checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" dependencies = [ "libc", ] @@ -4925,9 +4978,9 @@ checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" [[package]] name = "similar" -version = "2.5.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa42c91313f1d05da9b26f267f931cf178d4aba455b4c4622dd7355eb80c6640" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" [[package]] name = "simple_asn1" @@ -4955,9 +5008,9 @@ checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" -version = "0.4.9" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" dependencies = [ "autocfg", ] @@ -4983,6 +5036,9 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] name = "smartstring" @@ -4991,18 +5047,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fb72c633efbaa2dd666986505016c32c3044395ceaf881518399d2f4127ee29" dependencies = [ "autocfg", + "serde", "static_assertions", "version_check", ] [[package]] name = "socket2" -version = "0.5.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", - "windows-sys 0.52.0", + "winapi", +] + +[[package]] +name = "socket2" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +dependencies = [ + "libc", + "windows-sys 0.48.0", ] [[package]] @@ -5071,31 +5138,31 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.3" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" dependencies = [ "strum_macros", ] [[package]] name = "strum_macros" -version = "0.26.4" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" dependencies = [ - "heck 0.5.0", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] name = "subtle" -version = "2.6.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "syn" @@ -5110,9 +5177,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.70" +version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0209b68b3613b093e0ec905354eccaedcfe83b8cb37cbdeae64026c3064c16" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", @@ -5128,7 +5195,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -5154,7 +5221,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -5233,6 +5300,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "thin-vec" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a38c90d48152c236a3ab59271da4f4ae63d678c5d7ad6b7714d7cb9760be5e4b" +dependencies = [ + "serde", +] + [[package]] name = "thiserror" version = "1.0.61" @@ -5250,14 +5326,14 @@ checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] name = "thread_local" -version = "1.1.8" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ "cfg-if", "once_cell", @@ -5311,6 +5387,15 @@ dependencies = [ "time-core", ] +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -5323,9 +5408,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -5380,7 +5465,7 @@ dependencies = [ "parking_lot", "pin-project-lite", "signal-hook-registry", - "socket2", + "socket2 0.5.5", "tokio-macros", "windows-sys 0.48.0", ] @@ -5393,7 +5478,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -5453,9 +5538,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.1" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" dependencies = [ "indexmap", "toml_datetime", @@ -5535,7 +5620,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -5614,9 +5699,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.5" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typenum" @@ -5641,9 +5726,9 @@ dependencies = [ [[package]] name = "unicase" -version = "2.7.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ "version_check", ] @@ -5692,9 +5777,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode_categories" @@ -5724,7 +5809,7 @@ dependencies = [ "serde_json", "socks", "url", - "webpki-roots 0.26.3", + "webpki-roots 0.26.1", ] [[package]] @@ -5747,15 +5832,15 @@ checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" [[package]] name = "utf8-width" -version = "0.1.7" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" +checksum = "5190c9442dcdaf0ddd50f37420417d219ae5261bbf5db120d0f9bab996c9cba1" [[package]] name = "utf8parse" -version = "0.2.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" +checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" @@ -5881,15 +5966,15 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if", "js-sys", @@ -5915,7 +6000,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5941,9 +6026,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -5951,15 +6036,15 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.4" +version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "b3de34ae270483955a94f4b21bdaaeb83d508bb84a01435f393818edb0012009" dependencies = [ "rustls-pki-types", ] @@ -5970,7 +6055,7 @@ version = "0.16.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "471d1c1645d361eb782a1650b1786a8fb58dd625e681a04c09f5ff7c8764a7b0" dependencies = [ - "hashbrown 0.14.5", + "hashbrown 0.14.3", "once_cell", ] @@ -5992,11 +6077,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ - "windows-sys 0.52.0", + "winapi", ] [[package]] @@ -6012,7 +6097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core", - "windows-targets 0.52.6", + "windows-targets 0.52.4", ] [[package]] @@ -6021,7 +6106,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", ] [[package]] @@ -6030,7 +6124,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.5", + "windows-targets 0.48.1", ] [[package]] @@ -6039,129 +6133,179 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.6", + "windows-targets 0.52.4", ] [[package]] name = "windows-targets" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" dependencies = [ - "windows_aarch64_gnullvm 0.48.5", - "windows_aarch64_msvc 0.48.5", - "windows_i686_gnu 0.48.5", - "windows_i686_msvc 0.48.5", - "windows_x86_64_gnu 0.48.5", - "windows_x86_64_gnullvm 0.48.5", - "windows_x86_64_msvc 0.48.5", + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] name = "windows-targets" -version = "0.52.6" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ - "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", + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" +name = "windows_i686_gnu" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" -version = "0.48.5" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.52.6" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" @@ -6253,9 +6397,9 @@ dependencies = [ [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "65e71b2e4f287f467794c671e2b8f8a5f3716b3c829079a1c44740148eff07e4" dependencies = [ "serde", "stable_deref_trait", @@ -6265,54 +6409,54 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", "synstructure", ] [[package]] name = "zerocopy" -version = "0.7.35" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.35" +version = "0.7.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "655b0814c5c0b19ade497851070c640773304939a6c0fd5f5fb43da0696d05b7" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", "synstructure", ] @@ -6333,7 +6477,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.70", + "syn 2.0.60", ] [[package]] @@ -6423,9 +6567,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.12+zstd.1.5.6" +version = "2.0.10+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" +checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" dependencies = [ "cc", "pkg-config", diff --git a/dump/src/lib.rs b/dump/src/lib.rs index 42cb0e444..722633ec6 100644 --- a/dump/src/lib.rs +++ b/dump/src/lib.rs @@ -104,6 +104,11 @@ pub enum KindDump { DocumentDeletionByFilter { filter: serde_json::Value, }, + DocumentEdition { + filter: Option, + context: Option>, + function: String, + }, Settings { settings: Box>, is_deletion: bool, @@ -172,6 +177,9 @@ impl From for KindDump { KindWithContent::DocumentDeletionByFilter { filter_expr, .. } => { KindDump::DocumentDeletionByFilter { filter: filter_expr } } + KindWithContent::DocumentEdition { filter_expr, context, function, .. } => { + KindDump::DocumentEdition { filter: filter_expr, context, function } + } KindWithContent::DocumentClear { .. } => KindDump::DocumentClear, KindWithContent::SettingsUpdate { new_settings, diff --git a/index-scheduler/src/autobatcher.rs b/index-scheduler/src/autobatcher.rs index dc184947c..96201bebb 100644 --- a/index-scheduler/src/autobatcher.rs +++ b/index-scheduler/src/autobatcher.rs @@ -24,6 +24,7 @@ enum AutobatchKind { allow_index_creation: bool, primary_key: Option, }, + DocumentEdition, DocumentDeletion, DocumentDeletionByFilter, DocumentClear, @@ -63,6 +64,7 @@ impl From for AutobatchKind { primary_key, .. } => AutobatchKind::DocumentImport { method, allow_index_creation, primary_key }, + KindWithContent::DocumentEdition { .. } => AutobatchKind::DocumentEdition, KindWithContent::DocumentDeletion { .. } => AutobatchKind::DocumentDeletion, KindWithContent::DocumentClear { .. } => AutobatchKind::DocumentClear, KindWithContent::DocumentDeletionByFilter { .. } => { @@ -98,6 +100,9 @@ pub enum BatchKind { primary_key: Option, operation_ids: Vec, }, + DocumentEdition { + id: TaskId, + }, DocumentDeletion { deletion_ids: Vec, }, @@ -199,6 +204,7 @@ impl BatchKind { }), allow_index_creation, ), + K::DocumentEdition => (Break(BatchKind::DocumentEdition { id: task_id }), false), K::DocumentDeletion => { (Continue(BatchKind::DocumentDeletion { deletion_ids: vec![task_id] }), false) } @@ -222,7 +228,7 @@ impl BatchKind { match (self, kind) { // We don't batch any of these operations - (this, K::IndexCreation | K::IndexUpdate | K::IndexSwap | K::DocumentDeletionByFilter) => Break(this), + (this, K::IndexCreation | K::IndexUpdate | K::IndexSwap | K::DocumentEdition | K::DocumentDeletionByFilter) => Break(this), // We must not batch tasks that don't have the same index creation rights if the index doesn't already exists. (this, kind) if !index_already_exists && this.allow_index_creation() == Some(false) && kind.allow_index_creation() == Some(true) => { Break(this) @@ -519,6 +525,7 @@ impl BatchKind { | BatchKind::IndexDeletion { .. } | BatchKind::IndexUpdate { .. } | BatchKind::IndexSwap { .. } + | BatchKind::DocumentEdition { .. } | BatchKind::DocumentDeletionByFilter { .. }, _, ) => { diff --git a/index-scheduler/src/batch.rs b/index-scheduler/src/batch.rs index cd5525eea..d504ef915 100644 --- a/index-scheduler/src/batch.rs +++ b/index-scheduler/src/batch.rs @@ -34,7 +34,7 @@ use meilisearch_types::milli::update::{ use meilisearch_types::milli::vector::parsed_vectors::{ ExplicitVectors, VectorOrArrayOfVectors, RESERVED_VECTORS_FIELD_NAME, }; -use meilisearch_types::milli::{self, Filter}; +use meilisearch_types::milli::{self, Filter, Object}; use meilisearch_types::settings::{apply_settings_to_builder, Settings, Unchecked}; use meilisearch_types::tasks::{Details, IndexSwap, Kind, KindWithContent, Status, Task}; use meilisearch_types::{compression, Index, VERSION_FILE_NAME}; @@ -106,6 +106,10 @@ pub(crate) enum IndexOperation { operations: Vec, tasks: Vec, }, + DocumentEdition { + index_uid: String, + task: Task, + }, IndexDocumentDeletionByFilter { index_uid: String, task: Task, @@ -164,7 +168,8 @@ impl Batch { | IndexOperation::DocumentClear { tasks, .. } => { RoaringBitmap::from_iter(tasks.iter().map(|task| task.uid)) } - IndexOperation::IndexDocumentDeletionByFilter { task, .. } => { + IndexOperation::DocumentEdition { task, .. } + | IndexOperation::IndexDocumentDeletionByFilter { task, .. } => { RoaringBitmap::from_sorted_iter(std::iter::once(task.uid)).unwrap() } IndexOperation::SettingsAndDocumentOperation { @@ -228,6 +233,7 @@ impl IndexOperation { pub fn index_uid(&self) -> &str { match self { IndexOperation::DocumentOperation { index_uid, .. } + | IndexOperation::DocumentEdition { index_uid, .. } | IndexOperation::IndexDocumentDeletionByFilter { index_uid, .. } | IndexOperation::DocumentClear { index_uid, .. } | IndexOperation::Settings { index_uid, .. } @@ -243,6 +249,9 @@ impl fmt::Display for IndexOperation { IndexOperation::DocumentOperation { .. } => { f.write_str("IndexOperation::DocumentOperation") } + IndexOperation::DocumentEdition { .. } => { + f.write_str("IndexOperation::DocumentEdition") + } IndexOperation::IndexDocumentDeletionByFilter { .. } => { f.write_str("IndexOperation::IndexDocumentDeletionByFilter") } @@ -295,6 +304,21 @@ impl IndexScheduler { _ => unreachable!(), } } + BatchKind::DocumentEdition { id } => { + let task = self.get_task(rtxn, id)?.ok_or(Error::CorruptedTaskQueue)?; + match &task.kind { + KindWithContent::DocumentEdition { index_uid, .. } => { + Ok(Some(Batch::IndexOperation { + op: IndexOperation::DocumentEdition { + index_uid: index_uid.clone(), + task, + }, + must_create_index: false, + })) + } + _ => unreachable!(), + } + } BatchKind::DocumentOperation { method, operation_ids, .. } => { let tasks = self.get_existing_tasks(rtxn, operation_ids)?; let primary_key = tasks @@ -1386,6 +1410,64 @@ impl IndexScheduler { Ok(tasks) } + IndexOperation::DocumentEdition { mut task, .. } => { + let (filter, context, function) = + if let KindWithContent::DocumentEdition { + filter_expr, context, function, .. + } = &task.kind + { + (filter_expr, context, function) + } else { + unreachable!() + }; + let result_count = edit_documents_by_function( + index_wtxn, + filter, + context.clone(), + function, + self.index_mapper.indexer_config(), + self.must_stop_processing.clone(), + index, + ); + let (original_filter, context, function) = if let Some(Details::DocumentEdition { + original_filter, + context, + function, + .. + }) = task.details + { + (original_filter, context, function) + } else { + // In the case of a `documentDeleteByFilter` the details MUST be set + unreachable!(); + }; + + match result_count { + Ok((deleted_documents, edited_documents)) => { + task.status = Status::Succeeded; + task.details = Some(Details::DocumentEdition { + original_filter, + context, + function, + deleted_documents: Some(deleted_documents), + edited_documents: Some(edited_documents), + }); + } + Err(e) => { + task.status = Status::Failed; + task.details = Some(Details::DocumentEdition { + original_filter, + context, + function, + deleted_documents: Some(0), + edited_documents: Some(0), + }); + task.error = Some(e.into()); + } + } + + Ok(vec![task]) + } IndexOperation::IndexDocumentDeletionByFilter { mut task, index_uid: _ } => { let filter = if let KindWithContent::DocumentDeletionByFilter { filter_expr, .. } = @@ -1674,3 +1756,44 @@ fn delete_document_by_filter<'a>( 0 }) } + +fn edit_documents_by_function<'a>( + wtxn: &mut RwTxn<'a>, + filter: &Option, + context: Option, + code: &str, + indexer_config: &IndexerConfig, + must_stop_processing: MustStopProcessing, + index: &'a Index, +) -> Result<(u64, u64)> { + let candidates = match filter.as_ref().map(Filter::from_json) { + Some(Ok(Some(filter))) => filter.evaluate(wtxn, index).map_err(|err| match err { + milli::Error::UserError(milli::UserError::InvalidFilter(_)) => { + Error::from(err).with_custom_error_code(Code::InvalidDocumentFilter) + } + e => e.into(), + })?, + None | Some(Ok(None)) => index.documents_ids(wtxn)?, + Some(Err(e)) => return Err(e.into()), + }; + + let config = IndexDocumentsConfig { + update_method: IndexDocumentsMethod::ReplaceDocuments, + ..Default::default() + }; + + let mut builder = milli::update::IndexDocuments::new( + wtxn, + index, + indexer_config, + config, + |indexing_step| tracing::debug!(update = ?indexing_step), + || must_stop_processing.get(), + )?; + + let (new_builder, count) = builder.edit_documents(&candidates, context, code)?; + builder = new_builder; + + let _ = builder.execute()?; + Ok(count.unwrap()) +} diff --git a/index-scheduler/src/features.rs b/index-scheduler/src/features.rs index ae8e6728a..fbb273e54 100644 --- a/index-scheduler/src/features.rs +++ b/index-scheduler/src/features.rs @@ -68,6 +68,19 @@ impl RoFeatures { .into()) } } + + pub fn check_edit_documents_by_function(&self, disabled_action: &'static str) -> Result<()> { + if self.runtime.edit_documents_by_function { + Ok(()) + } else { + Err(FeatureNotEnabledError { + disabled_action, + feature: "edit documents by function", + issue_link: "https://github.com/orgs/meilisearch/discussions/762", + } + .into()) + } + } } impl FeatureData { diff --git a/index-scheduler/src/insta_snapshot.rs b/index-scheduler/src/insta_snapshot.rs index d8625a2c7..c65bb0716 100644 --- a/index-scheduler/src/insta_snapshot.rs +++ b/index-scheduler/src/insta_snapshot.rs @@ -177,6 +177,17 @@ fn snapshot_details(d: &Details) -> String { } => { format!("{{ received_documents: {received_documents}, indexed_documents: {indexed_documents:?} }}") } + Details::DocumentEdition { + deleted_documents, + edited_documents, + original_filter, + context, + function, + } => { + format!( + "{{ deleted_documents: {deleted_documents:?}, edited_documents: {edited_documents:?}, context: {context:?}, function: {function:?}, original_filter: {original_filter:?} }}" + ) + } Details::SettingsUpdate { settings } => { format!("{{ settings: {settings:?} }}") } diff --git a/index-scheduler/src/lib.rs b/index-scheduler/src/lib.rs index 0b98cc22a..da57bfc9b 100644 --- a/index-scheduler/src/lib.rs +++ b/index-scheduler/src/lib.rs @@ -1603,6 +1603,14 @@ impl<'a> Dump<'a> { index_uid: task.index_uid.ok_or(Error::CorruptedDump)?, } } + KindDump::DocumentEdition { filter, context, function } => { + KindWithContent::DocumentEdition { + index_uid: task.index_uid.ok_or(Error::CorruptedDump)?, + filter_expr: filter, + context, + function, + } + } KindDump::DocumentClear => KindWithContent::DocumentClear { index_uid: task.index_uid.ok_or(Error::CorruptedDump)?, }, @@ -4744,6 +4752,7 @@ mod tests { "types": { "documentAdditionOrUpdate": 0, "documentDeletion": 0, + "documentEdition": 0, "dumpCreation": 0, "indexCreation": 3, "indexDeletion": 0, @@ -4775,6 +4784,7 @@ mod tests { "types": { "documentAdditionOrUpdate": 0, "documentDeletion": 0, + "documentEdition": 0, "dumpCreation": 0, "indexCreation": 3, "indexDeletion": 0, @@ -4813,6 +4823,7 @@ mod tests { "types": { "documentAdditionOrUpdate": 0, "documentDeletion": 0, + "documentEdition": 0, "dumpCreation": 0, "indexCreation": 3, "indexDeletion": 0, @@ -4852,6 +4863,7 @@ mod tests { "types": { "documentAdditionOrUpdate": 0, "documentDeletion": 0, + "documentEdition": 0, "dumpCreation": 0, "indexCreation": 3, "indexDeletion": 0, diff --git a/index-scheduler/src/utils.rs b/index-scheduler/src/utils.rs index 260ff6ee4..788a70fb8 100644 --- a/index-scheduler/src/utils.rs +++ b/index-scheduler/src/utils.rs @@ -238,6 +238,7 @@ pub fn swap_index_uid_in_task(task: &mut Task, swap: (&str, &str)) { let mut index_uids = vec![]; match &mut task.kind { K::DocumentAdditionOrUpdate { index_uid, .. } => index_uids.push(index_uid), + K::DocumentEdition { index_uid, .. } => index_uids.push(index_uid), K::DocumentDeletion { index_uid, .. } => index_uids.push(index_uid), K::DocumentDeletionByFilter { index_uid, .. } => index_uids.push(index_uid), K::DocumentClear { index_uid } => index_uids.push(index_uid), @@ -408,7 +409,26 @@ impl IndexScheduler { match status { Status::Succeeded => assert!(indexed_documents <= received_documents), Status::Failed | Status::Canceled => assert_eq!(indexed_documents, 0), - status => panic!("DocumentAddition can't have an indexed_document set if it's {}", status), + status => panic!("DocumentAddition can't have an indexed_documents set if it's {}", status), + } + } + None => { + assert!(matches!(status, Status::Enqueued | Status::Processing)) + } + } + } + Details::DocumentEdition { edited_documents, .. } => { + assert_eq!(kind.as_kind(), Kind::DocumentEdition); + match edited_documents { + Some(edited_documents) => { + assert!(matches!( + status, + Status::Succeeded | Status::Failed | Status::Canceled + )); + match status { + Status::Succeeded => (), + Status::Failed | Status::Canceled => assert_eq!(edited_documents, 0), + status => panic!("DocumentEdition can't have an edited_documents set if it's {}", status), } } None => { diff --git a/meilisearch-types/src/deserr/mod.rs b/meilisearch-types/src/deserr/mod.rs index 1c1b0e987..87ca342d7 100644 --- a/meilisearch-types/src/deserr/mod.rs +++ b/meilisearch-types/src/deserr/mod.rs @@ -155,6 +155,10 @@ make_missing_field_convenience_builder!( MissingFacetSearchFacetName, missing_facet_search_facet_name ); +make_missing_field_convenience_builder!( + MissingDocumentEditionFunction, + missing_document_edition_function +); // Integrate a sub-error into a [`DeserrError`] by taking its error message but using // the default error code (C) from `Self` diff --git a/meilisearch-types/src/error.rs b/meilisearch-types/src/error.rs index f529238e4..092d852ac 100644 --- a/meilisearch-types/src/error.rs +++ b/meilisearch-types/src/error.rs @@ -224,6 +224,7 @@ InvalidDocumentCsvDelimiter , InvalidRequest , BAD_REQUEST ; InvalidDocumentFields , InvalidRequest , BAD_REQUEST ; InvalidDocumentRetrieveVectors , InvalidRequest , BAD_REQUEST ; MissingDocumentFilter , InvalidRequest , BAD_REQUEST ; +MissingDocumentEditionFunction , InvalidRequest , BAD_REQUEST ; InvalidDocumentFilter , InvalidRequest , BAD_REQUEST ; InvalidDocumentGeoField , InvalidRequest , BAD_REQUEST ; InvalidVectorDimensions , InvalidRequest , BAD_REQUEST ; @@ -336,7 +337,10 @@ UnsupportedMediaType , InvalidRequest , UNSUPPORTED_MEDIA // Experimental features VectorEmbeddingError , InvalidRequest , BAD_REQUEST ; -NotFoundSimilarId , InvalidRequest , BAD_REQUEST +NotFoundSimilarId , InvalidRequest , BAD_REQUEST ; +InvalidDocumentEditionContext , InvalidRequest , BAD_REQUEST ; +InvalidDocumentEditionFunctionFilter , InvalidRequest , BAD_REQUEST ; +EditDocumentsByFunctionError , InvalidRequest , BAD_REQUEST } impl ErrorCode for JoinError { @@ -407,6 +411,12 @@ impl ErrorCode for milli::Error { } UserError::InvalidEmbedder(_) => Code::InvalidEmbedder, UserError::VectorEmbeddingError(_) => Code::VectorEmbeddingError, + UserError::DocumentEditionCannotModifyPrimaryKey + | UserError::DocumentEditionDocumentMustBeObject + | UserError::DocumentEditionRuntimeError(_) + | UserError::DocumentEditionCompilationError(_) => { + Code::EditDocumentsByFunctionError + } } } } diff --git a/meilisearch-types/src/features.rs b/meilisearch-types/src/features.rs index dda9dee51..f15a1c999 100644 --- a/meilisearch-types/src/features.rs +++ b/meilisearch-types/src/features.rs @@ -6,6 +6,7 @@ pub struct RuntimeTogglableFeatures { pub vector_store: bool, pub metrics: bool, pub logs_route: bool, + pub edit_documents_by_function: bool, } #[derive(Default, Debug, Clone, Copy)] diff --git a/meilisearch-types/src/task_view.rs b/meilisearch-types/src/task_view.rs index 659427c9d..3075fa899 100644 --- a/meilisearch-types/src/task_view.rs +++ b/meilisearch-types/src/task_view.rs @@ -1,3 +1,4 @@ +use milli::Object; use serde::Serialize; use time::{Duration, OffsetDateTime}; @@ -54,6 +55,8 @@ pub struct DetailsView { #[serde(skip_serializing_if = "Option::is_none")] pub indexed_documents: Option>, #[serde(skip_serializing_if = "Option::is_none")] + pub edited_documents: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub primary_key: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub provided_ids: Option, @@ -70,6 +73,10 @@ pub struct DetailsView { #[serde(skip_serializing_if = "Option::is_none")] pub dump_uid: Option>, #[serde(skip_serializing_if = "Option::is_none")] + pub context: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + pub function: Option, + #[serde(skip_serializing_if = "Option::is_none")] #[serde(flatten)] pub settings: Option>>, #[serde(skip_serializing_if = "Option::is_none")] @@ -86,6 +93,20 @@ impl From
for DetailsView { ..DetailsView::default() } } + Details::DocumentEdition { + deleted_documents, + edited_documents, + original_filter, + context, + function, + } => DetailsView { + deleted_documents: Some(deleted_documents), + edited_documents: Some(edited_documents), + original_filter: Some(original_filter), + context: Some(context), + function: Some(function), + ..DetailsView::default() + }, Details::SettingsUpdate { mut settings } => { settings.hide_secrets(); DetailsView { settings: Some(settings), ..DetailsView::default() } diff --git a/meilisearch-types/src/tasks.rs b/meilisearch-types/src/tasks.rs index 693ee4242..1dd6d3fbf 100644 --- a/meilisearch-types/src/tasks.rs +++ b/meilisearch-types/src/tasks.rs @@ -5,6 +5,7 @@ use std::str::FromStr; use enum_iterator::Sequence; use milli::update::IndexDocumentsMethod; +use milli::Object; use roaring::RoaringBitmap; use serde::{Deserialize, Serialize, Serializer}; use time::{Duration, OffsetDateTime}; @@ -48,6 +49,7 @@ impl Task { | TaskDeletion { .. } | IndexSwap { .. } => None, DocumentAdditionOrUpdate { index_uid, .. } + | DocumentEdition { index_uid, .. } | DocumentDeletion { index_uid, .. } | DocumentDeletionByFilter { index_uid, .. } | DocumentClear { index_uid } @@ -67,7 +69,8 @@ impl Task { pub fn content_uuid(&self) -> Option { match self.kind { KindWithContent::DocumentAdditionOrUpdate { content_file, .. } => Some(content_file), - KindWithContent::DocumentDeletion { .. } + KindWithContent::DocumentEdition { .. } + | KindWithContent::DocumentDeletion { .. } | KindWithContent::DocumentDeletionByFilter { .. } | KindWithContent::DocumentClear { .. } | KindWithContent::SettingsUpdate { .. } @@ -102,6 +105,12 @@ pub enum KindWithContent { index_uid: String, filter_expr: serde_json::Value, }, + DocumentEdition { + index_uid: String, + filter_expr: Option, + context: Option, + function: String, + }, DocumentClear { index_uid: String, }, @@ -150,6 +159,7 @@ impl KindWithContent { pub fn as_kind(&self) -> Kind { match self { KindWithContent::DocumentAdditionOrUpdate { .. } => Kind::DocumentAdditionOrUpdate, + KindWithContent::DocumentEdition { .. } => Kind::DocumentEdition, KindWithContent::DocumentDeletion { .. } => Kind::DocumentDeletion, KindWithContent::DocumentDeletionByFilter { .. } => Kind::DocumentDeletion, KindWithContent::DocumentClear { .. } => Kind::DocumentDeletion, @@ -174,6 +184,7 @@ impl KindWithContent { | TaskCancelation { .. } | TaskDeletion { .. } => vec![], DocumentAdditionOrUpdate { index_uid, .. } + | DocumentEdition { index_uid, .. } | DocumentDeletion { index_uid, .. } | DocumentDeletionByFilter { index_uid, .. } | DocumentClear { index_uid } @@ -202,6 +213,15 @@ impl KindWithContent { indexed_documents: None, }) } + KindWithContent::DocumentEdition { index_uid: _, filter_expr, context, function } => { + Some(Details::DocumentEdition { + deleted_documents: None, + edited_documents: None, + original_filter: filter_expr.as_ref().map(|v| v.to_string()), + context: context.clone(), + function: function.clone(), + }) + } KindWithContent::DocumentDeletion { index_uid: _, documents_ids } => { Some(Details::DocumentDeletion { provided_ids: documents_ids.len(), @@ -250,6 +270,15 @@ impl KindWithContent { indexed_documents: Some(0), }) } + KindWithContent::DocumentEdition { index_uid: _, filter_expr, context, function } => { + Some(Details::DocumentEdition { + deleted_documents: Some(0), + edited_documents: Some(0), + original_filter: filter_expr.as_ref().map(|v| v.to_string()), + context: context.clone(), + function: function.clone(), + }) + } KindWithContent::DocumentDeletion { index_uid: _, documents_ids } => { Some(Details::DocumentDeletion { provided_ids: documents_ids.len(), @@ -301,6 +330,7 @@ impl From<&KindWithContent> for Option
{ indexed_documents: None, }) } + KindWithContent::DocumentEdition { .. } => None, KindWithContent::DocumentDeletion { .. } => None, KindWithContent::DocumentDeletionByFilter { .. } => None, KindWithContent::DocumentClear { .. } => None, @@ -394,6 +424,7 @@ impl std::error::Error for ParseTaskStatusError {} #[serde(rename_all = "camelCase")] pub enum Kind { DocumentAdditionOrUpdate, + DocumentEdition, DocumentDeletion, SettingsUpdate, IndexCreation, @@ -410,6 +441,7 @@ impl Kind { pub fn related_to_one_index(&self) -> bool { match self { Kind::DocumentAdditionOrUpdate + | Kind::DocumentEdition | Kind::DocumentDeletion | Kind::SettingsUpdate | Kind::IndexCreation @@ -427,6 +459,7 @@ impl Display for Kind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Kind::DocumentAdditionOrUpdate => write!(f, "documentAdditionOrUpdate"), + Kind::DocumentEdition => write!(f, "documentEdition"), Kind::DocumentDeletion => write!(f, "documentDeletion"), Kind::SettingsUpdate => write!(f, "settingsUpdate"), Kind::IndexCreation => write!(f, "indexCreation"), @@ -454,6 +487,8 @@ impl FromStr for Kind { Ok(Kind::IndexDeletion) } else if kind.eq_ignore_ascii_case("documentAdditionOrUpdate") { Ok(Kind::DocumentAdditionOrUpdate) + } else if kind.eq_ignore_ascii_case("documentEdition") { + Ok(Kind::DocumentEdition) } else if kind.eq_ignore_ascii_case("documentDeletion") { Ok(Kind::DocumentDeletion) } else if kind.eq_ignore_ascii_case("settingsUpdate") { @@ -495,16 +530,50 @@ impl std::error::Error for ParseTaskKindError {} #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] pub enum Details { - DocumentAdditionOrUpdate { received_documents: u64, indexed_documents: Option }, - SettingsUpdate { settings: Box> }, - IndexInfo { primary_key: Option }, - DocumentDeletion { provided_ids: usize, deleted_documents: Option }, - DocumentDeletionByFilter { original_filter: String, deleted_documents: Option }, - ClearAll { deleted_documents: Option }, - TaskCancelation { matched_tasks: u64, canceled_tasks: Option, original_filter: String }, - TaskDeletion { matched_tasks: u64, deleted_tasks: Option, original_filter: String }, - Dump { dump_uid: Option }, - IndexSwap { swaps: Vec }, + DocumentAdditionOrUpdate { + received_documents: u64, + indexed_documents: Option, + }, + SettingsUpdate { + settings: Box>, + }, + IndexInfo { + primary_key: Option, + }, + DocumentDeletion { + provided_ids: usize, + deleted_documents: Option, + }, + DocumentDeletionByFilter { + original_filter: String, + deleted_documents: Option, + }, + DocumentEdition { + deleted_documents: Option, + edited_documents: Option, + original_filter: Option, + context: Option, + function: String, + }, + ClearAll { + deleted_documents: Option, + }, + TaskCancelation { + matched_tasks: u64, + canceled_tasks: Option, + original_filter: String, + }, + TaskDeletion { + matched_tasks: u64, + deleted_tasks: Option, + original_filter: String, + }, + Dump { + dump_uid: Option, + }, + IndexSwap { + swaps: Vec, + }, } impl Details { @@ -514,6 +583,7 @@ impl Details { Self::DocumentAdditionOrUpdate { indexed_documents, .. } => { *indexed_documents = Some(0) } + Self::DocumentEdition { edited_documents, .. } => *edited_documents = Some(0), Self::DocumentDeletion { deleted_documents, .. } => *deleted_documents = Some(0), Self::DocumentDeletionByFilter { deleted_documents, .. } => { *deleted_documents = Some(0) diff --git a/meilisearch/src/analytics/mock_analytics.rs b/meilisearch/src/analytics/mock_analytics.rs index 8f2fe0333..e212775a2 100644 --- a/meilisearch/src/analytics/mock_analytics.rs +++ b/meilisearch/src/analytics/mock_analytics.rs @@ -6,7 +6,7 @@ use meilisearch_types::InstanceUid; use serde_json::Value; use super::{find_user_id, Analytics, DocumentDeletionKind, DocumentFetchKind}; -use crate::routes::indexes::documents::UpdateDocumentsQuery; +use crate::routes::indexes::documents::{DocumentEditionByFunction, UpdateDocumentsQuery}; use crate::Opt; pub struct MockAnalytics { @@ -97,6 +97,13 @@ impl Analytics for MockAnalytics { _request: &HttpRequest, ) { } + fn update_documents_by_function( + &self, + _documents_query: &DocumentEditionByFunction, + _index_creation: bool, + _request: &HttpRequest, + ) { + } fn get_fetch_documents(&self, _documents_query: &DocumentFetchKind, _request: &HttpRequest) {} fn post_fetch_documents(&self, _documents_query: &DocumentFetchKind, _request: &HttpRequest) {} } diff --git a/meilisearch/src/analytics/mod.rs b/meilisearch/src/analytics/mod.rs index 6863dc57b..9140e3492 100644 --- a/meilisearch/src/analytics/mod.rs +++ b/meilisearch/src/analytics/mod.rs @@ -13,7 +13,7 @@ use once_cell::sync::Lazy; use platform_dirs::AppDirs; use serde_json::Value; -use crate::routes::indexes::documents::UpdateDocumentsQuery; +use crate::routes::indexes::documents::{DocumentEditionByFunction, UpdateDocumentsQuery}; // if the analytics feature is disabled // the `SegmentAnalytics` point to the mock instead of the real analytics @@ -119,11 +119,19 @@ pub trait Analytics: Sync + Send { // this method should be called to aggregate a add documents request fn delete_documents(&self, kind: DocumentDeletionKind, request: &HttpRequest); - // this method should be called to batch a update documents request + // this method should be called to batch an update documents request fn update_documents( &self, documents_query: &UpdateDocumentsQuery, index_creation: bool, request: &HttpRequest, ); + + // this method should be called to batch an update documents by function request + fn update_documents_by_function( + &self, + documents_query: &DocumentEditionByFunction, + index_creation: bool, + request: &HttpRequest, + ); } diff --git a/meilisearch/src/analytics/segment_analytics.rs b/meilisearch/src/analytics/segment_analytics.rs index 67f437082..405baa057 100644 --- a/meilisearch/src/analytics/segment_analytics.rs +++ b/meilisearch/src/analytics/segment_analytics.rs @@ -30,7 +30,7 @@ use crate::analytics::Analytics; use crate::option::{ default_http_addr, IndexerOpts, LogMode, MaxMemory, MaxThreads, ScheduleSnapshot, }; -use crate::routes::indexes::documents::UpdateDocumentsQuery; +use crate::routes::indexes::documents::{DocumentEditionByFunction, UpdateDocumentsQuery}; use crate::routes::indexes::facet_search::FacetSearchQuery; use crate::routes::{create_all_stats, Stats}; use crate::search::{ @@ -80,6 +80,7 @@ pub enum AnalyticsMsg { AggregateAddDocuments(DocumentsAggregator), AggregateDeleteDocuments(DocumentsDeletionAggregator), AggregateUpdateDocuments(DocumentsAggregator), + AggregateEditDocumentsByFunction(EditDocumentsByFunctionAggregator), AggregateGetFetchDocuments(DocumentsFetchAggregator), AggregatePostFetchDocuments(DocumentsFetchAggregator), } @@ -149,6 +150,7 @@ impl SegmentAnalytics { add_documents_aggregator: DocumentsAggregator::default(), delete_documents_aggregator: DocumentsDeletionAggregator::default(), update_documents_aggregator: DocumentsAggregator::default(), + edit_documents_by_function_aggregator: EditDocumentsByFunctionAggregator::default(), get_fetch_documents_aggregator: DocumentsFetchAggregator::default(), post_fetch_documents_aggregator: DocumentsFetchAggregator::default(), get_similar_aggregator: SimilarAggregator::default(), @@ -229,6 +231,17 @@ impl super::Analytics for SegmentAnalytics { let _ = self.sender.try_send(AnalyticsMsg::AggregateUpdateDocuments(aggregate)); } + fn update_documents_by_function( + &self, + documents_query: &DocumentEditionByFunction, + index_creation: bool, + request: &HttpRequest, + ) { + let aggregate = + EditDocumentsByFunctionAggregator::from_query(documents_query, index_creation, request); + let _ = self.sender.try_send(AnalyticsMsg::AggregateEditDocumentsByFunction(aggregate)); + } + fn get_fetch_documents(&self, documents_query: &DocumentFetchKind, request: &HttpRequest) { let aggregate = DocumentsFetchAggregator::from_query(documents_query, request); let _ = self.sender.try_send(AnalyticsMsg::AggregateGetFetchDocuments(aggregate)); @@ -389,6 +402,7 @@ pub struct Segment { add_documents_aggregator: DocumentsAggregator, delete_documents_aggregator: DocumentsDeletionAggregator, update_documents_aggregator: DocumentsAggregator, + edit_documents_by_function_aggregator: EditDocumentsByFunctionAggregator, get_fetch_documents_aggregator: DocumentsFetchAggregator, post_fetch_documents_aggregator: DocumentsFetchAggregator, get_similar_aggregator: SimilarAggregator, @@ -453,6 +467,7 @@ impl Segment { Some(AnalyticsMsg::AggregateAddDocuments(agreg)) => self.add_documents_aggregator.aggregate(agreg), Some(AnalyticsMsg::AggregateDeleteDocuments(agreg)) => self.delete_documents_aggregator.aggregate(agreg), Some(AnalyticsMsg::AggregateUpdateDocuments(agreg)) => self.update_documents_aggregator.aggregate(agreg), + Some(AnalyticsMsg::AggregateEditDocumentsByFunction(agreg)) => self.edit_documents_by_function_aggregator.aggregate(agreg), Some(AnalyticsMsg::AggregateGetFetchDocuments(agreg)) => self.get_fetch_documents_aggregator.aggregate(agreg), Some(AnalyticsMsg::AggregatePostFetchDocuments(agreg)) => self.post_fetch_documents_aggregator.aggregate(agreg), Some(AnalyticsMsg::AggregateGetSimilar(agreg)) => self.get_similar_aggregator.aggregate(agreg), @@ -508,6 +523,7 @@ impl Segment { add_documents_aggregator, delete_documents_aggregator, update_documents_aggregator, + edit_documents_by_function_aggregator, get_fetch_documents_aggregator, post_fetch_documents_aggregator, get_similar_aggregator, @@ -549,6 +565,11 @@ impl Segment { { let _ = self.batcher.push(update_documents).await; } + if let Some(edit_documents_by_function) = take(edit_documents_by_function_aggregator) + .into_event(user, "Documents Edited By Function") + { + let _ = self.batcher.push(edit_documents_by_function).await; + } if let Some(get_fetch_documents) = take(get_fetch_documents_aggregator).into_event(user, "Documents Fetched GET") { @@ -1465,6 +1486,75 @@ impl DocumentsAggregator { } } +#[derive(Default)] +pub struct EditDocumentsByFunctionAggregator { + timestamp: Option, + + // Set to true if at least one request was filtered + filtered: bool, + // Set to true if at least one request contained a context + with_context: bool, + + // context + user_agents: HashSet, + + index_creation: bool, +} + +impl EditDocumentsByFunctionAggregator { + pub fn from_query( + documents_query: &DocumentEditionByFunction, + index_creation: bool, + request: &HttpRequest, + ) -> Self { + let DocumentEditionByFunction { filter, context, function: _ } = documents_query; + + Self { + timestamp: Some(OffsetDateTime::now_utc()), + user_agents: extract_user_agents(request).into_iter().collect(), + filtered: filter.is_some(), + with_context: context.is_some(), + index_creation, + } + } + + /// Aggregate one [DocumentsAggregator] into another. + pub fn aggregate(&mut self, other: Self) { + let Self { timestamp, user_agents, index_creation, filtered, with_context } = other; + + if self.timestamp.is_none() { + self.timestamp = timestamp; + } + + // we can't create a union because there is no `into_union` method + for user_agent in user_agents { + self.user_agents.insert(user_agent); + } + self.index_creation |= index_creation; + self.filtered |= filtered; + self.with_context |= with_context; + } + + pub fn into_event(self, user: &User, event_name: &str) -> Option { + let Self { timestamp, user_agents, index_creation, filtered, with_context } = self; + + let properties = json!({ + "user-agent": user_agents, + "filtered": filtered, + "with_context": with_context, + "index_creation": index_creation, + }); + + Some(Track { + timestamp, + user: user.clone(), + event: event_name.to_string(), + properties, + ..Default::default() + }) + } +} + #[derive(Default, Serialize)] pub struct DocumentsDeletionAggregator { #[serde(skip)] diff --git a/meilisearch/src/routes/features.rs b/meilisearch/src/routes/features.rs index 0e02309fa..14aece10f 100644 --- a/meilisearch/src/routes/features.rs +++ b/meilisearch/src/routes/features.rs @@ -47,6 +47,8 @@ pub struct RuntimeTogglableFeatures { pub metrics: Option, #[deserr(default)] pub logs_route: Option, + #[deserr(default)] + pub edit_documents_by_function: Option, } async fn patch_features( @@ -66,13 +68,21 @@ async fn patch_features( vector_store: new_features.0.vector_store.unwrap_or(old_features.vector_store), metrics: new_features.0.metrics.unwrap_or(old_features.metrics), logs_route: new_features.0.logs_route.unwrap_or(old_features.logs_route), + edit_documents_by_function: new_features + .0 + .edit_documents_by_function + .unwrap_or(old_features.edit_documents_by_function), }; // explicitly destructure for analytics rather than using the `Serialize` implementation, because // the it renames to camelCase, which we don't want for analytics. // **Do not** ignore fields with `..` or `_` here, because we want to add them in the future. - let meilisearch_types::features::RuntimeTogglableFeatures { vector_store, metrics, logs_route } = - new_features; + let meilisearch_types::features::RuntimeTogglableFeatures { + vector_store, + metrics, + logs_route, + edit_documents_by_function, + } = new_features; analytics.publish( "Experimental features Updated".to_string(), @@ -80,6 +90,7 @@ async fn patch_features( "vector_store": vector_store, "metrics": metrics, "logs_route": logs_route, + "edit_documents_by_function": edit_documents_by_function, }), Some(&req), ); diff --git a/meilisearch/src/routes/indexes/documents.rs b/meilisearch/src/routes/indexes/documents.rs index 7c6cbc85d..20c0aed07 100644 --- a/meilisearch/src/routes/indexes/documents.rs +++ b/meilisearch/src/routes/indexes/documents.rs @@ -82,6 +82,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) { web::resource("/delete-batch").route(web::post().to(SeqHandler(delete_documents_batch))), ) .service(web::resource("/delete").route(web::post().to(SeqHandler(delete_documents_by_filter)))) + .service(web::resource("/edit").route(web::post().to(SeqHandler(edit_documents_by_function)))) .service(web::resource("/fetch").route(web::post().to(SeqHandler(documents_by_query_post)))) .service( web::resource("/{document_id}") @@ -574,6 +575,82 @@ pub async fn delete_documents_by_filter( Ok(HttpResponse::Accepted().json(task)) } +#[derive(Debug, Deserr)] +#[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)] +pub struct DocumentEditionByFunction { + #[deserr(default, error = DeserrJsonError)] + pub filter: Option, + #[deserr(default, error = DeserrJsonError)] + pub context: Option, + #[deserr(error = DeserrJsonError, missing_field_error = DeserrJsonError::missing_document_edition_function)] + pub function: String, +} + +pub async fn edit_documents_by_function( + index_scheduler: GuardedData, Data>, + index_uid: web::Path, + params: AwebJson, + req: HttpRequest, + opt: web::Data, + analytics: web::Data, +) -> Result { + debug!(parameters = ?params, "Edit documents by function"); + + index_scheduler + .features() + .check_edit_documents_by_function("Using the documents edit route")?; + + let index_uid = IndexUid::try_from(index_uid.into_inner())?; + let index_uid = index_uid.into_inner(); + let params = params.into_inner(); + + analytics.update_documents_by_function( + ¶ms, + index_scheduler.index(&index_uid).is_err(), + &req, + ); + + let DocumentEditionByFunction { filter, context, function } = params; + let engine = milli::rhai::Engine::new(); + if let Err(e) = engine.compile(&function) { + return Err(ResponseError::from_msg(e.to_string(), Code::BadRequest)); + } + + if let Some(ref filter) = filter { + // we ensure the filter is well formed before enqueuing it + || -> Result<_, ResponseError> { + Ok(crate::search::parse_filter(filter)?.ok_or(MeilisearchHttpError::EmptyFilter)?) + }() + // and whatever was the error, the error code should always be an InvalidDocumentFilter + .map_err(|err| ResponseError::from_msg(err.message, Code::InvalidDocumentFilter))?; + } + let task = KindWithContent::DocumentEdition { + index_uid, + filter_expr: filter, + context: match context { + Some(Value::Object(m)) => Some(m), + None => None, + _ => { + return Err(ResponseError::from_msg( + "The context must be an object".to_string(), + Code::InvalidDocumentEditionContext, + )) + } + }, + function, + }; + + let uid = get_task_id(&req, &opt)?; + let dry_run = is_dry_run(&req, &opt)?; + let task: SummarizedTaskView = + tokio::task::spawn_blocking(move || index_scheduler.register(task, uid, dry_run)) + .await?? + .into(); + + debug!(returns = ?task, "Edit documents by function"); + Ok(HttpResponse::Accepted().json(task)) +} + pub async fn clear_all_documents( index_scheduler: GuardedData, Data>, index_uid: web::Path, diff --git a/meilisearch/src/routes/tasks.rs b/meilisearch/src/routes/tasks.rs index a4cf68d57..3dc6520af 100644 --- a/meilisearch/src/routes/tasks.rs +++ b/meilisearch/src/routes/tasks.rs @@ -591,7 +591,7 @@ mod tests { let err = deserr_query_params::(params).unwrap_err(); snapshot!(meili_snap::json_string!(err), @r###" { - "message": "Invalid value in parameter `types`: `createIndex` is not a valid task type. Available types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`.", + "message": "Invalid value in parameter `types`: `createIndex` is not a valid task type. Available types are `documentAdditionOrUpdate`, `documentEdition`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`.", "code": "invalid_task_types", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_task_types" diff --git a/meilisearch/tests/documents/get_documents.rs b/meilisearch/tests/documents/get_documents.rs index 68065b019..f32adf48d 100644 --- a/meilisearch/tests/documents/get_documents.rs +++ b/meilisearch/tests/documents/get_documents.rs @@ -535,7 +535,8 @@ async fn get_document_with_vectors() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); diff --git a/meilisearch/tests/dumps/mod.rs b/meilisearch/tests/dumps/mod.rs index fa402cb41..8c53e661b 100644 --- a/meilisearch/tests/dumps/mod.rs +++ b/meilisearch/tests/dumps/mod.rs @@ -1859,7 +1859,8 @@ async fn import_dump_v6_containing_experimental_features() { { "vectorStore": false, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -1952,7 +1953,8 @@ async fn generate_and_import_dump_containing_vectors() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); let index = server.index("pets"); @@ -2022,7 +2024,8 @@ async fn generate_and_import_dump_containing_vectors() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); diff --git a/meilisearch/tests/features/mod.rs b/meilisearch/tests/features/mod.rs index 9548567ff..b90e455c5 100644 --- a/meilisearch/tests/features/mod.rs +++ b/meilisearch/tests/features/mod.rs @@ -20,7 +20,8 @@ async fn experimental_features() { { "vectorStore": false, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -31,7 +32,8 @@ async fn experimental_features() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -42,7 +44,8 @@ async fn experimental_features() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -54,7 +57,8 @@ async fn experimental_features() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -66,7 +70,8 @@ async fn experimental_features() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); } @@ -85,7 +90,8 @@ async fn experimental_feature_metrics() { { "vectorStore": false, "metrics": true, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -140,7 +146,7 @@ async fn errors() { meili_snap::snapshot!(code, @"400 Bad Request"); meili_snap::snapshot!(meili_snap::json_string!(response), @r###" { - "message": "Unknown field `NotAFeature`: expected one of `vectorStore`, `metrics`, `logsRoute`", + "message": "Unknown field `NotAFeature`: expected one of `vectorStore`, `metrics`, `logsRoute`, `editDocumentsByFunction`", "code": "bad_request", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#bad_request" diff --git a/meilisearch/tests/search/hybrid.rs b/meilisearch/tests/search/hybrid.rs index 02768bf60..1a4e8baab 100644 --- a/meilisearch/tests/search/hybrid.rs +++ b/meilisearch/tests/search/hybrid.rs @@ -18,7 +18,8 @@ async fn index_with_documents_user_provided<'a>( { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -46,7 +47,8 @@ async fn index_with_documents_hf<'a>(server: &'a Server, documents: &Value) -> I { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); diff --git a/meilisearch/tests/settings/get_settings.rs b/meilisearch/tests/settings/get_settings.rs index 379e0a917..d1fe71140 100644 --- a/meilisearch/tests/settings/get_settings.rs +++ b/meilisearch/tests/settings/get_settings.rs @@ -98,7 +98,8 @@ async fn secrets_are_hidden_in_settings() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); diff --git a/meilisearch/tests/similar/mod.rs b/meilisearch/tests/similar/mod.rs index 60a0203ed..edfecf83c 100644 --- a/meilisearch/tests/similar/mod.rs +++ b/meilisearch/tests/similar/mod.rs @@ -55,7 +55,8 @@ async fn basic() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -244,7 +245,8 @@ async fn ranking_score_threshold() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -523,7 +525,8 @@ async fn filter() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -650,7 +653,8 @@ async fn limit_and_offset() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); diff --git a/meilisearch/tests/tasks/errors.rs b/meilisearch/tests/tasks/errors.rs index 830c4c8e7..2c85acf0e 100644 --- a/meilisearch/tests/tasks/errors.rs +++ b/meilisearch/tests/tasks/errors.rs @@ -97,7 +97,7 @@ async fn task_bad_types() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Invalid value in parameter `types`: `doggo` is not a valid task type. Available types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`.", + "message": "Invalid value in parameter `types`: `doggo` is not a valid task type. Available types are `documentAdditionOrUpdate`, `documentEdition`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`.", "code": "invalid_task_types", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_task_types" @@ -108,7 +108,7 @@ async fn task_bad_types() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Invalid value in parameter `types`: `doggo` is not a valid task type. Available types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`.", + "message": "Invalid value in parameter `types`: `doggo` is not a valid task type. Available types are `documentAdditionOrUpdate`, `documentEdition`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`.", "code": "invalid_task_types", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_task_types" @@ -119,7 +119,7 @@ async fn task_bad_types() { snapshot!(code, @"400 Bad Request"); snapshot!(json_string!(response), @r###" { - "message": "Invalid value in parameter `types`: `doggo` is not a valid task type. Available types are `documentAdditionOrUpdate`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`.", + "message": "Invalid value in parameter `types`: `doggo` is not a valid task type. Available types are `documentAdditionOrUpdate`, `documentEdition`, `documentDeletion`, `settingsUpdate`, `indexCreation`, `indexDeletion`, `indexUpdate`, `indexSwap`, `taskCancelation`, `taskDeletion`, `dumpCreation`, `snapshotCreation`.", "code": "invalid_task_types", "type": "invalid_request", "link": "https://docs.meilisearch.com/errors#invalid_task_types" diff --git a/meilisearch/tests/vector/mod.rs b/meilisearch/tests/vector/mod.rs index 0343ab785..21b643c20 100644 --- a/meilisearch/tests/vector/mod.rs +++ b/meilisearch/tests/vector/mod.rs @@ -16,7 +16,8 @@ async fn add_remove_user_provided() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -159,7 +160,8 @@ async fn generate_default_user_provided_documents(server: &Server) -> Index { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); @@ -516,7 +518,8 @@ async fn add_remove_one_vector_4588() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); diff --git a/meilisearch/tests/vector/settings.rs b/meilisearch/tests/vector/settings.rs index e53ceb383..177e070cd 100644 --- a/meilisearch/tests/vector/settings.rs +++ b/meilisearch/tests/vector/settings.rs @@ -14,7 +14,8 @@ async fn update_embedder() { { "vectorStore": true, "metrics": false, - "logsRoute": false + "logsRoute": false, + "editDocumentsByFunction": false } "###); diff --git a/milli/Cargo.toml b/milli/Cargo.toml index 64f0116d3..a71d013ff 100644 --- a/milli/Cargo.toml +++ b/milli/Cargo.toml @@ -78,11 +78,13 @@ hf-hub = { git = "https://github.com/dureuill/hf-hub.git", branch = "rust_tls", ] } tiktoken-rs = "0.5.9" liquid = "0.26.6" +rhai = { version = "1.19.0", features = ["serde", "no_module", "no_custom_syntax", "no_time", "sync"] } arroy = "0.4.0" rand = "0.8.5" tracing = "0.1.40" ureq = { version = "2.10.0", features = ["json"] } url = "2.5.2" +rayon-par-bridge = "0.1.0" [dev-dependencies] mimalloc = { version = "0.1.43", default-features = false } diff --git a/milli/src/error.rs b/milli/src/error.rs index 8e03fde4e..0effb7be7 100644 --- a/milli/src/error.rs +++ b/milli/src/error.rs @@ -5,6 +5,7 @@ use std::{io, str}; use heed::{Error as HeedError, MdbError}; use rayon::ThreadPoolBuildError; +use rhai::EvalAltResult; use serde_json::Value; use thiserror::Error; @@ -259,6 +260,14 @@ only composed of alphanumeric characters (a-z A-Z 0-9), hyphens (-) and undersco InvalidSettingsDimensions { embedder_name: String }, #[error("`.embedders.{embedder_name}.url`: could not parse `{url}`: {inner_error}")] InvalidUrl { embedder_name: String, inner_error: url::ParseError, url: String }, + #[error("Document editions cannot modify a document's primary key")] + DocumentEditionCannotModifyPrimaryKey, + #[error("Document editions must keep documents as objects")] + DocumentEditionDocumentMustBeObject, + #[error("Document edition runtime error encountered while running the function: {0}")] + DocumentEditionRuntimeError(Box), + #[error("Document edition runtime error encountered while compiling the function: {0}")] + DocumentEditionCompilationError(rhai::ParseError), } impl From for Error { diff --git a/milli/src/lib.rs b/milli/src/lib.rs index 581ffc73c..fcb0da19c 100644 --- a/milli/src/lib.rs +++ b/milli/src/lib.rs @@ -45,7 +45,7 @@ pub use search::new::{ }; use serde_json::Value; pub use thread_pool_no_abort::{PanicCatched, ThreadPoolNoAbort, ThreadPoolNoAbortBuilder}; -pub use {charabia as tokenizer, heed}; +pub use {charabia as tokenizer, heed, rhai}; pub use self::asc_desc::{AscDesc, AscDescError, Member, SortError}; pub use self::criterion::{default_criteria, Criterion, CriterionError}; diff --git a/milli/src/update/index_documents/mod.rs b/milli/src/update/index_documents/mod.rs index 727c763aa..271d4037c 100644 --- a/milli/src/update/index_documents/mod.rs +++ b/milli/src/update/index_documents/mod.rs @@ -1,6 +1,7 @@ mod enrich; mod extract; mod helpers; +mod parallel; mod transform; mod typed_chunk; @@ -16,6 +17,8 @@ use grenad::{Merger, MergerBuilder}; use heed::types::Str; use heed::Database; use rand::SeedableRng; +use rayon::iter::{ParallelBridge, ParallelIterator}; +use rhai::{Dynamic, Engine, OptimizationLevel, Scope}; use roaring::RoaringBitmap; use serde::{Deserialize, Serialize}; use slice_group_by::GroupBy; @@ -32,15 +35,16 @@ pub use self::helpers::{ }; use self::helpers::{grenad_obkv_into_chunks, GrenadParameters}; pub use self::transform::{Transform, TransformOutput}; -use crate::documents::{obkv_to_object, DocumentsBatchReader}; +use crate::documents::{obkv_to_object, DocumentsBatchBuilder, DocumentsBatchReader}; use crate::error::{Error, InternalError, UserError}; use crate::thread_pool_no_abort::ThreadPoolNoAbortBuilder; pub use crate::update::index_documents::helpers::CursorClonableMmap; +use crate::update::index_documents::parallel::ImmutableObkvs; use crate::update::{ IndexerConfig, UpdateIndexingStep, WordPrefixDocids, WordPrefixIntegerDocids, WordsPrefixesFst, }; use crate::vector::EmbeddingConfigs; -use crate::{CboRoaringBitmapCodec, Index, Result}; +use crate::{CboRoaringBitmapCodec, Index, Object, Result}; static MERGED_DATABASE_COUNT: usize = 7; static PREFIX_DATABASE_COUNT: usize = 4; @@ -172,6 +176,141 @@ where Ok((self, Ok(indexed_documents))) } + #[tracing::instrument(level = "trace", skip_all, target = "indexing::documents")] + pub fn edit_documents( + self, + documents: &RoaringBitmap, + context: Option, + code: &str, + ) -> Result<(Self, StdResult<(u64, u64), UserError>)> { + // Early return when there is no document to edit + if documents.is_empty() { + return Ok((self, Ok((0, 0)))); + } + + fn rhaimap_to_object(map: rhai::Map) -> Object { + let mut output = Object::new(); + for (key, value) in map { + let value = serde_json::to_value(&value).unwrap(); + output.insert(key.into(), value); + } + output + } + + // Setup the security and limits of the Engine + let mut engine = Engine::new(); + engine.set_optimization_level(OptimizationLevel::Full); + engine.set_max_call_levels(1000); + // It is an arbitrary value. We need to let users define this in the settings. + engine.set_max_operations(1_000_000); + engine.set_max_variables(1000); + engine.set_max_functions(30); + engine.set_max_expr_depths(100, 1000); + engine.set_max_string_size(1024 * 1024 * 1024); // 1 GiB + engine.set_max_array_size(10_000); + engine.set_max_map_size(10_000); + + let ast = engine.compile(code).map_err(UserError::DocumentEditionCompilationError)?; + let fields_ids_map = self.index.fields_ids_map(self.wtxn)?; + let primary_key = self.index.primary_key(self.wtxn)?.unwrap(); + let mut documents_batch_builder = tempfile::tempfile().map(DocumentsBatchBuilder::new)?; + let mut documents_to_remove = RoaringBitmap::new(); + + let context: Option = match context { + Some(context) => { + Some(serde_json::from_value(context.into()).map_err(InternalError::SerdeJson)?) + } + None => None, + }; + + enum DocumentEdition { + Deleted(crate::DocumentId), + Edited(Object), + Nothing, + } + + let immutable_obkvs = ImmutableObkvs::new( + self.wtxn, + self.index.documents, + fields_ids_map.clone(), + documents.clone(), + )?; + + let processing = documents.into_iter().par_bridge().map(|docid| { + // safety: Both documents *must* exists in the database as + // their IDs comes from the list of documents ids. + let rhai_document = immutable_obkvs.rhai_map(docid)?.unwrap(); + let json_document = immutable_obkvs.json_map(docid)?.unwrap(); + let document_id = &json_document[primary_key]; + + let mut scope = Scope::new(); + if let Some(context) = context.as_ref().cloned() { + scope.push_constant_dynamic("context", context.clone()); + } + scope.push("doc", rhai_document); + // That's were the magic happens. We run the user script + // which edits "doc" scope variable reprensenting the document + // and ignore the output and even the type of it, i.e., Dynamic. + let _ = engine + .eval_ast_with_scope::(&mut scope, &ast) + .map_err(UserError::DocumentEditionRuntimeError)?; + + match scope.remove::("doc") { + // If the "doc" variable has set to (), we effectively delete the document. + Some(doc) if doc.is_unit() => Ok(DocumentEdition::Deleted(docid)), + None => unreachable!("missing doc variable from the Rhai scope"), + Some(document) => match document.try_cast() { + Some(document) => { + let new_document = rhaimap_to_object(document); + // Note: This condition is not perfect. Sometimes it detect changes + // like with floating points numbers and consider updating + // the document even if nothing actually changed. + if json_document != new_document { + if Some(document_id) != new_document.get(primary_key) { + Err(Error::UserError( + UserError::DocumentEditionCannotModifyPrimaryKey, + )) + } else { + Ok(DocumentEdition::Edited(new_document)) + } + } else { + Ok(DocumentEdition::Nothing) + } + } + None => Err(Error::UserError(UserError::DocumentEditionDocumentMustBeObject)), + }, + } + }); + + rayon_par_bridge::par_bridge(100, processing, |iterator| { + for result in iterator { + if (self.should_abort)() { + return Err(Error::InternalError(InternalError::AbortedIndexation)); + } + + match result? { + DocumentEdition::Deleted(docid) => { + documents_to_remove.push(docid); + } + DocumentEdition::Edited(new_document) => { + documents_batch_builder.append_json_object(&new_document)?; + } + DocumentEdition::Nothing => (), + } + } + + Ok(()) + })?; + + let file = documents_batch_builder.into_inner()?; + let reader = DocumentsBatchReader::from_reader(file)?; + + let (this, removed) = self.remove_documents_from_db_no_batch(&documents_to_remove)?; + let (this, result) = this.add_documents(reader)?; + + Ok((this, result.map(|added| (removed, added)))) + } + pub fn with_embedders(mut self, embedders: EmbeddingConfigs) -> Self { self.embedders = embedders; self diff --git a/milli/src/update/index_documents/parallel.rs b/milli/src/update/index_documents/parallel.rs new file mode 100644 index 000000000..52e72a378 --- /dev/null +++ b/milli/src/update/index_documents/parallel.rs @@ -0,0 +1,86 @@ +use heed::types::Bytes; +use heed::{Database, RoTxn}; +use obkv::KvReaderU16; +use roaring::RoaringBitmap; + +use crate::{all_obkv_to_json, DocumentId, FieldsIdsMap, Object, ObkvCodec, Result, BEU32}; + +pub struct ImmutableObkvs<'t> { + ids: RoaringBitmap, + fields_ids_map: FieldsIdsMap, + slices: Vec<&'t [u8]>, +} + +impl<'t> ImmutableObkvs<'t> { + /// Creates the structure by fetching all the OBKVs + /// and keeping the transaction making the pointers valid. + pub fn new( + rtxn: &'t RoTxn, + documents_database: Database, + fields_ids_map: FieldsIdsMap, + subset: RoaringBitmap, + ) -> heed::Result { + let mut slices = Vec::new(); + let documents_database = documents_database.remap_data_type::(); + for docid in &subset { + let slice = documents_database.get(rtxn, &docid)?.unwrap(); + slices.push(slice); + } + + Ok(ImmutableObkvs { ids: subset, fields_ids_map, slices }) + } + + /// Returns the OBKVs identified by the given ID. + pub fn obkv(&self, docid: DocumentId) -> heed::Result>> { + match self + .ids + .rank(docid) + .checked_sub(1) + .and_then(|offset| self.slices.get(offset as usize)) + { + Some(bytes) => Ok(Some(KvReaderU16::new(bytes))), + None => Ok(None), + } + } + + /// Returns the owned rhai::Map identified by the given ID. + pub fn rhai_map(&self, docid: DocumentId) -> Result> { + let obkv = match self.obkv(docid) { + Ok(Some(obkv)) => obkv, + Ok(None) => return Ok(None), + Err(e) => return Err(e.into()), + }; + + let all_keys = obkv.iter().map(|(k, _v)| k).collect::>(); + let map: Result = all_keys + .iter() + .copied() + .flat_map(|id| obkv.get(id).map(|value| (id, value))) + .map(|(id, value)| { + let name = self.fields_ids_map.name(id).ok_or( + crate::error::FieldIdMapMissingEntry::FieldId { + field_id: id, + process: "all_obkv_to_rhaimap", + }, + )?; + let value = serde_json::from_slice(value) + .map_err(crate::error::InternalError::SerdeJson)?; + Ok((name.into(), value)) + }) + .collect(); + + map.map(Some) + } + + pub fn json_map(&self, docid: DocumentId) -> Result> { + let obkv = match self.obkv(docid) { + Ok(Some(obkv)) => obkv, + Ok(None) => return Ok(None), + Err(e) => return Err(e.into()), + }; + + all_obkv_to_json(obkv, &self.fields_ids_map).map(Some) + } +} + +unsafe impl Sync for ImmutableObkvs<'_> {}