diff --git a/Cargo.lock b/Cargo.lock index 0eacf6bd1..35b34d3d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,9 +21,9 @@ dependencies = [ [[package]] name = "actix-cors" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "684a6ce1562a5fcca49bc9302896c63547eea78a1e405e837e7416affd8b6eb9" +checksum = "b340e9cfa5b08690aae90fb61beb44e9b06f44fe3d0f93781aaa58cfba86245e" dependencies = [ "actix-utils", "actix-web", @@ -59,7 +59,7 @@ dependencies = [ "http", "httparse", "httpdate", - "itoa 1.0.4", + "itoa 1.0.5", "language-tags", "local-channel", "mime", @@ -77,8 +77,8 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6" dependencies = [ - "quote 1.0.21", - "syn 1.0.103", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -188,7 +188,7 @@ dependencies = [ "futures-core", "futures-util", "http", - "itoa 1.0.4", + "itoa 1.0.5", "language-tags", "log", "mime", @@ -211,9 +211,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa9362663c8643d67b2d5eafba49e4cb2c8a053a29ed00a0bea121f17c76b13" dependencies = [ "actix-router", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -229,9 +229,9 @@ dependencies = [ [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -267,9 +267,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] @@ -291,9 +291,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.66" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6" +checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" dependencies = [ "backtrace", ] @@ -324,27 +324,27 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "async-trait" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c" +checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "atomic-polyfill" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c041a8d9751a520ee19656232a18971f18946a7900f1520ee4400002244dd89" +checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" dependencies = [ "critical-section", ] @@ -355,7 +355,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi", ] @@ -368,9 +368,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.66" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab84319d616cfb654d03394f38ab7e6f0919e181b1b57e1fd15e7fb4077d9a7" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", @@ -381,21 +381,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "bare-metal" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5deb64efa5bd81e31fcd1938615a6d98c82eafcbcd787162b6f63b91d6bac5b3" -dependencies = [ - "rustc_version 0.2.3", -] - -[[package]] -name = "bare-metal" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fe8f5a8a398345e52358e18ff07cc17a568fbca5c6f73873d3a62056309603" - [[package]] name = "base64" version = "0.13.1" @@ -447,18 +432,6 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" -[[package]] -name = "bit_field" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb6dd1c2376d2e096796e234a70e17e94cc2d5d54ff8ce42b28cef1d0d359a4" - -[[package]] -name = "bitfield" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719" - [[package]] name = "bitflags" version = "1.3.2" @@ -509,9 +482,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca0852af221f458706eb0725c03e4ed6c46af9ac98e6a689d5e634215d594dd" +checksum = "b45ea9b00a7b3f2988e9a65ad3917e62123c38dba709b666506207be96d1790b" dependencies = [ "memchr", "once_cell", @@ -533,9 +506,9 @@ checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba" [[package]] name = "byte-unit" -version = "4.0.14" +version = "4.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ebf10dda65f19ff0f42ea15572a359ed60d7fc74fdc984d90310937be0014b" +checksum = "3348673602e04848647fffaa8e9a861e7b5d5cae6570727b41bde0f722514484" dependencies = [ "serde", "utf8-width", @@ -549,22 +522,22 @@ checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" [[package]] name = "bytemuck" -version = "1.12.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f5715e491b5a1598fc2bef5a606847b5dc1d48ea625bd3c02c00de8285591da" +checksum = "aaa3a8d9a1ca92e282c96a32d6511b695d7d994d1d102ba85d279f9b2756947f" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9e1f5fa78f69496407a27ae9ed989e3c3b072310286f5ef385525e4cbc24a9" +checksum = "5fe233b960f12f8007e3db2d136e3cb1c291bfd7396e384ee76025fc1a3932b4" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -575,24 +548,24 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db" +checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "bytestring" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b6a75fd3048808ef06af5cd79712be8111960adaf89d90250974b38fc3928a" +checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1" dependencies = [ "bytes", ] [[package]] name = "bzip2" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0" +checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8" dependencies = [ "bzip2-sys", "libc", @@ -611,9 +584,9 @@ dependencies = [ [[package]] name = "cargo_toml" -version = "0.13.0" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa0e3586af56b3bfa51fca452bd56e8dbbbd5d8d81cbf0b7e4e35b695b537eb8" +checksum = "497049e9477329f8f6a559972ee42e117487d01d1e8c2cc9f836ea6fa23a9e1a" dependencies = [ "serde", "toml", @@ -621,9 +594,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.73" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" dependencies = [ "jobserver", ] @@ -702,14 +675,14 @@ dependencies = [ [[package]] name = "clap" -version = "4.0.18" +version = "4.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335867764ed2de42325fafe6d18b8af74ba97ee0c590fa016f157535b42ab04b" +checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39" dependencies = [ - "atty", "bitflags", - "clap_derive 4.0.18", + "clap_derive 4.0.21", "clap_lex 0.3.0", + "is-terminal", "once_cell", "strsim", "termcolor", @@ -723,22 +696,22 @@ checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "clap_derive" -version = "4.0.18" +version = "4.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16a1b0f6422af32d5da0c58e2703320f379216ee70198241c84173a8c5ac28f3" +checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -765,22 +738,21 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1df715824eb382e34b7afb7463b0247bf41538aeba731fba05241ecdb5dc3747" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "console" -version = "0.15.2" +version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" +checksum = "c9b6515d269224923b26b5febea2ed42b2d5f2ce37284a4dd670fedd6cb8347a" dependencies = [ "encode_unicode", "lazy_static", "libc", - "terminal_size", - "winapi", + "windows-sys", ] [[package]] @@ -795,6 +767,12 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "convert_case" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb4a24b1aaf0fd0ce8b45161144d6f42cd91677fd5940fd431183eb023b3a2b8" + [[package]] name = "convert_case" version = "0.6.0" @@ -806,9 +784,9 @@ dependencies = [ [[package]] name = "cookie" -version = "0.16.1" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "344adc371239ef32293cb1c4fe519592fcf21206c79c02854320afcdf3ab4917" +checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" dependencies = [ "percent-encoding", "time", @@ -821,18 +799,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" -[[package]] -name = "cortex-m" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70858629a458fdfd39f9675c4dc309411f2a3f83bede76988d81bf1a0ecee9e0" -dependencies = [ - "bare-metal 0.2.5", - "bitfield", - "embedded-hal", - "volatile-register", -] - [[package]] name = "cow-utils" version = "0.1.2" @@ -868,15 +834,9 @@ dependencies = [ [[package]] name = "critical-section" -version = "0.2.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd" -dependencies = [ - "bare-metal 1.0.0", - "cfg-if", - "cortex-m", - "riscv", -] +checksum = "6548a0ad5d2549e111e1f6a11a6c2e2d00ce6a3dafe22948d67c2b443f775e52" [[package]] name = "crossbeam" @@ -915,9 +875,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.11" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f916dfc5d356b0ed9dae65f1db9fc9770aa2851d2662b988ccf4fe3516e86348" +checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a" dependencies = [ "autocfg", "cfg-if", @@ -928,9 +888,9 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7" +checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" dependencies = [ "cfg-if", "crossbeam-utils", @@ -938,9 +898,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.12" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbafec5fa1f196ca66527c1b12c2ec4745ca14b50f1ad8f9f6f720b55d11fac" +checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f" dependencies = [ "cfg-if", ] @@ -979,9 +939,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4529658bdda7fd6769b8614be250cdcfc3aeb0ee72fe66f9e41e5e5eb73eac02" +checksum = "b0dd3cd20dc6b5a876612a6e5accfe7f3dd883db6d07acfbf14c128f61550dfa" dependencies = [ "darling_core", "darling_macro", @@ -989,27 +949,27 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "649c91bc01e8b1eac09fb91e8dbc7d517684ca6be8ebc75bb9cafc894f9fdb6f" +checksum = "a784d2ccaf7c98501746bf0be29b2022ba41fd62a2e622af997a03e9f972859f" dependencies = [ "fnv", "ident_case", - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.49", + "quote 1.0.23", "strsim", - "syn 1.0.103", + "syn 1.0.107", ] [[package]] name = "darling_macro" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc69c5bfcbd2fc09a0f38451d2daf0e372e367986a83906d1b0dbc88134fb5" +checksum = "7618812407e9402654622dd402b0a89dff9ba93badd6540781526117b92aab7e" dependencies = [ "darling_core", - "quote 1.0.21", - "syn 1.0.103", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -1028,9 +988,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f91d4cfa921f1c05904dc3c57b4a32c38aed3340cce209f3a6fd1478babafc4" dependencies = [ "darling", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -1040,7 +1000,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f0314b72bed045f3a68671b3c86328386762c93f82d98c65c3cb5e5f573dd68" dependencies = [ "derive_builder_core", - "syn 1.0.103", + "syn 1.0.107", ] [[package]] @@ -1050,23 +1010,42 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ "convert_case 0.4.0", - "proc-macro2 1.0.47", - "quote 1.0.21", - "rustc_version 0.4.0", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "rustc_version", + "syn 1.0.107", +] + +[[package]] +name = "deserr" +version = "0.1.0" +dependencies = [ + "deserr-internal", + "serde-cs", + "serde_json", +] + +[[package]] +name = "deserr-internal" +version = "0.1.0" +dependencies = [ + "convert_case 0.5.0", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "deunicode" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ff6a4480d42625e59bc4e8b5dc3723279fd24d83afe8aa20df217276261cd6" +checksum = "8c1bba4f227a4a53d12b653f50ca7bf10c9119ae2aba56aff9e0338b5c98f36a" [[package]] name = "digest" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adfbc57365a37acbd2ebf2b64d7e69bb766e2fea813521ed536f5d0520dcf86c" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ "block-buffer", "crypto-common", @@ -1116,7 +1095,7 @@ dependencies = [ "tempfile", "thiserror", "time", - "uuid 1.2.1", + "uuid 1.2.2", ] [[package]] @@ -1128,16 +1107,6 @@ dependencies = [ "serde", ] -[[package]] -name = "embedded-hal" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35949884794ad573cf46071e41c9b60efb0cb311e3ca01f7af807af1debc66ff" -dependencies = [ - "nb 0.1.3", - "void", -] - [[package]] name = "encode_unicode" version = "0.3.6" @@ -1228,9 +1197,9 @@ dependencies = [ [[package]] name = "enum-iterator" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a0ac4aeb3a18f92eaf09c6bb9b3ac30ff61ca95514fc58cbead1c9a6bf5401" +checksum = "91a4ec26efacf4aeff80887a175a419493cb6f8b5480d26387eb0bd038976187" dependencies = [ "enum-iterator-derive", ] @@ -1241,16 +1210,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "828de45d0ca18782232dfb8f3ea9cc428e8ced380eb26a520baaacfc70de39ce" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "env_logger" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c90bf5f19754d10198ccb95b70664fc925bd1fc090a0fd9a6ebc54acc8cd6272" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", @@ -1306,9 +1275,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35c9bb4a2c13ffb3a93a39902aaf4e7190a1706a4779b6db0449aee433d26c4a" dependencies = [ "darling", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", "uuid 0.8.2", ] @@ -1319,19 +1288,19 @@ dependencies = [ "faux", "tempfile", "thiserror", - "uuid 1.2.1", + "uuid 1.2.2", ] [[package]] name = "filetime" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9663d381d07ae25dc88dbdf27df458faa83a9b25336bcac83d5e452b5fc9d3" +checksum = "4e884668cd0c7480504233e951174ddc3b382f7c2666e3b7310b5c4e7b0c37f9" dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -1345,9 +1314,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6" +checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841" dependencies = [ "crc32fast", "miniz_oxide", @@ -1436,9 +1405,9 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -1514,22 +1483,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e45727250e75cc04ff2846a66397da8ef2b3db8e40e0cef4df67950a07621eb9" dependencies = [ "proc-macro-error", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "gimli" -version = "0.26.2" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" +checksum = "dec7af912d60cdbd3677c1af9352ebae6fb8394d165568a2234df0fa00f87793" [[package]] name = "git2" -version = "0.14.4" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0155506aab710a86160ddb504a480d2964d7ab5b9e62419be69e0032bc5931c" +checksum = "2994bee4a3a6a51eb90c218523be382fd7ea09b16380b9312e9dbe955ff7c7d1" dependencies = [ "bitflags", "libc", @@ -1600,7 +1569,7 @@ checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" dependencies = [ "atomic-polyfill", "hash32", - "rustc_version 0.4.0", + "rustc_version", "spin 0.9.4", "stable_deref_trait", ] @@ -1654,6 +1623,15 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "hex" version = "0.4.3" @@ -1677,7 +1655,7 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa 1.0.4", + "itoa 1.0.5", ] [[package]] @@ -1711,9 +1689,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.20" +version = "0.14.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" +checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c" dependencies = [ "bytes", "futures-channel", @@ -1724,7 +1702,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.4", + "itoa 1.0.5", "pin-project-lite", "socket2", "tokio", @@ -1735,9 +1713,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.23.0" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c" dependencies = [ "http", "hyper", @@ -1788,14 +1766,14 @@ dependencies = [ "tempfile", "thiserror", "time", - "uuid 1.2.1", + "uuid 1.2.2", ] [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399" dependencies = [ "autocfg", "hashbrown", @@ -1804,9 +1782,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.21.0" +version = "1.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581d4e3314cae4536e5d22ffd23189d4a374696c5ef733eadafae0ed273fd303" +checksum = "eb5686bd8e9239eabe90bb30a0c341bffd6fdc177fb556708f2cb792bf00352d" dependencies = [ "console", "lazy_static", @@ -1829,15 +1807,31 @@ dependencies = [ [[package]] name = "io-lifetimes" -version = "0.7.4" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e481ccbe3dea62107216d0d1138bb8ad8e5e5c43009a098bd1990272c497b0" +checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c" +dependencies = [ + "libc", + "windows-sys", +] [[package]] name = "ipnet" -version = "2.5.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e" + +[[package]] +name = "is-terminal" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189" +dependencies = [ + "hermit-abi 0.2.6", + "io-lifetimes", + "rustix", + "windows-sys", +] [[package]] name = "itertools" @@ -1856,9 +1850,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "jieba-rs" @@ -1903,9 +1897,9 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "8.1.1" +version = "8.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa4b4af834c6cfd35d8763d359661b90f2e45d8f750a0849156c7f4671af09c" +checksum = "09f4f04699947111ec1733e71778d763555737579e44b85844cae8e1940a1828" dependencies = [ "base64", "pem", @@ -1938,15 +1932,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.137" +version = "0.2.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" [[package]] name = "libgit2-sys" -version = "0.13.4+1.4.2" +version = "0.14.0+1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0fa6563431ede25f5cc7f6d803c6afbc1c5d3ad3d4925d12c882bf2b526f5d1" +checksum = "47a00859c70c8a4f7218e6d1cc32875c4b55f6799445b842b0d8ed5e4c3d959b" dependencies = [ "cc", "libc", @@ -1956,17 +1950,18 @@ dependencies = [ [[package]] name = "libm" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "292a948cd991e376cf75541fe5b97a1081d713c618b4f1b9500f8844e49eb565" +checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" [[package]] name = "libmimalloc-sys" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc093ab289b0bfda3aa1bdfab9c9542be29c7ef385cfcbe77f8c9813588eb48" +checksum = "04d1c67deb83e6b75fa4fe3309e09cfeade12e7721d95322af500d3814ea60c9" dependencies = [ "cc", + "libc", ] [[package]] @@ -2165,14 +2160,14 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.0.46" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4d2456c373231a208ad294c33dc5bff30051eafd954cd4caae83a712b12854d" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" [[package]] name = "lmdb-rkv-sys" version = "0.15.1" -source = "git+https://github.com/meilisearch/lmdb-rs#0144fb2bac524cdc2897d7750681ed3fff2dc3ac" +source = "git+https://github.com/meilisearch/lmdb-rs#501aa34a1ab7f092e3ff54a6c22ff6c55931a2d8" dependencies = [ "cc", "libc", @@ -2233,9 +2228,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10a9062912d7952c5588cc474795e0b9ee008e7e6781127945b85413d4b99d81" dependencies = [ "log", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -2255,9 +2250,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f08150cf2bab1fc47c2196f4f41173a27fcd0f684165e5458c0046b53a472e2f" dependencies = [ "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -2288,6 +2283,7 @@ dependencies = [ "actix-cors", "actix-http", "actix-rt", + "actix-utils", "actix-web", "actix-web-static-files", "anyhow", @@ -2295,12 +2291,13 @@ dependencies = [ "async-stream", "async-trait", "brotli", - "bstr 1.0.1", + "bstr 1.1.0", "byte-unit", "bytes", "cargo_toml", - "clap 4.0.18", + "clap 4.0.32", "crossbeam-channel", + "deserr", "dump", "either", "env_logger", @@ -2343,6 +2340,7 @@ dependencies = [ "serde", "serde-cs", "serde_json", + "serde_urlencoded", "sha-1", "sha2", "siphasher", @@ -2358,7 +2356,7 @@ dependencies = [ "tokio-stream", "toml", "urlencoding", - "uuid 1.2.1", + "uuid 1.2.2", "vergen", "walkdir", "yaup", @@ -2380,7 +2378,7 @@ dependencies = [ "sha2", "thiserror", "time", - "uuid 1.2.1", + "uuid 1.2.2", ] [[package]] @@ -2391,6 +2389,7 @@ dependencies = [ "anyhow", "convert_case 0.6.0", "csv", + "deserr", "either", "enum-iterator", "file-store", @@ -2410,7 +2409,7 @@ dependencies = [ "thiserror", "time", "tokio", - "uuid 1.2.1", + "uuid 1.2.2", ] [[package]] @@ -2421,18 +2420,18 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memmap2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95af15f345b17af2efc8ead6080fb8bc376f8cec1b35277b935637595fe77498" +checksum = "4b182332558b18d807c4ce1ca8ca983b34c3ee32765e47b3f0f69b90355cc1dc" dependencies = [ "libc", ] [[package]] name = "memoffset" -version = "0.6.5" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" dependencies = [ "autocfg", ] @@ -2444,7 +2443,7 @@ source = "git+https://github.com/meilisearch/milli.git?tag=v0.38.0#c3f4835e8e102 dependencies = [ "bimap", "bincode", - "bstr 1.0.1", + "bstr 1.1.0", "byteorder", "charabia", "concat-arrays", @@ -2479,14 +2478,14 @@ dependencies = [ "tempfile", "thiserror", "time", - "uuid 1.2.1", + "uuid 1.2.2", ] [[package]] name = "mimalloc" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ce6a4b40d3bff9eb3ce9881ca0737a85072f9f975886082640cd46a75cdb35" +checksum = "9b2374e2999959a7b583e1811a1ddbf1d3a4b9496eceb9746f1192a59d871eca" dependencies = [ "libmimalloc-sys", ] @@ -2515,9 +2514,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.5.4" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] @@ -2531,24 +2530,9 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys 0.42.0", + "windows-sys", ] -[[package]] -name = "nb" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801d31da0513b6ec5214e9bf433a77966320625a37860f910be265be6e18d06f" -dependencies = [ - "nb 1.0.0", -] - -[[package]] -name = "nb" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546c37ac5d9e56f55e73b677106873d9d9f5190605e41a856503623648488cae" - [[package]] name = "nelson" version = "0.1.0" @@ -2556,9 +2540,9 @@ source = "git+https://github.com/meilisearch/nelson.git?rev=675f13885548fb415ead [[package]] name = "nom" -version = "7.1.1" +version = "7.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36" +checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c" dependencies = [ "memchr", "minimal-lexical", @@ -2617,28 +2601,19 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "num_threads" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ + "hermit-abi 0.2.6", "libc", ] [[package]] name = "object" -version = "0.29.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21158b2c33aa6d4561f1c0a6ea283ca92bc54802a93b263e910746d679a7eb53" +checksum = "8d864c91689fdc196779b98dba0aceac6118594c2df6ee5d943eb6a8df4d107a" dependencies = [ "memchr", ] @@ -2651,9 +2626,9 @@ checksum = "f69e48cd7c8e5bb52a1da1287fdbfd877c32673176583ce664cd63b201aba385" [[package]] name = "once_cell" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "opaque-debug" @@ -2663,18 +2638,18 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "ordered-float" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f74e330193f90ec45e2b257fa3ef6df087784157ac1ad2c1e71c62837b03aa7" +checksum = "d84eb1409416d254e4a9c8fa56cc24701755025b458f0fcd8e59e1f5f40c23bf" dependencies = [ "num-traits", ] [[package]] name = "os_str_bytes" -version = "6.3.0" +version = "6.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ff7415e9ae3fff1225851df9e0d9e4e5479f947619774677a63572e55e80eff" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" [[package]] name = "page_size" @@ -2708,15 +2683,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0" +checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys 0.42.0", + "windows-sys", ] [[package]] @@ -2732,9 +2707,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1" +checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba" [[package]] name = "path-matchers" @@ -2788,9 +2763,9 @@ dependencies = [ [[package]] name = "pest" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc7bc69c062e492337d74d59b120c274fd3d261b6bf6d3207d499b4b379c41a" +checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4" dependencies = [ "thiserror", "ucd-trie", @@ -2798,9 +2773,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b75706b9642ebcb34dab3bc7750f811609a0eb1dd8b88c2d15bf628c1c65b2" +checksum = "96504449aa860c8dcde14f9fba5c58dc6658688ca1fe363589d6327b8662c603" dependencies = [ "pest", "pest_generator", @@ -2808,22 +2783,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4f9272122f5979a6511a749af9db9bfc810393f63119970d7085fed1c4ea0db" +checksum = "798e0220d1111ae63d66cb66a5dcb3fc2d986d520b98e49e1852bfdb11d7c5e7" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "pest_meta" -version = "2.4.0" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c8717927f9b79515e565a64fe46c38b8cd0427e64c40680b14a7365ab09ac8d" +checksum = "984298b75898e30a843e278a9f2452c31e349a073a0ce6fd950a12a74464e065" dependencies = [ "once_cell", "pest", @@ -2903,9 +2878,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "proc-macro-error" @@ -2914,9 +2889,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", "version_check", ] @@ -2926,8 +2901,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.49", + "quote 1.0.23", "version_check", ] @@ -2942,18 +2917,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] [[package]] name = "procfs" -version = "0.14.1" +version = "0.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfb6451c91904606a1abe93e83a8ec851f45827fa84273f256ade45dc095818" +checksum = "b1de8dacb0873f77e6aefc6d71e044761fcc68060290f5b1089fcdf84626bb69" dependencies = [ "bitflags", "byteorder", @@ -3039,11 +3014,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ - "proc-macro2 1.0.47", + "proc-macro2 1.0.49", ] [[package]] @@ -3087,21 +3062,19 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "6db3a213adf02b3bcfd2d3846bb41cb22857d131789e01df434fb7e7bc0759b7" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "cac410af5d00ab6884528b4ab69d1e8e146e8d471201800fa1b4524126de6ad3" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -3131,9 +3104,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" +checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a" dependencies = [ "aho-corasick", "memchr", @@ -3148,9 +3121,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.27" +version = "0.6.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" +checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848" [[package]] name = "remove_dir_all" @@ -3163,9 +3136,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.12" +version = "0.11.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "431949c384f4e2ae07605ccaa56d1d9d2ecdb5cadd4f9577ccfab29f2e5149fc" +checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c" dependencies = [ "base64", "bytes", @@ -3221,27 +3194,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "riscv" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6907ccdd7a31012b70faf2af85cd9e5ba97657cc3987c4f13f8e4d2c2a088aba" -dependencies = [ - "bare-metal 1.0.0", - "bit_field", - "riscv-target", -] - -[[package]] -name = "riscv-target" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88aa938cda42a0cf62a20cfe8d139ff1af20c2e681212b5b34adb5a58333f222" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "roaring" version = "0.10.1" @@ -3272,36 +3224,27 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.14", + "semver", ] [[package]] name = "rustix" -version = "0.35.12" +version = "0.36.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "985947f9b6423159c4726323f373be0a21bdb514c5af06a849cb3d2dce2d01e8" +checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549" dependencies = [ "bitflags", "errno", "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.36.1", + "windows-sys", ] [[package]] @@ -3327,9 +3270,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8" +checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70" [[package]] name = "rusty-fork" @@ -3345,9 +3288,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "same-file" @@ -3390,30 +3333,15 @@ dependencies = [ [[package]] name = "semver" -version = "0.9.0" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a" [[package]] name = "serde" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965" +checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb" dependencies = [ "serde_derive", ] @@ -3429,23 +3357,23 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.147" +version = "1.0.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852" +checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "serde_json" -version = "1.0.87" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce777b7b150d76b9cf60d28b55f5847135a003f7d7350c6be7a773508ce7d45" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "indexmap", - "itoa 1.0.4", + "itoa 1.0.5", "ryu", "serde", ] @@ -3457,16 +3385,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.4", + "itoa 1.0.5", "ryu", "serde", ] [[package]] name = "sha-1" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" dependencies = [ "cfg-if", "cpufeatures", @@ -3506,9 +3434,9 @@ dependencies = [ [[package]] name = "similar" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62ac7f900db32bf3fd12e0117dd3dc4da74bc52ebaac97f39668446d89694803" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" [[package]] name = "simple_asn1" @@ -3643,12 +3571,12 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.103" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", + "proc-macro2 1.0.49", + "quote 1.0.23", "unicode-ident", ] @@ -3667,17 +3595,17 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", "unicode-xid 0.2.4", ] [[package]] name = "sysinfo" -version = "0.26.6" +version = "0.26.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6d0dedf2e65d25b365c588382be9dc3a3ee4b0ed792366cf722d174c359d948" +checksum = "29ddf41e393a9133c81d5f0974195366bd57082deac6e0eb02ed39b8341c2bb6" dependencies = [ "cfg-if", "core-foundation-sys", @@ -3731,16 +3659,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "textwrap" version = "0.16.0" @@ -3749,33 +3667,31 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" +checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" +checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] name = "time" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fab5c8b9980850e06d92ddbe3ab839c062c801f3927c0fb8abd6fc8e918fbca" +checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ - "itoa 1.0.4", - "libc", - "num_threads", + "itoa 1.0.5", "serde", "time-core", "time-macros", @@ -3789,9 +3705,9 @@ checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd" [[package]] name = "time-macros" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bb801831d812c562ae7d2bfb531f26e66e4e1f6b17307ba4149c5064710e5b" +checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2" dependencies = [ "time-core", ] @@ -3813,9 +3729,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.21.2" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e03c497dc955702ba729190dc4aac6f2a0ce97f913e5b1b5912fc5039d9099" +checksum = "7125661431c26622a80ca5051a2f936c9a678318e0351007b0cc313143024e5c" dependencies = [ "autocfg", "bytes", @@ -3828,18 +3744,18 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "winapi", + "windows-sys", ] [[package]] name = "tokio-macros" -version = "1.8.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", ] [[package]] @@ -3880,9 +3796,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f" dependencies = [ "serde", ] @@ -3922,9 +3838,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" @@ -3949,9 +3865,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-normalization" @@ -4020,20 +3936,14 @@ dependencies = [ [[package]] name = "uuid" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feb41e78f93363bb2df8b0e86a2ca30eed7806ea16ea0c790d757cf93f79be83" +checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c" dependencies = [ "getrandom", "serde", ] -[[package]] -name = "vcell" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002" - [[package]] name = "vcpkg" version = "0.2.15" @@ -4042,9 +3952,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "vergen" -version = "7.4.2" +version = "7.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ba753d713ec3844652ad2cb7eb56bc71e34213a14faddac7852a10ba88f61e" +checksum = "571b69f690c855821462709b6f41d42ceccc316fbd17b60bd06d06928cfe6a99" dependencies = [ "anyhow", "cfg-if", @@ -4062,21 +3972,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - -[[package]] -name = "volatile-register" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ee8f19f9d74293faf70901bc20ad067dc1ad390d2cbf1e3f75f721ffee908b6" -dependencies = [ - "vcell", -] - [[package]] name = "wait-timeout" version = "0.2.0" @@ -4132,9 +4027,9 @@ dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", "wasm-bindgen-shared", ] @@ -4156,7 +4051,7 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ - "quote 1.0.21", + "quote 1.0.23", "wasm-bindgen-macro-support", ] @@ -4166,9 +4061,9 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ - "proc-macro2 1.0.47", - "quote 1.0.21", - "syn 1.0.103", + "proc-macro2 1.0.49", + "quote 1.0.23", + "syn 1.0.107", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4201,9 +4096,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.22.5" +version = "0.22.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be" +checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87" dependencies = [ "webpki", ] @@ -4249,19 +4144,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - [[package]] name = "windows-sys" version = "0.42.0" @@ -4269,12 +4151,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" dependencies = [ "windows_aarch64_gnullvm", - "windows_aarch64_msvc 0.42.0", - "windows_i686_gnu 0.42.0", - "windows_i686_msvc 0.42.0", - "windows_x86_64_gnu 0.42.0", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", "windows_x86_64_gnullvm", - "windows_x86_64_msvc 0.42.0", + "windows_x86_64_msvc", ] [[package]] @@ -4283,48 +4165,24 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e" -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - [[package]] name = "windows_aarch64_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4" -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - [[package]] name = "windows_i686_gnu" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7" -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - [[package]] name = "windows_i686_msvc" version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246" -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - [[package]] name = "windows_x86_64_gnu" version = "0.42.0" @@ -4337,12 +4195,6 @@ version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028" -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - [[package]] name = "windows_x86_64_msvc" version = "0.42.0" @@ -4408,8 +4260,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d498dbd1fd7beb83c86709ae1c33ca50942889473473d287d56ce4770a18edfb" dependencies = [ - "proc-macro2 1.0.47", - "syn 1.0.103", + "proc-macro2 1.0.49", + "syn 1.0.107", "synstructure", ] @@ -4454,9 +4306,9 @@ dependencies = [ [[package]] name = "zstd-sys" -version = "2.0.1+zstd.1.5.2" +version = "2.0.4+zstd.1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fd07cbbc53846d9145dbffdf6dd09a7a0aa52be46741825f5c97bdd4f73f12b" +checksum = "4fa202f2ef00074143e219d15b62ffc317d17cc33909feac471c044087cad7b0" dependencies = [ "cc", "libc", diff --git a/dump/src/lib.rs b/dump/src/lib.rs index 7a7b9a5b7..c4a7cbae0 100644 --- a/dump/src/lib.rs +++ b/dump/src/lib.rs @@ -249,17 +249,17 @@ pub(crate) mod test { pub fn create_test_settings() -> Settings { let settings = Settings { - displayed_attributes: Setting::Set(vec![S("race"), S("name")]), - searchable_attributes: Setting::Set(vec![S("name"), S("race")]), - filterable_attributes: Setting::Set(btreeset! { S("race"), S("age") }), - sortable_attributes: Setting::Set(btreeset! { S("age") }), - ranking_rules: Setting::NotSet, - stop_words: Setting::NotSet, - synonyms: Setting::NotSet, - distinct_attribute: Setting::NotSet, - typo_tolerance: Setting::NotSet, - faceting: Setting::NotSet, - pagination: Setting::NotSet, + displayed_attributes: Setting::Set(vec![S("race"), S("name")]).into(), + searchable_attributes: Setting::Set(vec![S("name"), S("race")]).into(), + filterable_attributes: Setting::Set(btreeset! { S("race"), S("age") }).into(), + sortable_attributes: Setting::Set(btreeset! { S("age") }).into(), + ranking_rules: Setting::NotSet.into(), + stop_words: Setting::NotSet.into(), + synonyms: Setting::NotSet.into(), + distinct_attribute: Setting::NotSet.into(), + typo_tolerance: Setting::NotSet.into(), + faceting: Setting::NotSet.into(), + pagination: Setting::NotSet.into(), _kind: std::marker::PhantomData, }; settings.check() diff --git a/dump/src/reader/v6/mod.rs b/dump/src/reader/v6/mod.rs index 1cb1d66db..b3cc6c7d3 100644 --- a/dump/src/reader/v6/mod.rs +++ b/dump/src/reader/v6/mod.rs @@ -26,7 +26,7 @@ pub type Kind = crate::KindDump; pub type Details = meilisearch_types::tasks::Details; // everything related to the settings -pub type Setting = meilisearch_types::milli::update::Setting; +pub type Setting = meilisearch_types::settings::Setting; pub type TypoTolerance = meilisearch_types::settings::TypoSettings; pub type MinWordSizeForTypos = meilisearch_types::settings::MinWordSizeTyposSetting; pub type FacetingSettings = meilisearch_types::settings::FacetingSettings; diff --git a/index-scheduler/src/error.rs b/index-scheduler/src/error.rs index 037f8a269..b7f72210d 100644 --- a/index-scheduler/src/error.rs +++ b/index-scheduler/src/error.rs @@ -1,3 +1,5 @@ +use std::fmt::Display; + use meilisearch_types::error::{Code, ErrorCode}; use meilisearch_types::tasks::{Kind, Status}; use meilisearch_types::{heed, milli}; @@ -5,6 +7,42 @@ use thiserror::Error; use crate::TaskId; +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum DateField { + BeforeEnqueuedAt, + AfterEnqueuedAt, + BeforeStartedAt, + AfterStartedAt, + BeforeFinishedAt, + AfterFinishedAt, +} + +impl Display for DateField { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + DateField::BeforeEnqueuedAt => write!(f, "beforeEnqueuedAt"), + DateField::AfterEnqueuedAt => write!(f, "afterEnqueuedAt"), + DateField::BeforeStartedAt => write!(f, "beforeStartedAt"), + DateField::AfterStartedAt => write!(f, "afterStartedAt"), + DateField::BeforeFinishedAt => write!(f, "beforeFinishedAt"), + DateField::AfterFinishedAt => write!(f, "afterFinishedAt"), + } + } +} + +impl From for Code { + fn from(date: DateField) -> Self { + match date { + DateField::BeforeEnqueuedAt => Code::InvalidTaskBeforeEnqueuedAt, + DateField::AfterEnqueuedAt => Code::InvalidTaskAfterEnqueuedAt, + DateField::BeforeStartedAt => Code::InvalidTaskBeforeStartedAt, + DateField::AfterStartedAt => Code::InvalidTaskAfterStartedAt, + DateField::BeforeFinishedAt => Code::InvalidTaskBeforeFinishedAt, + DateField::AfterFinishedAt => Code::InvalidTaskAfterFinishedAt, + } + } +} + #[allow(clippy::large_enum_variant)] #[derive(Error, Debug)] pub enum Error { @@ -31,7 +69,7 @@ pub enum Error { #[error( "Task `{field}` `{date}` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format." )] - InvalidTaskDate { field: String, date: String }, + InvalidTaskDate { field: DateField, date: String }, #[error("Task uid `{task_uid}` is invalid. It should only contain numeric characters.")] InvalidTaskUids { task_uid: String }, #[error( @@ -102,11 +140,11 @@ impl ErrorCode for Error { Error::IndexAlreadyExists(_) => Code::IndexAlreadyExists, Error::SwapDuplicateIndexesFound(_) => Code::DuplicateIndexFound, Error::SwapDuplicateIndexFound(_) => Code::DuplicateIndexFound, - Error::InvalidTaskDate { .. } => Code::InvalidTaskDateFilter, - Error::InvalidTaskUids { .. } => Code::InvalidTaskUidsFilter, - Error::InvalidTaskStatuses { .. } => Code::InvalidTaskStatusesFilter, - Error::InvalidTaskTypes { .. } => Code::InvalidTaskTypesFilter, - Error::InvalidTaskCanceledBy { .. } => Code::InvalidTaskCanceledByFilter, + Error::InvalidTaskDate { field, .. } => (*field).into(), + Error::InvalidTaskUids { .. } => Code::InvalidTaskUids, + Error::InvalidTaskStatuses { .. } => Code::InvalidTaskStatuses, + Error::InvalidTaskTypes { .. } => Code::InvalidTaskTypes, + Error::InvalidTaskCanceledBy { .. } => Code::InvalidTaskCanceledBy, Error::InvalidIndexUid { .. } => Code::InvalidIndexUid, Error::TaskNotFound(_) => Code::TaskNotFound, Error::TaskDeletionWithEmptyQuery => Code::TaskDeletionWithEmptyQuery, diff --git a/meilisearch-types/Cargo.toml b/meilisearch-types/Cargo.toml index 72170359a..c52171419 100644 --- a/meilisearch-types/Cargo.toml +++ b/meilisearch-types/Cargo.toml @@ -5,6 +5,7 @@ authors = ["marin "] edition = "2021" [dependencies] +deserr = { path = "../../deserr", features = ["serde-json"] } actix-web = { version = "4.2.1", default-features = false } anyhow = "1.0.65" convert_case = "0.6.0" diff --git a/meilisearch-types/src/error.rs b/meilisearch-types/src/error.rs index 54231cf2b..f617233a9 100644 --- a/meilisearch-types/src/error.rs +++ b/meilisearch-types/src/error.rs @@ -119,9 +119,13 @@ pub enum Code { // index related error CreateIndex, IndexAlreadyExists, + InvalidIndexPrimaryKey, IndexNotFound, InvalidIndexUid, + MissingIndexUid, InvalidMinWordLengthForTypo, + InvalidIndexLimit, + InvalidIndexOffset, DuplicateIndexFound, @@ -138,6 +142,55 @@ pub enum Code { Filter, Sort, + // Invalid swap-indexes + InvalidSwapIndexes, + + // Invalid settings update request + InvalidSettingsDisplayedAttributes, + InvalidSettingsSearchableAttributes, + InvalidSettingsFilterableAttributes, + InvalidSettingsSortableAttributes, + InvalidSettingsRankingRules, + InvalidSettingsStopWords, + InvalidSettingsSynonyms, + InvalidSettingsDistinctAttribute, + InvalidSettingsTypoTolerance, + InvalidSettingsFaceting, + InvalidSettingsPagination, + + // Invalid search request + InvalidSearchQ, + InvalidSearchOffset, + InvalidSearchLimit, + InvalidSearchPage, + InvalidSearchHitsPerPage, + InvalidSearchAttributesToRetrieve, + InvalidSearchAttributesToCrop, + InvalidSearchCropLength, + InvalidSearchAttributesToHighlight, + InvalidSearchShowMatchesPosition, + InvalidSearchFilter, + InvalidSearchSort, + InvalidSearchFacets, + InvalidSearchHighlightPreTag, + InvalidSearchHighlightPostTag, + InvalidSearchCropMarker, + InvalidSearchMatchingStrategy, + + // Related to the tasks + InvalidTaskUids, + InvalidTaskTypes, + InvalidTaskStatuses, + InvalidTaskCanceledBy, + InvalidTaskLimit, + InvalidTaskFrom, + InvalidTaskBeforeEnqueuedAt, + InvalidTaskAfterEnqueuedAt, + InvalidTaskBeforeStartedAt, + InvalidTaskAfterStartedAt, + InvalidTaskBeforeFinishedAt, + InvalidTaskAfterFinishedAt, + BadParameter, BadRequest, DatabaseSizeLimitReached, @@ -150,11 +203,6 @@ pub enum Code { MissingAuthorizationHeader, MissingMasterKey, DumpNotFound, - InvalidTaskDateFilter, - InvalidTaskStatusesFilter, - InvalidTaskTypesFilter, - InvalidTaskCanceledByFilter, - InvalidTaskUidsFilter, TaskNotFound, TaskDeletionWithEmptyQuery, TaskCancelationWithEmptyQuery, @@ -209,6 +257,12 @@ impl Code { // thrown when requesting an unexisting index IndexNotFound => ErrCode::invalid("index_not_found", StatusCode::NOT_FOUND), InvalidIndexUid => ErrCode::invalid("invalid_index_uid", StatusCode::BAD_REQUEST), + MissingIndexUid => ErrCode::invalid("missing_index_uid", StatusCode::BAD_REQUEST), + InvalidIndexPrimaryKey => { + ErrCode::invalid("invalid_index_primary_key", StatusCode::BAD_REQUEST) + } + InvalidIndexLimit => ErrCode::invalid("invalid_index_limit", StatusCode::BAD_REQUEST), + InvalidIndexOffset => ErrCode::invalid("invalid_index_offset", StatusCode::BAD_REQUEST), // invalid state error InvalidState => ErrCode::internal("invalid_state", StatusCode::INTERNAL_SERVER_ERROR), @@ -259,21 +313,6 @@ impl Code { MissingMasterKey => { ErrCode::authentication("missing_master_key", StatusCode::UNAUTHORIZED) } - InvalidTaskDateFilter => { - ErrCode::invalid("invalid_task_date_filter", StatusCode::BAD_REQUEST) - } - InvalidTaskUidsFilter => { - ErrCode::invalid("invalid_task_uids_filter", StatusCode::BAD_REQUEST) - } - InvalidTaskStatusesFilter => { - ErrCode::invalid("invalid_task_statuses_filter", StatusCode::BAD_REQUEST) - } - InvalidTaskTypesFilter => { - ErrCode::invalid("invalid_task_types_filter", StatusCode::BAD_REQUEST) - } - InvalidTaskCanceledByFilter => { - ErrCode::invalid("invalid_task_canceled_by_filter", StatusCode::BAD_REQUEST) - } TaskNotFound => ErrCode::invalid("task_not_found", StatusCode::NOT_FOUND), TaskDeletionWithEmptyQuery => { ErrCode::invalid("missing_task_filters", StatusCode::BAD_REQUEST) @@ -336,6 +375,116 @@ impl Code { DuplicateIndexFound => { ErrCode::invalid("duplicate_index_found", StatusCode::BAD_REQUEST) } + + InvalidSwapIndexes => ErrCode::invalid("invalid_swap_indexes", StatusCode::BAD_REQUEST), + + InvalidSettingsDisplayedAttributes => { + ErrCode::invalid("invalid_settings_displayed_attributes", StatusCode::BAD_REQUEST) + } + InvalidSettingsSearchableAttributes => { + ErrCode::invalid("invalid_settings_searchable_attributes", StatusCode::BAD_REQUEST) + } + InvalidSettingsFilterableAttributes => { + ErrCode::invalid("invalid_settings_filterable_attributes", StatusCode::BAD_REQUEST) + } + InvalidSettingsSortableAttributes => { + ErrCode::invalid("invalid_settings_sortable_attributes", StatusCode::BAD_REQUEST) + } + InvalidSettingsRankingRules => { + ErrCode::invalid("invalid_settings_ranking_rules", StatusCode::BAD_REQUEST) + } + InvalidSettingsStopWords => { + ErrCode::invalid("invalid_settings_stop_words", StatusCode::BAD_REQUEST) + } + InvalidSettingsSynonyms => { + ErrCode::invalid("invalid_settings_synonyms", StatusCode::BAD_REQUEST) + } + InvalidSettingsDistinctAttribute => { + ErrCode::invalid("invalid_settings_distinct_attribute", StatusCode::BAD_REQUEST) + } + InvalidSettingsTypoTolerance => { + ErrCode::invalid("invalid_settings_typo_tolerance", StatusCode::BAD_REQUEST) + } + InvalidSettingsFaceting => { + ErrCode::invalid("invalid_settings_faceting", StatusCode::BAD_REQUEST) + } + InvalidSettingsPagination => { + ErrCode::invalid("invalid_settings_pagination", StatusCode::BAD_REQUEST) + } + + InvalidSearchQ => ErrCode::invalid("invalid_search_q", StatusCode::BAD_REQUEST), + InvalidSearchOffset => { + ErrCode::invalid("invalid_search_offset", StatusCode::BAD_REQUEST) + } + InvalidSearchLimit => ErrCode::invalid("invalid_search_limit", StatusCode::BAD_REQUEST), + InvalidSearchPage => ErrCode::invalid("invalid_search_page", StatusCode::BAD_REQUEST), + InvalidSearchHitsPerPage => { + ErrCode::invalid("invalid_search_hits_per_page", StatusCode::BAD_REQUEST) + } + InvalidSearchAttributesToRetrieve => { + ErrCode::invalid("invalid_search_attributes_to_retrieve", StatusCode::BAD_REQUEST) + } + InvalidSearchAttributesToCrop => { + ErrCode::invalid("invalid_search_attributes_to_crop", StatusCode::BAD_REQUEST) + } + InvalidSearchCropLength => { + ErrCode::invalid("invalid_search_crop_length", StatusCode::BAD_REQUEST) + } + InvalidSearchAttributesToHighlight => { + ErrCode::invalid("invalid_search_attributes_to_highlight", StatusCode::BAD_REQUEST) + } + InvalidSearchShowMatchesPosition => { + ErrCode::invalid("invalid_search_show_matches_position", StatusCode::BAD_REQUEST) + } + InvalidSearchFilter => { + ErrCode::invalid("invalid_search_filter", StatusCode::BAD_REQUEST) + } + InvalidSearchSort => ErrCode::invalid("invalid_search_sort", StatusCode::BAD_REQUEST), + InvalidSearchFacets => { + ErrCode::invalid("invalid_search_facets", StatusCode::BAD_REQUEST) + } + InvalidSearchHighlightPreTag => { + ErrCode::invalid("invalid_search_highlight_pre_tag", StatusCode::BAD_REQUEST) + } + InvalidSearchHighlightPostTag => { + ErrCode::invalid("invalid_search_highlight_post_tag", StatusCode::BAD_REQUEST) + } + InvalidSearchCropMarker => { + ErrCode::invalid("invalid_search_crop_marker", StatusCode::BAD_REQUEST) + } + InvalidSearchMatchingStrategy => { + ErrCode::invalid("invalid_search_matching_strategy", StatusCode::BAD_REQUEST) + } + + // Related to the tasks + InvalidTaskUids => ErrCode::invalid("invalid_task_uids", StatusCode::BAD_REQUEST), + InvalidTaskTypes => ErrCode::invalid("invalid_task_types", StatusCode::BAD_REQUEST), + InvalidTaskStatuses => { + ErrCode::invalid("invalid_task_statuses", StatusCode::BAD_REQUEST) + } + InvalidTaskCanceledBy => { + ErrCode::invalid("invalid_task_canceled_by", StatusCode::BAD_REQUEST) + } + InvalidTaskLimit => ErrCode::invalid("invalid_task_limit", StatusCode::BAD_REQUEST), + InvalidTaskFrom => ErrCode::invalid("invalid_task_from", StatusCode::BAD_REQUEST), + InvalidTaskBeforeEnqueuedAt => { + ErrCode::invalid("invalid_task_before_enqueued_at", StatusCode::BAD_REQUEST) + } + InvalidTaskAfterEnqueuedAt => { + ErrCode::invalid("invalid_task_after_enqueued_at", StatusCode::BAD_REQUEST) + } + InvalidTaskBeforeStartedAt => { + ErrCode::invalid("invalid_task_before_started_at", StatusCode::BAD_REQUEST) + } + InvalidTaskAfterStartedAt => { + ErrCode::invalid("invalid_task_after_started_at", StatusCode::BAD_REQUEST) + } + InvalidTaskBeforeFinishedAt => { + ErrCode::invalid("invalid_task_before_finished_at", StatusCode::BAD_REQUEST) + } + InvalidTaskAfterFinishedAt => { + ErrCode::invalid("invalid_task_after_finished_at", StatusCode::BAD_REQUEST) + } } } @@ -476,6 +625,13 @@ impl ErrorCode for io::Error { } } +pub fn unwrap_any(any: Result) -> T { + match any { + Ok(any) => any, + Err(any) => any, + } +} + #[cfg(feature = "test-traits")] mod strategy { use proptest::strategy::Strategy; diff --git a/meilisearch-types/src/settings.rs b/meilisearch-types/src/settings.rs index 3369cfdfb..f863e1905 100644 --- a/meilisearch-types/src/settings.rs +++ b/meilisearch-types/src/settings.rs @@ -2,10 +2,10 @@ use std::collections::{BTreeMap, BTreeSet}; use std::marker::PhantomData; use std::num::NonZeroUsize; +use deserr::{DeserializeError, DeserializeFromValue}; use fst::IntoStreamer; -use milli::update::Setting; use milli::{Index, DEFAULT_VALUES_PER_FACET}; -use serde::{Deserialize, Serialize, Serializer}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; /// The maximimum number of results that the engine /// will be able to return in one search call. @@ -27,16 +27,135 @@ where .serialize(s) } +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +pub enum Setting { + Set(T), + Reset, + NotSet, +} + +impl Default for Setting { + fn default() -> Self { + Self::NotSet + } +} + +impl From> for milli::update::Setting { + fn from(value: Setting) -> Self { + match value { + Setting::Set(x) => milli::update::Setting::Set(x), + Setting::Reset => milli::update::Setting::Reset, + Setting::NotSet => milli::update::Setting::NotSet, + } + } +} +impl From> for Setting { + fn from(value: milli::update::Setting) -> Self { + match value { + milli::update::Setting::Set(x) => Setting::Set(x), + milli::update::Setting::Reset => Setting::Reset, + milli::update::Setting::NotSet => Setting::NotSet, + } + } +} + +impl Setting { + pub fn set(self) -> Option { + match self { + Self::Set(value) => Some(value), + _ => None, + } + } + + pub const fn as_ref(&self) -> Setting<&T> { + match *self { + Self::Set(ref value) => Setting::Set(value), + Self::Reset => Setting::Reset, + Self::NotSet => Setting::NotSet, + } + } + + pub const fn is_not_set(&self) -> bool { + matches!(self, Self::NotSet) + } + + /// If `Self` is `Reset`, then map self to `Set` with the provided `val`. + pub fn or_reset(self, val: T) -> Self { + match self { + Self::Reset => Self::Set(val), + otherwise => otherwise, + } + } +} + +impl Serialize for Setting { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: Serializer, + { + match self { + Self::Set(value) => Some(value), + // Usually not_set isn't serialized by setting skip_serializing_if field attribute + Self::NotSet | Self::Reset => None, + } + .serialize(serializer) + } +} + +impl<'de, T: Deserialize<'de>> Deserialize<'de> for Setting { + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + Deserialize::deserialize(deserializer).map(|x| match x { + Some(x) => Self::Set(x), + None => Self::Reset, // Reset is forced by sending null value + }) + } +} + +impl DeserializeFromValue for Setting +where + T: DeserializeFromValue, + E: DeserializeError, +{ + fn deserialize_from_value( + value: deserr::Value, + location: deserr::ValuePointerRef, + ) -> Result { + match value { + deserr::Value::Null => Ok(Setting::Reset), + _ => T::deserialize_from_value(value, location).map(Setting::Set), + } + } + fn default() -> Option { + Some(Self::NotSet) + } +} + #[derive(Clone, Default, Debug, Serialize, PartialEq, Eq)] pub struct Checked; #[derive(Clone, Default, Debug, Serialize, Deserialize, PartialEq, Eq)] pub struct Unchecked; +impl DeserializeFromValue for Unchecked +where + E: DeserializeError, +{ + fn deserialize_from_value( + _value: deserr::Value, + _location: deserr::ValuePointerRef, + ) -> Result { + unreachable!() + } +} + #[cfg_attr(test, derive(proptest_derive::Arbitrary))] -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, DeserializeFromValue)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] +#[deserr(rename_all = camelCase, deny_unknown_fields)] pub struct MinWordSizeTyposSetting { #[cfg_attr(test, proptest(strategy = "test::setting_strategy()"))] #[serde(default, skip_serializing_if = "Setting::is_not_set")] @@ -47,9 +166,10 @@ pub struct MinWordSizeTyposSetting { } #[cfg_attr(test, derive(proptest_derive::Arbitrary))] -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, DeserializeFromValue)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] +#[deserr(rename_all = camelCase, deny_unknown_fields)] pub struct TypoSettings { #[cfg_attr(test, proptest(strategy = "test::setting_strategy()"))] #[serde(default, skip_serializing_if = "Setting::is_not_set")] @@ -66,9 +186,10 @@ pub struct TypoSettings { } #[cfg_attr(test, derive(proptest_derive::Arbitrary))] -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, DeserializeFromValue)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] +#[deserr(rename_all = camelCase, deny_unknown_fields)] pub struct FacetingSettings { #[cfg_attr(test, proptest(strategy = "test::setting_strategy()"))] #[serde(default, skip_serializing_if = "Setting::is_not_set")] @@ -76,9 +197,10 @@ pub struct FacetingSettings { } #[cfg_attr(test, derive(proptest_derive::Arbitrary))] -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, DeserializeFromValue)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] +#[deserr(rename_all = camelCase, deny_unknown_fields)] pub struct PaginationSettings { #[cfg_attr(test, proptest(strategy = "test::setting_strategy()"))] #[serde(default, skip_serializing_if = "Setting::is_not_set")] @@ -88,10 +210,11 @@ pub struct PaginationSettings { /// Holds all the settings for an index. `T` can either be `Checked` if they represents settings /// whose validity is guaranteed, or `Unchecked` if they need to be validated. In the later case, a /// call to `check` will return a `Settings` from a `Settings`. -#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq)] +#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq, Eq, DeserializeFromValue)] #[serde(deny_unknown_fields)] #[serde(rename_all = "camelCase")] #[serde(bound(serialize = "T: Serialize", deserialize = "T: Deserialize<'static>"))] +#[deserr(rename_all = camelCase, deny_unknown_fields)] #[cfg_attr(test, derive(proptest_derive::Arbitrary))] pub struct Settings { #[serde( diff --git a/meilisearch/Cargo.toml b/meilisearch/Cargo.toml index 89b97f910..2cf620e1e 100644 --- a/meilisearch/Cargo.toml +++ b/meilisearch/Cargo.toml @@ -7,6 +7,7 @@ name = "meilisearch" version = "1.0.0" [dependencies] +deserr = { path = "../../deserr", features = ["serde-json"] } actix-cors = "0.6.3" actix-http = { version = "3.2.2", default-features = false, features = ["compress-brotli", "compress-gzip", "rustls"] } actix-web = { version = "4.2.1", default-features = false, features = ["macros", "compress-brotli", "compress-gzip", "cookies", "rustls"] } @@ -71,6 +72,8 @@ toml = "0.5.9" uuid = { version = "1.1.2", features = ["serde", "v4"] } walkdir = "2.3.2" yaup = "0.2.0" +serde_urlencoded = "0.7.1" +actix-utils = "3.0.1" [dev-dependencies] actix-rt = "2.7.0" @@ -99,17 +102,7 @@ zip = { version = "0.6.2", optional = true } default = ["analytics", "meilisearch-types/default", "mini-dashboard"] metrics = ["prometheus"] analytics = ["segment"] -mini-dashboard = [ - "actix-web-static-files", - "static-files", - "anyhow", - "cargo_toml", - "hex", - "reqwest", - "sha-1", - "tempfile", - "zip", -] +mini-dashboard = ["actix-web-static-files", "static-files", "anyhow", "cargo_toml", "hex", "reqwest", "sha-1", "tempfile", "zip"] chinese = ["meilisearch-types/chinese"] hebrew = ["meilisearch-types/hebrew"] japanese = ["meilisearch-types/japanese"] diff --git a/meilisearch/src/extractors/deserr.rs b/meilisearch/src/extractors/deserr.rs new file mode 100644 index 000000000..f800a228e --- /dev/null +++ b/meilisearch/src/extractors/deserr.rs @@ -0,0 +1,78 @@ +use std::fmt::Debug; +use std::future::Future; +use std::marker::PhantomData; +use std::pin::Pin; +use std::task::{Context, Poll}; + +use actix_web::dev::Payload; +use actix_web::web::Json; +use actix_web::{FromRequest, HttpRequest}; +use deserr::{DeserializeError, DeserializeFromValue}; +use futures::ready; +use meilisearch_types::error::{ErrorCode, ResponseError}; + +/// Extractor for typed data from Json request payloads +/// deserialised by deserr. +/// +/// # Extractor +/// To extract typed data from a request body, the inner type `T` must implement the +/// [`deserr::DeserializeFromError`] trait. The inner type `E` must implement the +/// [`ErrorCode`](meilisearch_error::ErrorCode) trait. +#[derive(Debug)] +pub struct ValidatedJson(pub T, PhantomData<*const E>); + +impl ValidatedJson { + pub fn new(data: T) -> Self { + ValidatedJson(data, PhantomData) + } + pub fn into_inner(self) -> T { + self.0 + } +} + +impl FromRequest for ValidatedJson +where + E: DeserializeError + ErrorCode + 'static, + T: DeserializeFromValue, +{ + type Error = actix_web::Error; + type Future = ValidatedJsonExtractFut; + + #[inline] + fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { + ValidatedJsonExtractFut { + fut: Json::::from_request(req, payload), + _phantom: PhantomData, + } + } +} + +pub struct ValidatedJsonExtractFut { + fut: as FromRequest>::Future, + _phantom: PhantomData<*const (T, E)>, +} + +impl Future for ValidatedJsonExtractFut +where + T: DeserializeFromValue, + E: DeserializeError + ErrorCode + 'static, +{ + type Output = Result, actix_web::Error>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let ValidatedJsonExtractFut { fut, .. } = self.get_mut(); + let fut = Pin::new(fut); + + let res = ready!(fut.poll(cx)); + + let res = match res { + Err(err) => Err(err), + Ok(data) => match deserr::deserialize::<_, _, E>(data.into_inner()) { + Ok(data) => Ok(ValidatedJson::new(data)), + Err(e) => Err(ResponseError::from(e).into()), + }, + }; + + Poll::Ready(res) + } +} diff --git a/meilisearch/src/extractors/json.rs b/meilisearch/src/extractors/json.rs new file mode 100644 index 000000000..f800a228e --- /dev/null +++ b/meilisearch/src/extractors/json.rs @@ -0,0 +1,78 @@ +use std::fmt::Debug; +use std::future::Future; +use std::marker::PhantomData; +use std::pin::Pin; +use std::task::{Context, Poll}; + +use actix_web::dev::Payload; +use actix_web::web::Json; +use actix_web::{FromRequest, HttpRequest}; +use deserr::{DeserializeError, DeserializeFromValue}; +use futures::ready; +use meilisearch_types::error::{ErrorCode, ResponseError}; + +/// Extractor for typed data from Json request payloads +/// deserialised by deserr. +/// +/// # Extractor +/// To extract typed data from a request body, the inner type `T` must implement the +/// [`deserr::DeserializeFromError`] trait. The inner type `E` must implement the +/// [`ErrorCode`](meilisearch_error::ErrorCode) trait. +#[derive(Debug)] +pub struct ValidatedJson(pub T, PhantomData<*const E>); + +impl ValidatedJson { + pub fn new(data: T) -> Self { + ValidatedJson(data, PhantomData) + } + pub fn into_inner(self) -> T { + self.0 + } +} + +impl FromRequest for ValidatedJson +where + E: DeserializeError + ErrorCode + 'static, + T: DeserializeFromValue, +{ + type Error = actix_web::Error; + type Future = ValidatedJsonExtractFut; + + #[inline] + fn from_request(req: &HttpRequest, payload: &mut Payload) -> Self::Future { + ValidatedJsonExtractFut { + fut: Json::::from_request(req, payload), + _phantom: PhantomData, + } + } +} + +pub struct ValidatedJsonExtractFut { + fut: as FromRequest>::Future, + _phantom: PhantomData<*const (T, E)>, +} + +impl Future for ValidatedJsonExtractFut +where + T: DeserializeFromValue, + E: DeserializeError + ErrorCode + 'static, +{ + type Output = Result, actix_web::Error>; + + fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll { + let ValidatedJsonExtractFut { fut, .. } = self.get_mut(); + let fut = Pin::new(fut); + + let res = ready!(fut.poll(cx)); + + let res = match res { + Err(err) => Err(err), + Ok(data) => match deserr::deserialize::<_, _, E>(data.into_inner()) { + Ok(data) => Ok(ValidatedJson::new(data)), + Err(e) => Err(ResponseError::from(e).into()), + }, + }; + + Poll::Ready(res) + } +} diff --git a/meilisearch/src/extractors/mod.rs b/meilisearch/src/extractors/mod.rs index 98a22f8c9..cb1ac28bf 100644 --- a/meilisearch/src/extractors/mod.rs +++ b/meilisearch/src/extractors/mod.rs @@ -1,4 +1,7 @@ pub mod payload; #[macro_use] pub mod authentication; +// pub mod deserr; +pub mod json; +pub mod query_parameters; pub mod sequential_extractor; diff --git a/meilisearch/src/extractors/query_parameters.rs b/meilisearch/src/extractors/query_parameters.rs new file mode 100644 index 000000000..ebbf33a04 --- /dev/null +++ b/meilisearch/src/extractors/query_parameters.rs @@ -0,0 +1,134 @@ +//! For query parameter extractor documentation, see [`Query`]. + +use std::marker::PhantomData; +use std::{fmt, ops}; + +use actix_http::Payload; +use actix_utils::future::{err, ok, Ready}; +use actix_web::{FromRequest, HttpRequest}; +use deserr::{DeserializeError, DeserializeFromValue}; +use meilisearch_types::error::{Code, ErrorCode, ResponseError}; + +/// Extract typed information from the request's query. +/// +/// To extract typed data from the URL query string, the inner type `T` must implement the +/// [`DeserializeOwned`] trait. +/// +/// Use [`QueryConfig`] to configure extraction process. +/// +/// # Panics +/// A query string consists of unordered `key=value` pairs, therefore it cannot be decoded into any +/// type which depends upon data ordering (eg. tuples). Trying to do so will result in a panic. +/// +/// # Examples +/// ``` +/// use actix_web::{get, web}; +/// use serde::Deserialize; +/// +/// #[derive(Debug, Deserialize)] +/// pub enum ResponseType { +/// Token, +/// Code +/// } +/// +/// #[derive(Debug, Deserialize)] +/// pub struct AuthRequest { +/// id: u64, +/// response_type: ResponseType, +/// } +/// +/// // Deserialize `AuthRequest` struct from query string. +/// // This handler gets called only if the request's query parameters contain both fields. +/// // A valid request path for this handler would be `/?id=64&response_type=Code"`. +/// #[get("/")] +/// async fn index(info: web::Query) -> String { +/// format!("Authorization request for id={} and type={:?}!", info.id, info.response_type) +/// } +/// +/// // To access the entire underlying query struct, use `.into_inner()`. +/// #[get("/debug1")] +/// async fn debug1(info: web::Query) -> String { +/// dbg!("Authorization object = {:?}", info.into_inner()); +/// "OK".to_string() +/// } +/// +/// // Or use destructuring, which is equivalent to `.into_inner()`. +/// #[get("/debug2")] +/// async fn debug2(web::Query(info): web::Query) -> String { +/// dbg!("Authorization object = {:?}", info); +/// "OK".to_string() +/// } +/// ``` +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct QueryParameter(pub T, PhantomData<*const E>); + +impl QueryParameter { + /// Unwrap into inner `T` value. + pub fn into_inner(self) -> T { + self.0 + } +} + +impl QueryParameter +where + T: DeserializeFromValue, + E: DeserializeError + ErrorCode + 'static, +{ + /// Deserialize a `T` from the URL encoded query parameter string. + /// + /// ``` + /// # use std::collections::HashMap; + /// # use actix_web::web::Query; + /// let numbers = Query::>::from_query("one=1&two=2").unwrap(); + /// assert_eq!(numbers.get("one"), Some(&1)); + /// assert_eq!(numbers.get("two"), Some(&2)); + /// assert!(numbers.get("three").is_none()); + /// ``` + pub fn from_query(query_str: &str) -> Result { + let value = serde_urlencoded::from_str::(query_str) + .map_err(|e| ResponseError::from_msg(e.to_string(), Code::BadRequest))?; + + match deserr::deserialize::<_, _, E>(value) { + Ok(data) => Ok(QueryParameter(data, PhantomData)), + Err(e) => Err(ResponseError::from(e).into()), + } + } +} + +impl ops::Deref for QueryParameter { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + +impl ops::DerefMut for QueryParameter { + fn deref_mut(&mut self) -> &mut T { + &mut self.0 + } +} + +impl fmt::Display for QueryParameter { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} + +/// See [here](#Examples) for example of usage as an extractor. +impl FromRequest for QueryParameter +where + T: DeserializeFromValue, + E: DeserializeError + ErrorCode + 'static, +{ + type Error = actix_web::Error; + type Future = Ready>; + + #[inline] + fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future { + QueryParameter::from_query(&req.query_string()).map(ok).unwrap_or_else(err) + // serde_urlencoded::from_str::(req.query_string()) + // .map(|val| Ok(QueryParameter(val, PhantomData))) + // .unwrap_or_else(|e| err(ResponseError::from_msg(e.to_string(), Code::BadRequest))) + } +} diff --git a/meilisearch/src/routes/indexes/mod.rs b/meilisearch/src/routes/indexes/mod.rs index e8fca0cf8..4eaba12f1 100644 --- a/meilisearch/src/routes/indexes/mod.rs +++ b/meilisearch/src/routes/indexes/mod.rs @@ -1,8 +1,14 @@ +use std::convert::Infallible; +use std::num::ParseIntError; + use actix_web::web::Data; use actix_web::{web, HttpRequest, HttpResponse}; +use deserr::{ + DeserializeError, DeserializeFromValue, ErrorKind, IntoValue, MergeWithError, ValuePointerRef, +}; use index_scheduler::IndexScheduler; use log::debug; -use meilisearch_types::error::ResponseError; +use meilisearch_types::error::{unwrap_any, Code, ErrorCode, ResponseError}; use meilisearch_types::index_uid::IndexUid; use meilisearch_types::milli::{self, FieldDistribution, Index}; use meilisearch_types::tasks::KindWithContent; @@ -14,6 +20,8 @@ use super::{Pagination, SummarizedTaskView}; use crate::analytics::Analytics; use crate::extractors::authentication::policies::*; use crate::extractors::authentication::{AuthenticationError, GuardedData}; +use crate::extractors::json::ValidatedJson; +use crate::extractors::query_parameters::QueryParameter; use crate::extractors::sequential_extractor::SeqHandler; pub mod documents; @@ -66,7 +74,7 @@ impl IndexView { pub async fn list_indexes( index_scheduler: GuardedData, Data>, - paginate: web::Query, + paginate: QueryParameter, ) -> Result { let search_rules = &index_scheduler.filters().search_rules; let indexes: Vec<_> = index_scheduler.indexes()?; @@ -82,8 +90,68 @@ pub async fn list_indexes( Ok(HttpResponse::Ok().json(ret)) } -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[derive(Debug)] +pub struct ListIndexesDeserrError { + error: String, + code: Code, +} + +impl std::fmt::Display for ListIndexesDeserrError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.error) + } +} + +impl std::error::Error for ListIndexesDeserrError {} +impl ErrorCode for ListIndexesDeserrError { + fn error_code(&self) -> Code { + self.code + } +} + +impl MergeWithError for ListIndexesDeserrError { + fn merge( + _self_: Option, + other: ListIndexesDeserrError, + _merge_location: ValuePointerRef, + ) -> Result { + Err(other) + } +} + +impl deserr::DeserializeError for ListIndexesDeserrError { + fn error( + _self_: Option, + error: ErrorKind, + location: ValuePointerRef, + ) -> Result { + let code = match location.last_field() { + Some("offset") => Code::InvalidIndexLimit, + Some("limit") => Code::InvalidIndexOffset, + _ => Code::BadRequest, + }; + let error = unwrap_any(deserr::serde_json::JsonError::error(None, error, location)).0; + + Err(ListIndexesDeserrError { error, code }) + } +} + +impl MergeWithError for ListIndexesDeserrError { + fn merge( + _self_: Option, + other: ParseIntError, + merge_location: ValuePointerRef, + ) -> Result { + ListIndexesDeserrError::error::( + None, + ErrorKind::Unexpected { msg: other.to_string() }, + merge_location, + ) + } +} + +#[derive(DeserializeFromValue, Debug)] +#[deserr(rename_all = camelCase, deny_unknown_fields)] pub struct IndexCreateRequest { uid: String, primary_key: Option, @@ -91,7 +159,7 @@ pub struct IndexCreateRequest { pub async fn create_index( index_scheduler: GuardedData, Data>, - body: web::Json, + body: ValidatedJson, req: HttpRequest, analytics: web::Data, ) -> Result { @@ -116,11 +184,58 @@ pub async fn create_index( } } -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -#[allow(dead_code)] +#[derive(Debug)] +pub struct CreateIndexesDeserrError { + error: String, + code: Code, +} + +impl std::fmt::Display for CreateIndexesDeserrError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.error) + } +} + +impl std::error::Error for CreateIndexesDeserrError {} +impl ErrorCode for CreateIndexesDeserrError { + fn error_code(&self) -> Code { + self.code + } +} + +impl MergeWithError for CreateIndexesDeserrError { + fn merge( + _self_: Option, + other: CreateIndexesDeserrError, + _merge_location: ValuePointerRef, + ) -> Result { + Err(other) + } +} + +impl deserr::DeserializeError for CreateIndexesDeserrError { + fn error( + _self_: Option, + error: ErrorKind, + location: ValuePointerRef, + ) -> Result { + let code = match location.last_field() { + Some("uid") => Code::InvalidIndexUid, + Some("primaryKey") => Code::InvalidIndexPrimaryKey, + None if matches!(error, ErrorKind::MissingField { field } if field == "uid") => { + Code::MissingIndexUid + } + _ => Code::BadRequest, + }; + let error = unwrap_any(deserr::serde_json::JsonError::error(None, error, location)).0; + + Err(CreateIndexesDeserrError { error, code }) + } +} + +#[derive(DeserializeFromValue, Debug)] +#[deserr(rename_all = camelCase, deny_unknown_fields)] pub struct UpdateIndexRequest { - uid: Option, primary_key: Option, } @@ -139,7 +254,7 @@ pub async fn get_index( pub async fn update_index( index_scheduler: GuardedData, Data>, path: web::Path, - body: web::Json, + body: ValidatedJson, req: HttpRequest, analytics: web::Data, ) -> Result { @@ -147,7 +262,7 @@ pub async fn update_index( let body = body.into_inner(); analytics.publish( "Index Updated".to_string(), - json!({ "primary_key": body.primary_key}), + json!({ "primary_key": body.primary_key }), Some(&req), ); @@ -163,6 +278,51 @@ pub async fn update_index( Ok(HttpResponse::Accepted().json(task)) } +#[derive(Debug)] +pub struct UpdateIndexesDeserrError { + error: String, + code: Code, +} + +impl std::fmt::Display for UpdateIndexesDeserrError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.error) + } +} + +impl std::error::Error for UpdateIndexesDeserrError {} +impl ErrorCode for UpdateIndexesDeserrError { + fn error_code(&self) -> Code { + self.code + } +} + +impl MergeWithError for UpdateIndexesDeserrError { + fn merge( + _self_: Option, + other: UpdateIndexesDeserrError, + _merge_location: ValuePointerRef, + ) -> Result { + Err(other) + } +} + +impl deserr::DeserializeError for UpdateIndexesDeserrError { + fn error( + _self_: Option, + error: ErrorKind, + location: ValuePointerRef, + ) -> Result { + let code = match location.last_field() { + Some("primaryKey") => Code::InvalidIndexPrimaryKey, + _ => Code::BadRequest, + }; + let error = unwrap_any(deserr::serde_json::JsonError::error(None, error, location)).0; + + Err(UpdateIndexesDeserrError { error, code }) + } +} + pub async fn delete_index( index_scheduler: GuardedData, Data>, index_uid: web::Path, diff --git a/meilisearch/src/routes/indexes/search.rs b/meilisearch/src/routes/indexes/search.rs index af5da44a0..bf0115997 100644 --- a/meilisearch/src/routes/indexes/search.rs +++ b/meilisearch/src/routes/indexes/search.rs @@ -1,21 +1,25 @@ +use std::str::FromStr; + use actix_web::web::Data; use actix_web::{web, HttpRequest, HttpResponse}; use index_scheduler::IndexScheduler; use log::debug; use meilisearch_auth::IndexSearchRules; use meilisearch_types::error::ResponseError; -use serde::Deserialize; use serde_cs::vec::CS; use serde_json::Value; use crate::analytics::{Analytics, SearchAggregator}; use crate::extractors::authentication::policies::*; use crate::extractors::authentication::GuardedData; +use crate::extractors::json::ValidatedJson; +use crate::extractors::query_parameters::QueryParameter; use crate::extractors::sequential_extractor::SeqHandler; +use crate::routes::from_string_to_option; use crate::search::{ - perform_search, MatchingStrategy, SearchQuery, DEFAULT_CROP_LENGTH, DEFAULT_CROP_MARKER, - DEFAULT_HIGHLIGHT_POST_TAG, DEFAULT_HIGHLIGHT_PRE_TAG, DEFAULT_SEARCH_LIMIT, - DEFAULT_SEARCH_OFFSET, + perform_search, MatchingStrategy, SearchDeserError, SearchQuery, DEFAULT_CROP_LENGTH, + DEFAULT_CROP_MARKER, DEFAULT_HIGHLIGHT_POST_TAG, DEFAULT_HIGHLIGHT_PRE_TAG, + DEFAULT_SEARCH_LIMIT, DEFAULT_SEARCH_OFFSET, }; pub fn configure(cfg: &mut web::ServiceConfig) { @@ -26,33 +30,35 @@ pub fn configure(cfg: &mut web::ServiceConfig) { ); } -#[derive(Deserialize, Debug)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[derive(Debug, deserr::DeserializeFromValue)] +#[deserr(rename_all = camelCase, deny_unknown_fields)] pub struct SearchQueryGet { q: Option, - #[serde(default = "DEFAULT_SEARCH_OFFSET")] + #[deserr(default = DEFAULT_SEARCH_OFFSET(), from(&String) = FromStr::from_str -> std::num::ParseIntError)] offset: usize, - #[serde(default = "DEFAULT_SEARCH_LIMIT")] + #[deserr(default = DEFAULT_SEARCH_LIMIT(), from(&String) = FromStr::from_str -> std::num::ParseIntError)] limit: usize, + #[deserr(from(&String) = from_string_to_option -> std::num::ParseIntError)] page: Option, + #[deserr(from(&String) = from_string_to_option -> std::num::ParseIntError)] hits_per_page: Option, attributes_to_retrieve: Option>, attributes_to_crop: Option>, - #[serde(default = "DEFAULT_CROP_LENGTH")] + #[deserr(default = DEFAULT_CROP_LENGTH(), from(&String) = FromStr::from_str -> std::num::ParseIntError)] crop_length: usize, attributes_to_highlight: Option>, filter: Option, sort: Option, - #[serde(default = "Default::default")] + #[deserr(default, from(&String) = FromStr::from_str -> std::str::ParseBoolError)] show_matches_position: bool, facets: Option>, - #[serde(default = "DEFAULT_HIGHLIGHT_PRE_TAG")] + #[deserr(default = DEFAULT_HIGHLIGHT_PRE_TAG())] highlight_pre_tag: String, - #[serde(default = "DEFAULT_HIGHLIGHT_POST_TAG")] + #[deserr(default = DEFAULT_HIGHLIGHT_POST_TAG())] highlight_post_tag: String, - #[serde(default = "DEFAULT_CROP_MARKER")] + #[deserr(default = DEFAULT_CROP_MARKER())] crop_marker: String, - #[serde(default)] + #[deserr(default)] matching_strategy: MatchingStrategy, } @@ -136,7 +142,7 @@ fn fix_sort_query_parameters(sort_query: &str) -> Vec { pub async fn search_with_url_query( index_scheduler: GuardedData, Data>, index_uid: web::Path, - params: web::Query, + params: QueryParameter, req: HttpRequest, analytics: web::Data, ) -> Result { @@ -168,7 +174,7 @@ pub async fn search_with_url_query( pub async fn search_with_post( index_scheduler: GuardedData, Data>, index_uid: web::Path, - params: web::Json, + params: ValidatedJson, req: HttpRequest, analytics: web::Data, ) -> Result { diff --git a/meilisearch/src/routes/indexes/settings.rs b/meilisearch/src/routes/indexes/settings.rs index d2508a3c8..47e5a4d50 100644 --- a/meilisearch/src/routes/indexes/settings.rs +++ b/meilisearch/src/routes/indexes/settings.rs @@ -1,8 +1,11 @@ +use std::fmt; + use actix_web::web::Data; use actix_web::{web, HttpRequest, HttpResponse}; +use deserr::{IntoValue, ValuePointerRef}; use index_scheduler::IndexScheduler; use log::debug; -use meilisearch_types::error::ResponseError; +use meilisearch_types::error::{unwrap_any, Code, ErrorCode, ResponseError}; use meilisearch_types::index_uid::IndexUid; use meilisearch_types::settings::{settings, Settings, Unchecked}; use meilisearch_types::tasks::KindWithContent; @@ -11,6 +14,7 @@ use serde_json::json; use crate::analytics::Analytics; use crate::extractors::authentication::policies::*; use crate::extractors::authentication::GuardedData; +use crate::extractors::json::ValidatedJson; use crate::routes::SummarizedTaskView; #[macro_export] @@ -39,7 +43,7 @@ macro_rules! make_setting_route { >, index_uid: web::Path, ) -> Result { - let new_settings = Settings { $attr: Setting::Reset, ..Default::default() }; + let new_settings = Settings { $attr: Setting::Reset.into(), ..Default::default() }; let allow_index_creation = index_scheduler.filters().allow_index_creation; let index_uid = IndexUid::try_from(index_uid.into_inner())?.into_inner(); @@ -74,8 +78,8 @@ macro_rules! make_setting_route { let new_settings = Settings { $attr: match body { - Some(inner_body) => Setting::Set(inner_body), - None => Setting::Reset, + Some(inner_body) => Setting::Set(inner_body).into(), + None => Setting::Reset.into(), }, ..Default::default() }; @@ -208,7 +212,7 @@ make_setting_route!( "TypoTolerance Updated".to_string(), json!({ "typo_tolerance": { - "enabled": setting.as_ref().map(|s| !matches!(s.enabled, Setting::Set(false))), + "enabled": setting.as_ref().map(|s| !matches!(s.enabled.into(), Setting::Set(false))), "disable_on_attributes": setting .as_ref() .and_then(|s| s.disable_on_attributes.as_ref().set().map(|m| !m.is_empty())), @@ -424,10 +428,66 @@ generate_configure!( faceting ); +#[derive(Debug)] +pub struct SettingsDeserrError { + error: String, + code: Code, +} + +impl std::fmt::Display for SettingsDeserrError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.error) + } +} + +impl std::error::Error for SettingsDeserrError {} +impl ErrorCode for SettingsDeserrError { + fn error_code(&self) -> Code { + self.code + } +} + +impl deserr::MergeWithError for SettingsDeserrError { + fn merge( + _self_: Option, + other: SettingsDeserrError, + _merge_location: ValuePointerRef, + ) -> Result { + Err(other) + } +} + +impl deserr::DeserializeError for SettingsDeserrError { + fn error( + _self_: Option, + error: deserr::ErrorKind, + location: ValuePointerRef, + ) -> Result { + let error = unwrap_any(deserr::serde_json::JsonError::error(None, error, location)).0; + + let code = match location.first_field() { + Some("displayedAttributes") => Code::InvalidSettingsDisplayedAttributes, + Some("searchableAttributes") => Code::InvalidSettingsSearchableAttributes, + Some("filterableAttributes") => Code::InvalidSettingsFilterableAttributes, + Some("sortableAttributes") => Code::InvalidSettingsSortableAttributes, + Some("rankingRules") => Code::InvalidSettingsRankingRules, + Some("stopWords") => Code::InvalidSettingsStopWords, + Some("synonyms") => Code::InvalidSettingsSynonyms, + Some("distinctAttribute") => Code::InvalidSettingsDistinctAttribute, + Some("typoTolerance") => Code::InvalidSettingsTypoTolerance, + Some("faceting") => Code::InvalidSettingsFaceting, + Some("pagination") => Code::InvalidSettingsPagination, + _ => Code::BadRequest, + }; + + Err(SettingsDeserrError { error, code }) + } +} + pub async fn update_all( index_scheduler: GuardedData, Data>, index_uid: web::Path, - body: web::Json>, + body: ValidatedJson, SettingsDeserrError>, req: HttpRequest, analytics: web::Data, ) -> Result { diff --git a/meilisearch/src/routes/mod.rs b/meilisearch/src/routes/mod.rs index 9fcb1c4b7..27d72f1d7 100644 --- a/meilisearch/src/routes/mod.rs +++ b/meilisearch/src/routes/mod.rs @@ -1,7 +1,9 @@ use std::collections::BTreeMap; +use std::str::FromStr; use actix_web::web::Data; use actix_web::{web, HttpRequest, HttpResponse}; +use deserr::DeserializeFromValue; use index_scheduler::{IndexScheduler, Query}; use log::debug; use meilisearch_types::error::ResponseError; @@ -49,6 +51,13 @@ where .collect() } +pub fn from_string_to_option(input: &str) -> Result, E> +where + T: FromStr, +{ + Ok(Some(input.parse()?)) +} + const PAGINATION_DEFAULT_LIMIT: fn() -> usize = || 20; #[derive(Debug, Serialize)] @@ -75,12 +84,15 @@ impl From for SummarizedTaskView { } } -#[derive(Debug, Clone, Copy, Deserialize)] +#[derive(DeserializeFromValue, Deserialize, Debug, Clone, Copy)] +#[deserr(rename_all = camelCase, deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)] pub struct Pagination { #[serde(default)] + #[deserr(default, from(&String) = FromStr::from_str -> std::num::ParseIntError)] pub offset: usize, #[serde(default = "PAGINATION_DEFAULT_LIMIT")] + #[deserr(default = PAGINATION_DEFAULT_LIMIT(), from(&String) = FromStr::from_str -> std::num::ParseIntError)] pub limit: usize, } diff --git a/meilisearch/src/routes/swap_indexes.rs b/meilisearch/src/routes/swap_indexes.rs index bc0c1705a..c2b80b5c4 100644 --- a/meilisearch/src/routes/swap_indexes.rs +++ b/meilisearch/src/routes/swap_indexes.rs @@ -1,9 +1,11 @@ +use std::fmt; + use actix_web::web::Data; use actix_web::{web, HttpRequest, HttpResponse}; +use deserr::{DeserializeFromValue, IntoValue, ValuePointerRef}; use index_scheduler::IndexScheduler; -use meilisearch_types::error::ResponseError; +use meilisearch_types::error::{unwrap_any, Code, ErrorCode, ResponseError}; use meilisearch_types::tasks::{IndexSwap, KindWithContent}; -use serde::Deserialize; use serde_json::json; use super::SummarizedTaskView; @@ -11,23 +13,26 @@ use crate::analytics::Analytics; use crate::error::MeilisearchHttpError; use crate::extractors::authentication::policies::*; use crate::extractors::authentication::{AuthenticationError, GuardedData}; +use crate::extractors::json::ValidatedJson; use crate::extractors::sequential_extractor::SeqHandler; pub fn configure(cfg: &mut web::ServiceConfig) { cfg.service(web::resource("").route(web::post().to(SeqHandler(swap_indexes)))); } -#[derive(Deserialize, Debug, Clone, PartialEq, Eq)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] + +#[derive(DeserializeFromValue, Debug, Clone, PartialEq, Eq)] +#[deserr(rename_all = camelCase, deny_unknown_fields)] pub struct SwapIndexesPayload { indexes: Vec, } pub async fn swap_indexes( index_scheduler: GuardedData, Data>, - params: web::Json>, + params: ValidatedJson, SwapIndexesDeserrError>, req: HttpRequest, analytics: web::Data, ) -> Result { + let params = params.into_inner(); analytics.publish( "Indexes Swapped".to_string(), json!({ @@ -38,7 +43,7 @@ pub async fn swap_indexes( let search_rules = &index_scheduler.filters().search_rules; let mut swaps = vec![]; - for SwapIndexesPayload { indexes } in params.into_inner().into_iter() { + for SwapIndexesPayload { indexes } in params.into_iter() { let (lhs, rhs) = match indexes.as_slice() { [lhs, rhs] => (lhs, rhs), _ => { @@ -57,3 +62,49 @@ pub async fn swap_indexes( let task: SummarizedTaskView = task.into(); Ok(HttpResponse::Accepted().json(task)) } + +#[derive(Debug)] +pub struct SwapIndexesDeserrError { + error: String, + code: Code, +} + +impl std::fmt::Display for SwapIndexesDeserrError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.error) + } +} + +impl std::error::Error for SwapIndexesDeserrError {} +impl ErrorCode for SwapIndexesDeserrError { + fn error_code(&self) -> Code { + self.code + } +} + +impl deserr::MergeWithError for SwapIndexesDeserrError { + fn merge( + _self_: Option, + other: SwapIndexesDeserrError, + _merge_location: ValuePointerRef, + ) -> Result { + Err(other) + } +} + +impl deserr::DeserializeError for SwapIndexesDeserrError { + fn error( + _self_: Option, + error: deserr::ErrorKind, + location: ValuePointerRef, + ) -> Result { + let error = unwrap_any(deserr::serde_json::JsonError::error(None, error, location)).0; + + let code = match location.last_field() { + Some("indexes") => Code::InvalidSwapIndexes, + _ => Code::BadRequest, + }; + + Err(SwapIndexesDeserrError { error, code }) + } +} diff --git a/meilisearch/src/routes/tasks.rs b/meilisearch/src/routes/tasks.rs index 914315711..d25707530 100644 --- a/meilisearch/src/routes/tasks.rs +++ b/meilisearch/src/routes/tasks.rs @@ -2,6 +2,7 @@ use std::str::FromStr; use actix_web::web::Data; use actix_web::{web, HttpRequest, HttpResponse}; +use index_scheduler::error::DateField; use index_scheduler::{IndexScheduler, Query, TaskId}; use meilisearch_types::error::ResponseError; use meilisearch_types::index_uid::IndexUid; @@ -168,6 +169,7 @@ pub struct TaskCommonQueryRaw { pub statuses: Option>>, pub index_uids: Option>>, } + impl TaskCommonQueryRaw { fn validate(self) -> Result { let Self { uids, canceled_by, types, statuses, index_uids } = self; @@ -290,37 +292,37 @@ impl TaskDateQueryRaw { for (field_name, string_value, before_or_after, dest) in [ ( - "afterEnqueuedAt", + DateField::AfterEnqueuedAt, after_enqueued_at, DeserializeDateOption::After, &mut query.after_enqueued_at, ), ( - "beforeEnqueuedAt", + DateField::BeforeEnqueuedAt, before_enqueued_at, DeserializeDateOption::Before, &mut query.before_enqueued_at, ), ( - "afterStartedAt", + DateField::AfterStartedAt, after_started_at, DeserializeDateOption::After, &mut query.after_started_at, ), ( - "beforeStartedAt", + DateField::BeforeStartedAt, before_started_at, DeserializeDateOption::Before, &mut query.before_started_at, ), ( - "afterFinishedAt", + DateField::AfterFinishedAt, after_finished_at, DeserializeDateOption::After, &mut query.after_finished_at, ), ( - "beforeFinishedAt", + DateField::BeforeFinishedAt, before_finished_at, DeserializeDateOption::Before, &mut query.before_finished_at, @@ -690,6 +692,7 @@ async fn get_task( } pub(crate) mod date_deserializer { + use index_scheduler::error::DateField; use meilisearch_types::error::ResponseError; use time::format_description::well_known::Rfc3339; use time::macros::format_description; @@ -701,7 +704,7 @@ pub(crate) mod date_deserializer { } pub fn deserialize_date( - field_name: &str, + field_name: DateField, value: &str, option: DeserializeDateOption, ) -> std::result::Result { @@ -727,7 +730,7 @@ pub(crate) mod date_deserializer { } } else { Err(index_scheduler::Error::InvalidTaskDate { - field: field_name.to_string(), + field: field_name, date: value.to_string(), } .into()) diff --git a/meilisearch/src/search.rs b/meilisearch/src/search.rs index 7310e7914..cd6dc6e30 100644 --- a/meilisearch/src/search.rs +++ b/meilisearch/src/search.rs @@ -1,9 +1,16 @@ use std::cmp::min; use std::collections::{BTreeMap, BTreeSet, HashSet}; -use std::str::FromStr; +use std::convert::Infallible; +use std::fmt; +use std::num::ParseIntError; +use std::str::{FromStr, ParseBoolError}; use std::time::Instant; +use deserr::{ + DeserializeError, DeserializeFromValue, ErrorKind, IntoValue, MergeWithError, ValuePointerRef, +}; use either::Either; +use meilisearch_types::error::{unwrap_any, Code, ErrorCode}; use meilisearch_types::settings::DEFAULT_PAGINATION_MAX_TOTAL_HITS; use meilisearch_types::{milli, Document}; use milli::tokenizer::TokenizerBuilder; @@ -26,34 +33,33 @@ pub const DEFAULT_CROP_MARKER: fn() -> String = || "…".to_string(); pub const DEFAULT_HIGHLIGHT_PRE_TAG: fn() -> String = || "".to_string(); pub const DEFAULT_HIGHLIGHT_POST_TAG: fn() -> String = || "".to_string(); -#[derive(Deserialize, Debug, Clone, PartialEq, Eq)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[derive(Debug, Clone, Default, PartialEq, DeserializeFromValue)] +#[deserr(rename_all = camelCase, deny_unknown_fields)] pub struct SearchQuery { pub q: Option, - #[serde(default = "DEFAULT_SEARCH_OFFSET")] + #[deserr(default = DEFAULT_SEARCH_OFFSET())] pub offset: usize, - #[serde(default = "DEFAULT_SEARCH_LIMIT")] + #[deserr(default = DEFAULT_SEARCH_LIMIT())] pub limit: usize, pub page: Option, pub hits_per_page: Option, pub attributes_to_retrieve: Option>, pub attributes_to_crop: Option>, - #[serde(default = "DEFAULT_CROP_LENGTH")] + #[deserr(default = DEFAULT_CROP_LENGTH())] pub crop_length: usize, pub attributes_to_highlight: Option>, - // Default to false - #[serde(default = "Default::default")] + #[deserr(default)] pub show_matches_position: bool, pub filter: Option, pub sort: Option>, pub facets: Option>, - #[serde(default = "DEFAULT_HIGHLIGHT_PRE_TAG")] + #[deserr(default = DEFAULT_HIGHLIGHT_PRE_TAG())] pub highlight_pre_tag: String, - #[serde(default = "DEFAULT_HIGHLIGHT_POST_TAG")] + #[deserr(default = DEFAULT_HIGHLIGHT_POST_TAG())] pub highlight_post_tag: String, - #[serde(default = "DEFAULT_CROP_MARKER")] + #[deserr(default = DEFAULT_CROP_MARKER())] pub crop_marker: String, - #[serde(default)] + #[deserr(default)] pub matching_strategy: MatchingStrategy, } @@ -63,7 +69,8 @@ impl SearchQuery { } } -#[derive(Deserialize, Debug, Clone, PartialEq, Eq)] +#[derive(Deserialize, Debug, Clone, PartialEq, Eq, DeserializeFromValue)] +#[deserr(rename_all = camelCase)] #[serde(rename_all = "camelCase")] pub enum MatchingStrategy { /// Remove query words from last to first @@ -87,6 +94,96 @@ impl From for TermsMatchingStrategy { } } +#[derive(Debug)] +pub struct SearchDeserError { + error: String, + code: Code, +} + +impl std::fmt::Display for SearchDeserError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.error) + } +} + +impl std::error::Error for SearchDeserError {} +impl ErrorCode for SearchDeserError { + fn error_code(&self) -> Code { + self.code + } +} + +impl MergeWithError for SearchDeserError { + fn merge( + _self_: Option, + other: SearchDeserError, + _merge_location: ValuePointerRef, + ) -> Result { + Err(other) + } +} + +impl DeserializeError for SearchDeserError { + fn error( + _self_: Option, + error: ErrorKind, + location: ValuePointerRef, + ) -> Result { + let error = unwrap_any(deserr::serde_json::JsonError::error(None, error, location)).0; + + let code = match location.last_field() { + Some("q") => Code::InvalidSearchQ, + Some("offset") => Code::InvalidSearchOffset, + Some("limit") => Code::InvalidSearchLimit, + Some("page") => Code::InvalidSearchPage, + Some("hitsPerPage") => Code::InvalidSearchHitsPerPage, + Some("attributesToRetrieve") => Code::InvalidSearchAttributesToRetrieve, + Some("attributesToCrop") => Code::InvalidSearchAttributesToCrop, + Some("cropLength") => Code::InvalidSearchCropLength, + Some("attributesToHighlight") => Code::InvalidSearchAttributesToHighlight, + Some("showMatchesPosition") => Code::InvalidSearchShowMatchesPosition, + Some("filter") => Code::InvalidSearchFilter, + Some("sort") => Code::InvalidSearchSort, + Some("facets") => Code::InvalidSearchFacets, + Some("highlightPreTag") => Code::InvalidSearchHighlightPreTag, + Some("highlightPostTag") => Code::InvalidSearchHighlightPostTag, + Some("cropMarker") => Code::InvalidSearchCropMarker, + Some("matchingStrategy") => Code::InvalidSearchMatchingStrategy, + _ => Code::BadRequest, + }; + + Err(SearchDeserError { error, code }) + } +} + +impl MergeWithError for SearchDeserError { + fn merge( + _self_: Option, + other: ParseBoolError, + merge_location: ValuePointerRef, + ) -> Result { + SearchDeserError::error::( + None, + ErrorKind::Unexpected { msg: other.to_string() }, + merge_location, + ) + } +} + +impl MergeWithError for SearchDeserError { + fn merge( + _self_: Option, + other: ParseIntError, + merge_location: ValuePointerRef, + ) -> Result { + SearchDeserError::error::( + None, + ErrorKind::Unexpected { msg: other.to_string() }, + merge_location, + ) + } +} + #[derive(Debug, Clone, Serialize, PartialEq, Eq)] pub struct SearchHit { #[serde(flatten)] diff --git a/meilisearch/tests/search/errors.rs b/meilisearch/tests/search/errors.rs index 731c86a73..837e02808 100644 --- a/meilisearch/tests/search/errors.rs +++ b/meilisearch/tests/search/errors.rs @@ -37,25 +37,105 @@ async fn search_unexisting_parameter() { } #[actix_rt::test] -async fn search_invalid_highlight_and_crop_tags() { +async fn search_invalid_crop_marker() { let server = Server::new().await; let index = server.index("test"); - let fields = &["cropMarker", "highlightPreTag", "highlightPostTag"]; + // object + let response = index.search_post(json!({"cropMarker": { "marker": "" }})).await; + meili_snap::snapshot!(format!("{:#?}", response), @r###" + ( + Object { + "message": String("invalid type: Map `{\"marker\":\"\"}`, expected a String at `.cropMarker`."), + "code": String("invalid_search_crop_marker"), + "type": String("invalid_request"), + "link": String("https://docs.meilisearch.com/errors#invalid_search_crop_marker"), + }, + 400, + ) + "###); - for field in fields { - // object - let (response, code) = - index.search_post(json!({field.to_string(): {"marker": ""}})).await; - assert_eq!(code, 400, "field {} passing object: {}", &field, response); - assert_eq!(response["code"], "bad_request"); + // array + let response = index.search_post(json!({"cropMarker": ["marker", ""]})).await; + meili_snap::snapshot!(format!("{:#?}", response), @r###" + ( + Object { + "message": String("invalid type: Sequence `[\"marker\",\"\"]`, expected a String at `.cropMarker`."), + "code": String("invalid_search_crop_marker"), + "type": String("invalid_request"), + "link": String("https://docs.meilisearch.com/errors#invalid_search_crop_marker"), + }, + 400, + ) + "###); +} - // array - let (response, code) = - index.search_post(json!({field.to_string(): ["marker", ""]})).await; - assert_eq!(code, 400, "field {} passing array: {}", &field, response); - assert_eq!(response["code"], "bad_request"); - } +#[actix_rt::test] +async fn search_invalid_highlight_pre_tag() { + let server = Server::new().await; + let index = server.index("test"); + + // object + let response = index.search_post(json!({"highlightPreTag": { "marker": "" }})).await; + meili_snap::snapshot!(format!("{:#?}", response), @r###" + ( + Object { + "message": String("invalid type: Map `{\"marker\":\"\"}`, expected a String at `.highlightPreTag`."), + "code": String("invalid_search_highlight_pre_tag"), + "type": String("invalid_request"), + "link": String("https://docs.meilisearch.com/errors#invalid_search_highlight_pre_tag"), + }, + 400, + ) + "###); + + // array + let response = index.search_post(json!({"highlightPreTag": ["marker", ""]})).await; + meili_snap::snapshot!(format!("{:#?}", response), @r###" + ( + Object { + "message": String("invalid type: Sequence `[\"marker\",\"\"]`, expected a String at `.highlightPreTag`."), + "code": String("invalid_search_highlight_pre_tag"), + "type": String("invalid_request"), + "link": String("https://docs.meilisearch.com/errors#invalid_search_highlight_pre_tag"), + }, + 400, + ) + "###); +} + +#[actix_rt::test] +async fn search_invalid_highlight_post_tag() { + let server = Server::new().await; + let index = server.index("test"); + + // object + let response = index.search_post(json!({"highlightPostTag": { "marker": "" }})).await; + meili_snap::snapshot!(format!("{:#?}", response), @r###" + ( + Object { + "message": String("invalid type: Map `{\"marker\":\"\"}`, expected a String at `.highlightPostTag`."), + "code": String("invalid_search_highlight_post_tag"), + "type": String("invalid_request"), + "link": String("https://docs.meilisearch.com/errors#invalid_search_highlight_post_tag"), + }, + 400, + ) + "###); + + // array + let response = index.search_post(json!({"highlightPostTag": ["marker", ""]})).await; + meili_snap::snapshot!(format!("{:#?}", response), @r###" + ( + Object { + "message": String("invalid type: Sequence `[\"marker\",\"\"]`, expected a String at `.highlightPostTag`."), + "code": String("invalid_search_highlight_post_tag"), + "type": String("invalid_request"), + "link": String("https://docs.meilisearch.com/errors#invalid_search_highlight_post_tag"), + }, + 400, + ) + "###); } #[actix_rt::test] diff --git a/meilisearch/tests/tasks/mod.rs b/meilisearch/tests/tasks/mod.rs index 6341876fa..caef60514 100644 --- a/meilisearch/tests/tasks/mod.rs +++ b/meilisearch/tests/tasks/mod.rs @@ -193,9 +193,9 @@ async fn get_task_filter_error() { insta::assert_json_snapshot!(response, @r###" { "message": "Task uid `pied` is invalid. It should only contain numeric characters.", - "code": "invalid_task_uids_filter", + "code": "invalid_task_uids", "type": "invalid_request", - "link": "https://docs.meilisearch.com/errors#invalid-task-uids-filter" + "link": "https://docs.meilisearch.com/errors#invalid-task-uids" } "###); @@ -215,9 +215,9 @@ async fn get_task_filter_error() { insta::assert_json_snapshot!(response, @r###" { "message": "Task `beforeStartedAt` `pied` is invalid. It should follow the YYYY-MM-DD or RFC 3339 date-time format.", - "code": "invalid_task_date_filter", + "code": "invalid_task_before_started_at", "type": "invalid_request", - "link": "https://docs.meilisearch.com/errors#invalid-task-date-filter" + "link": "https://docs.meilisearch.com/errors#invalid-task-before-started-at" } "###); } @@ -253,9 +253,9 @@ async fn delete_task_filter_error() { insta::assert_json_snapshot!(response, @r###" { "message": "Task uid `pied` is invalid. It should only contain numeric characters.", - "code": "invalid_task_uids_filter", + "code": "invalid_task_uids", "type": "invalid_request", - "link": "https://docs.meilisearch.com/errors#invalid-task-uids-filter" + "link": "https://docs.meilisearch.com/errors#invalid-task-uids" } "###); } @@ -291,9 +291,9 @@ async fn cancel_task_filter_error() { insta::assert_json_snapshot!(response, @r###" { "message": "Task uid `pied` is invalid. It should only contain numeric characters.", - "code": "invalid_task_uids_filter", + "code": "invalid_task_uids", "type": "invalid_request", - "link": "https://docs.meilisearch.com/errors#invalid-task-uids-filter" + "link": "https://docs.meilisearch.com/errors#invalid-task-uids" } "###); }