summaryrefslogtreecommitdiffstats
path: root/vendor/icu_list
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:25 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:18:25 +0000
commit5363f350887b1e5b5dd21a86f88c8af9d7fea6da (patch)
tree35ca005eb6e0e9a1ba3bb5dbc033209ad445dc17 /vendor/icu_list
parentAdding debian version 1.66.0+dfsg1-1. (diff)
downloadrustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.tar.xz
rustc-5363f350887b1e5b5dd21a86f88c8af9d7fea6da.zip
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/icu_list')
-rw-r--r--vendor/icu_list/.cargo-checksum.json1
-rw-r--r--vendor/icu_list/Cargo.lock1064
-rw-r--r--vendor/icu_list/Cargo.toml114
-rw-r--r--vendor/icu_list/LICENSE51
-rw-r--r--vendor/icu_list/README.md69
-rw-r--r--vendor/icu_list/examples/and_list.rs29
-rw-r--r--vendor/icu_list/src/error.rs27
-rw-r--r--vendor/icu_list/src/lib.rs122
-rw-r--r--vendor/icu_list/src/list_formatter.rs319
-rw-r--r--vendor/icu_list/src/provider.rs465
-rw-r--r--vendor/icu_list/src/string_matcher.rs213
11 files changed, 2474 insertions, 0 deletions
diff --git a/vendor/icu_list/.cargo-checksum.json b/vendor/icu_list/.cargo-checksum.json
new file mode 100644
index 000000000..31667c731
--- /dev/null
+++ b/vendor/icu_list/.cargo-checksum.json
@@ -0,0 +1 @@
+{"files":{"Cargo.lock":"f650478383a2f1a7aed551b2d4650d83a2e8cc3d44c749a0e4fcfc649130b9da","Cargo.toml":"ac843eda0523eadb2d7c3bb39ea34ca5c45648f2e00c1aca87607a427f583e73","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"33b424bdceea5edc4d3638592b007bf825e25a96e7fe9101a3ad04ea63637150","examples/and_list.rs":"2cf046f8af9892949db8c8b259ac060b9de5781a5941bec5d346cf82e9371774","src/error.rs":"3cf8a7962af6b43a91d9227e4d97824e4b2852d3d50fc00fb29c779768c1b915","src/lib.rs":"c0bd00a3d83d4285d33cef2af12bd9cae380ad9c81702ba7552ce14283e9651d","src/list_formatter.rs":"a5f6f9c8bf35c6e1d4cb712a73b31454c0d081572bbc0efd9997bf6013346825","src/provider.rs":"1ca4026dbc00c901763a41a4b4ad0083c32888b95d11f464a9e3389c7d976fec","src/string_matcher.rs":"6ce2a72cd61e3d87715dafb396d8e6ea4189a3e7dcb84d4188657a477b67b1e6"},"package":"c40218275f081c4493f190357c5395647b06734c2dc3dcb41cc099a0f60168b1"} \ No newline at end of file
diff --git a/vendor/icu_list/Cargo.lock b/vendor/icu_list/Cargo.lock
new file mode 100644
index 000000000..8d049ce78
--- /dev/null
+++ b/vendor/icu_list/Cargo.lock
@@ -0,0 +1,1064 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 3
+
+[[package]]
+name = "aho-corasick"
+version = "0.7.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "atomic-polyfill"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c041a8d9751a520ee19656232a18971f18946a7900f1520ee4400002244dd89"
+dependencies = [
+ "critical-section",
+]
+
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "autocfg"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
+
+[[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 = "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"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "bstr"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
+dependencies = [
+ "lazy_static",
+ "memchr",
+ "regex-automata 0.1.10",
+ "serde",
+]
+
+[[package]]
+name = "bumpalo"
+version = "3.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
+
+[[package]]
+name = "byteorder"
+version = "1.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "cast"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "clap"
+version = "2.34.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c"
+dependencies = [
+ "bitflags",
+ "textwrap",
+ "unicode-width",
+]
+
+[[package]]
+name = "cobs"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15"
+
+[[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 = "criterion"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f"
+dependencies = [
+ "atty",
+ "cast",
+ "clap",
+ "criterion-plot",
+ "csv",
+ "itertools",
+ "lazy_static",
+ "num-traits",
+ "oorandom",
+ "plotters",
+ "rayon",
+ "regex",
+ "serde",
+ "serde_cbor",
+ "serde_derive",
+ "serde_json",
+ "tinytemplate",
+ "walkdir",
+]
+
+[[package]]
+name = "criterion-plot"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876"
+dependencies = [
+ "cast",
+ "itertools",
+]
+
+[[package]]
+name = "critical-section"
+version = "0.2.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95da181745b56d4bd339530ec393508910c909c784e8962d15d722bacf0bcbcd"
+dependencies = [
+ "bare-metal 1.0.0",
+ "cfg-if",
+ "cortex-m",
+ "riscv",
+]
+
+[[package]]
+name = "crossbeam-channel"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
+dependencies = [
+ "cfg-if",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-deque"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
+dependencies = [
+ "cfg-if",
+ "crossbeam-epoch",
+ "crossbeam-utils",
+]
+
+[[package]]
+name = "crossbeam-epoch"
+version = "0.9.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
+dependencies = [
+ "autocfg",
+ "cfg-if",
+ "crossbeam-utils",
+ "memoffset",
+ "once_cell",
+ "scopeguard",
+]
+
+[[package]]
+name = "crossbeam-utils"
+version = "0.8.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+]
+
+[[package]]
+name = "csv"
+version = "1.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1"
+dependencies = [
+ "bstr",
+ "csv-core",
+ "itoa 0.4.8",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "csv-core"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
+name = "databake"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c87777d6d7bde863ba217aa87521dc857239de1f36d66aac46fd173fb0495858"
+dependencies = [
+ "databake-derive",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "databake-derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "905c7a060fc0c84c0452d97473b1177dd7a5cbc7670cfbae4a7fe22e42f6432e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "deduplicating_array"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e7f0807b2feeeda87369e8b4cf467f250f39841c8f9427bf3a972b878588937"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "displaydoc"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3bf95dc3f046b9da4f2d51833c0d3547d8564ef6910f5c1ed130306a75b92886"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "either"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+
+[[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 = "half"
+version = "1.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7"
+
+[[package]]
+name = "hash32"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
+dependencies = [
+ "byteorder",
+]
+
+[[package]]
+name = "heapless"
+version = "0.7.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743"
+dependencies = [
+ "atomic-polyfill",
+ "hash32",
+ "rustc_version 0.4.0",
+ "serde",
+ "spin",
+ "stable_deref_trait",
+]
+
+[[package]]
+name = "hermit-abi"
+version = "0.1.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "icu_benchmark_macros"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c867656f2d9c90b13709ac88e710a9d6afe33998c1dfa22384bab8804e8b3d4"
+
+[[package]]
+name = "icu_list"
+version = "1.0.0"
+dependencies = [
+ "criterion",
+ "databake",
+ "deduplicating_array",
+ "displaydoc",
+ "icu_benchmark_macros",
+ "icu_locid",
+ "icu_provider",
+ "postcard",
+ "regex-automata 0.2.0",
+ "serde",
+ "serde_json",
+ "writeable",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_locid"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34b3de5d99a0e275fe6193b9586dbf37364daebc0d39c89b5cf8376a53b789e8"
+dependencies = [
+ "displaydoc",
+ "litemap",
+ "tinystr",
+ "writeable",
+]
+
+[[package]]
+name = "icu_provider"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e629bc2b6591ed9e4467d8a0fa2a597b70cff64ff8170e54a3f0f3257b99873f"
+dependencies = [
+ "displaydoc",
+ "icu_locid",
+ "icu_provider_macros",
+ "serde",
+ "stable_deref_trait",
+ "writeable",
+ "yoke",
+ "zerofrom",
+ "zerovec",
+]
+
+[[package]]
+name = "icu_provider_macros"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38cf6f5b65cf81f0b4298da647101acbfe6ae0e25263f92bd7a22597e9d6d606"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "itertools"
+version = "0.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
+dependencies = [
+ "either",
+]
+
+[[package]]
+name = "itoa"
+version = "0.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
+
+[[package]]
+name = "itoa"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
+
+[[package]]
+name = "js-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+dependencies = [
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.133"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966"
+
+[[package]]
+name = "litemap"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f34a3f4798fac63fb48cf277eefa38f94d3443baff555bb98e4f56bc9092368e"
+
+[[package]]
+name = "lock_api"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+dependencies = [
+ "autocfg",
+ "scopeguard",
+]
+
+[[package]]
+name = "log"
+version = "0.4.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "memchr"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+
+[[package]]
+name = "memoffset"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
+dependencies = [
+ "autocfg",
+]
+
+[[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 = "num-traits"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
+dependencies = [
+ "autocfg",
+]
+
+[[package]]
+name = "num_cpus"
+version = "1.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
+dependencies = [
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
+
+[[package]]
+name = "oorandom"
+version = "11.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575"
+
+[[package]]
+name = "plotters"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97"
+dependencies = [
+ "num-traits",
+ "plotters-backend",
+ "plotters-svg",
+ "wasm-bindgen",
+ "web-sys",
+]
+
+[[package]]
+name = "plotters-backend"
+version = "0.3.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142"
+
+[[package]]
+name = "plotters-svg"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f"
+dependencies = [
+ "plotters-backend",
+]
+
+[[package]]
+name = "postcard"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c2b180dc0bade59f03fd005cb967d3f1e5f69b13922dad0cd6e047cb8af2363"
+dependencies = [
+ "cobs",
+ "heapless",
+ "serde",
+]
+
+[[package]]
+name = "proc-macro2"
+version = "1.0.44"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "rayon"
+version = "1.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d"
+dependencies = [
+ "autocfg",
+ "crossbeam-deque",
+ "either",
+ "rayon-core",
+]
+
+[[package]]
+name = "rayon-core"
+version = "1.9.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f"
+dependencies = [
+ "crossbeam-channel",
+ "crossbeam-deque",
+ "crossbeam-utils",
+ "num_cpus",
+]
+
+[[package]]
+name = "regex"
+version = "1.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+
+[[package]]
+name = "regex-automata"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e9368763f5a9b804326f3af749e16f9abf378d227bcdee7634b13d8f17793782"
+dependencies = [
+ "memchr",
+ "regex-syntax",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+
+[[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 = "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",
+]
+
+[[package]]
+name = "ryu"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+
+[[package]]
+name = "same-file"
+version = "1.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "scopeguard"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "semver"
+version = "0.9.0"
+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"
+
+[[package]]
+name = "serde"
+version = "1.0.145"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
+dependencies = [
+ "serde_derive",
+]
+
+[[package]]
+name = "serde_cbor"
+version = "0.11.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5"
+dependencies = [
+ "half",
+ "serde",
+]
+
+[[package]]
+name = "serde_derive"
+version = "1.0.145"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "serde_json"
+version = "1.0.85"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
+dependencies = [
+ "itoa 1.0.3",
+ "ryu",
+ "serde",
+]
+
+[[package]]
+name = "spin"
+version = "0.9.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f6002a767bff9e83f8eeecf883ecb8011875a21ae8da43bffb817a57e78cc09"
+dependencies = [
+ "lock_api",
+]
+
+[[package]]
+name = "stable_deref_trait"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
+
+[[package]]
+name = "syn"
+version = "1.0.101"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e90cde112c4b9690b8cbe810cba9ddd8bc1d7472e2cae317b69e9438c1cba7d2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "synstructure"
+version = "0.12.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "unicode-xid",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
+dependencies = [
+ "unicode-width",
+]
+
+[[package]]
+name = "tinystr"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8aeafdfd935e4a7fe16a91ab711fa52d54df84f9c8f7ca5837a9d1d902ef4c2"
+dependencies = [
+ "displaydoc",
+]
+
+[[package]]
+name = "tinytemplate"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
+dependencies = [
+ "serde",
+ "serde_json",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dcc811dc4066ac62f84f11307873c4850cb653bfa9b1719cee2bd2204a4bc5dd"
+
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
+[[package]]
+name = "unicode-xid"
+version = "0.2.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
+
+[[package]]
+name = "vcell"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77439c1b53d2303b20d9459b1ade71a83c716e3f9c34f3228c00e6f185d6c002"
+
+[[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 = "walkdir"
+version = "2.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
+dependencies = [
+ "same-file",
+ "winapi",
+ "winapi-util",
+]
+
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.83"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+
+[[package]]
+name = "web-sys"
+version = "0.3.60"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "writeable"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8e6ab4f5da1b24daf2c590cfac801bacb27b15b4f050e84eb60149ea726f06b"
+
+[[package]]
+name = "yoke"
+version = "0.6.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fe1d55ca72c32d573bfbd5cb2f0ca65a497854c44762957a6d3da96041a5184"
+dependencies = [
+ "serde",
+ "stable_deref_trait",
+ "yoke-derive",
+ "zerofrom",
+]
+
+[[package]]
+name = "yoke-derive"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "58c2c5bb7c929b85c1b9ec69091b0d835f0878b4fd9eb67973b25936e06c4374"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerofrom"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "79e9355fccf72b04b7deaa99ce7a0f6630530acf34045391b74460fcd714de54"
+dependencies = [
+ "zerofrom-derive",
+]
+
+[[package]]
+name = "zerofrom-derive"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8785f47d6062c1932866147f91297286a9f350b3070e9d9f0b6078e37d623c1a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
+
+[[package]]
+name = "zerovec"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b9d919a74c17749ccb17beaf6405562e413cd94e98ba52ca1e64bbe7eefbd8b8"
+dependencies = [
+ "serde",
+ "yoke",
+ "zerofrom",
+ "zerovec-derive",
+]
+
+[[package]]
+name = "zerovec-derive"
+version = "0.9.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "490e5f878c2856225e884c35927e7ea6db3c24cdb7229b72542c7526ad7ed49e"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "synstructure",
+]
diff --git a/vendor/icu_list/Cargo.toml b/vendor/icu_list/Cargo.toml
new file mode 100644
index 000000000..805f2aea4
--- /dev/null
+++ b/vendor/icu_list/Cargo.toml
@@ -0,0 +1,114 @@
+# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
+#
+# When uploading crates to the registry Cargo will automatically
+# "normalize" Cargo.toml files for maximal compatibility
+# with all versions of Cargo and also rewrite `path` dependencies
+# to registry (e.g., crates.io) dependencies.
+#
+# If you are reading this file be aware that the original Cargo.toml
+# will likely look very different (and much more reasonable).
+# See Cargo.toml.orig for the original contents.
+
+[package]
+edition = "2018"
+name = "icu_list"
+version = "1.0.0"
+authors = ["The ICU4X Project Developers"]
+include = [
+ "src/**/*",
+ "examples/**/*",
+ "benches/**/*",
+ "tests/**/*",
+ "Cargo.toml",
+ "LICENSE",
+ "README.md",
+]
+description = "ECMA-402 ListFormatter"
+readme = "README.md"
+categories = ["internationalization"]
+license = "Unicode-DFS-2016"
+repository = "https://github.com/unicode-org/icu4x"
+resolver = "2"
+
+[lib]
+path = "src/lib.rs"
+
+[[example]]
+name = "and_list"
+
+[dependencies.databake]
+version = "0.1.0"
+features = ["derive"]
+optional = true
+
+[dependencies.deduplicating_array]
+version = "0.1"
+optional = true
+
+[dependencies.displaydoc]
+version = "0.2.3"
+default-features = false
+
+[dependencies.icu_locid]
+version = "1.0.0"
+
+[dependencies.icu_provider]
+version = "1.0.0"
+features = ["macros"]
+
+[dependencies.regex-automata]
+version = "0.2"
+default-features = false
+
+[dependencies.serde]
+version = "1.0"
+features = [
+ "derive",
+ "alloc",
+]
+optional = true
+default-features = false
+
+[dependencies.writeable]
+version = "0.5"
+
+[dependencies.zerovec]
+version = "0.9"
+features = ["yoke"]
+
+[dev-dependencies.criterion]
+version = "0.3.3"
+
+[dev-dependencies.icu_benchmark_macros]
+version = "0.7"
+
+[dev-dependencies.postcard]
+version = "1.0.0"
+features = ["use-std"]
+
+[dev-dependencies.serde_json]
+version = "1"
+
+[features]
+bench = []
+datagen = [
+ "serde",
+ "std",
+ "databake",
+]
+serde = [
+ "dep:serde",
+ "icu_provider/serde",
+ "zerovec/serde",
+ "deduplicating_array",
+]
+serde_human = [
+ "serde",
+ "regex-automata/alloc",
+]
+std = [
+ "icu_provider/std",
+ "icu_locid/std",
+ "regex-automata/std",
+ "regex-automata/alloc",
+]
diff --git a/vendor/icu_list/LICENSE b/vendor/icu_list/LICENSE
new file mode 100644
index 000000000..9858d01ab
--- /dev/null
+++ b/vendor/icu_list/LICENSE
@@ -0,0 +1,51 @@
+UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE
+
+See Terms of Use <https://www.unicode.org/copyright.html>
+for definitions of Unicode Inc.’s Data Files and Software.
+
+NOTICE TO USER: Carefully read the following legal agreement.
+BY DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S
+DATA FILES ("DATA FILES"), AND/OR SOFTWARE ("SOFTWARE"),
+YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
+TERMS AND CONDITIONS OF THIS AGREEMENT.
+IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE
+THE DATA FILES OR SOFTWARE.
+
+COPYRIGHT AND PERMISSION NOTICE
+
+Copyright © 1991-2022 Unicode, Inc. All rights reserved.
+Distributed under the Terms of Use in https://www.unicode.org/copyright.html.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Unicode data files and any associated documentation
+(the "Data Files") or Unicode software and any associated documentation
+(the "Software") to deal in the Data Files or Software
+without restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, and/or sell copies of
+the Data Files or Software, and to permit persons to whom the Data Files
+or Software are furnished to do so, provided that either
+(a) this copyright and permission notice appear with all copies
+of the Data Files or Software, or
+(b) this copyright and permission notice appear in associated
+Documentation.
+
+THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF
+ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF THIRD PARTY RIGHTS.
+IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS
+NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL
+DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THE DATA FILES OR SOFTWARE.
+
+Except as contained in this notice, the name of a copyright holder
+shall not be used in advertising or otherwise to promote the sale,
+use or other dealings in these Data Files or Software without prior
+written authorization of the copyright holder.
+
+—
+
+Portions of ICU4X may have been adapted from ICU4C and/or ICU4J.
+ICU 1.8.1 to ICU 57.1 © 1995-2016 International Business Machines Corporation and others.
diff --git a/vendor/icu_list/README.md b/vendor/icu_list/README.md
new file mode 100644
index 000000000..d17e8a8d7
--- /dev/null
+++ b/vendor/icu_list/README.md
@@ -0,0 +1,69 @@
+# icu_list [![crates.io](https://img.shields.io/crates/v/icu_list)](https://crates.io/crates/icu_list)
+
+Formatting lists in a locale-sensitive way.
+
+This module is published as its own crate ([`icu_list`](https://docs.rs/icu_list/latest/icu_list/))
+and as part of the [`icu`](https://docs.rs/icu/latest/icu/) crate. See the latter for more details on the ICU4X project.
+
+## Examples
+
+### Formatting *and* lists in Spanish
+
+```rust
+#
+let list_formatter = ListFormatter::try_new_and_with_length_unstable(
+ &icu_testdata::unstable(),
+ &locale!("es").into(),
+ ListLength::Wide,
+)
+.expect("Data should load successfully");
+
+assert_writeable_eq!(
+ list_formatter.format(["España", "Suiza"].iter()),
+ "España y Suiza",
+);
+
+// The Spanish 'y' sometimes becomes an 'e':
+assert_writeable_eq!(
+ list_formatter.format(["España", "Suiza", "Italia"].iter()),
+ "España, Suiza e Italia",
+);
+```
+
+### Formatting *or* lists in Thai
+
+```rust
+#
+let list_formatter = ListFormatter::try_new_or_with_length_unstable(
+ &icu_testdata::unstable(),
+ &locale!("th").into(),
+ ListLength::Short,
+)
+.expect("Data should load successfully");
+
+// We can use any Writeables as inputs
+assert_writeable_eq!(list_formatter.format(1..=3), "1, 2 หรือ 3",);
+```
+
+### Formatting unit lists in English
+
+```rust
+#
+let list_formatter = ListFormatter::try_new_unit_with_length_unstable(
+ &icu_testdata::unstable(),
+ &locale!("en").into(),
+ ListLength::Wide,
+)
+.expect("Data should load successfully");
+
+assert_writeable_eq!(
+ list_formatter.format(["1ft", "2in"].iter()),
+ "1ft, 2in",
+);
+```
+Note: this last example is not fully internationalized. See [icu4x/2192](https://github.com/unicode-org/icu4x/issues/2192)
+for full unit handling.
+
+## More Information
+
+For more information on development, authorship, contributing etc. please visit [`ICU4X home page`](https://github.com/unicode-org/icu4x).
diff --git a/vendor/icu_list/examples/and_list.rs b/vendor/icu_list/examples/and_list.rs
new file mode 100644
index 000000000..9d869d9fb
--- /dev/null
+++ b/vendor/icu_list/examples/and_list.rs
@@ -0,0 +1,29 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+#![no_main] // https://github.com/unicode-org/icu4x/issues/395
+
+icu_benchmark_macros::static_setup!();
+
+use icu_list::{ListFormatter, ListLength};
+use icu_locid::locale;
+
+#[no_mangle]
+fn main(_argc: isize, _argv: *const *const u8) -> isize {
+ icu_benchmark_macros::main_setup!();
+
+ let list_formatter = ListFormatter::try_new_and_with_length_unstable(
+ &icu_testdata::unstable(),
+ &locale!("es").into(),
+ ListLength::Wide,
+ )
+ .unwrap();
+
+ println!(
+ "{}",
+ list_formatter.format(["España", "Francia", "Suiza", "Italia"].iter())
+ );
+
+ 0
+}
diff --git a/vendor/icu_list/src/error.rs b/vendor/icu_list/src/error.rs
new file mode 100644
index 000000000..d8622b03a
--- /dev/null
+++ b/vendor/icu_list/src/error.rs
@@ -0,0 +1,27 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+use core::fmt::Debug;
+use displaydoc::Display;
+use icu_provider::prelude::DataError;
+
+#[cfg(feature = "std")]
+impl std::error::Error for ListError {}
+
+/// A list of error outcomes for various operations in the `icu_timezone` crate.
+///
+/// Re-exported as [`Error`](crate::Error).
+#[derive(Display, Debug, Copy, Clone, PartialEq)]
+#[non_exhaustive]
+pub enum ListError {
+ /// An error originating inside of the [data provider](icu_provider).
+ #[displaydoc("{0}")]
+ Data(DataError),
+}
+
+impl From<DataError> for ListError {
+ fn from(e: DataError) -> Self {
+ Self::Data(e)
+ }
+}
diff --git a/vendor/icu_list/src/lib.rs b/vendor/icu_list/src/lib.rs
new file mode 100644
index 000000000..18f2156a6
--- /dev/null
+++ b/vendor/icu_list/src/lib.rs
@@ -0,0 +1,122 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+//! Formatting lists in a locale-sensitive way.
+//!
+//! This module is published as its own crate ([`icu_list`](https://docs.rs/icu_list/latest/icu_list/))
+//! and as part of the [`icu`](https://docs.rs/icu/latest/icu/) crate. See the latter for more details on the ICU4X project.
+//!
+//! # Examples
+//!
+//! ## Formatting *and* lists in Spanish
+//!
+//! ```
+//! # use icu::list::{ListFormatter, ListLength};
+//! # use icu::locid::locale;
+//! # use writeable::*;
+//! #
+//! let list_formatter = ListFormatter::try_new_and_with_length_unstable(
+//! &icu_testdata::unstable(),
+//! &locale!("es").into(),
+//! ListLength::Wide,
+//! )
+//! .expect("Data should load successfully");
+//!
+//! assert_writeable_eq!(
+//! list_formatter.format(["España", "Suiza"].iter()),
+//! "España y Suiza",
+//! );
+//!
+//! // The Spanish 'y' sometimes becomes an 'e':
+//! assert_writeable_eq!(
+//! list_formatter.format(["España", "Suiza", "Italia"].iter()),
+//! "España, Suiza e Italia",
+//! );
+//! ```
+//!
+//! ## Formatting *or* lists in Thai
+//!
+//! ```
+//! # use icu::list::{ListFormatter, ListLength};
+//! # use icu::locid::locale;
+//! # use writeable::*;
+//! #
+//! let list_formatter = ListFormatter::try_new_or_with_length_unstable(
+//! &icu_testdata::unstable(),
+//! &locale!("th").into(),
+//! ListLength::Short,
+//! )
+//! .expect("Data should load successfully");
+//!
+//! // We can use any Writeables as inputs
+//! assert_writeable_eq!(list_formatter.format(1..=3), "1, 2 หรือ 3",);
+//! ```
+//!
+//! ## Formatting unit lists in English
+//!
+//! ```
+//! # use icu::list::{ListFormatter, ListLength};
+//! # use icu::locid::locale;
+//! # use writeable::*;
+//! #
+//! let list_formatter = ListFormatter::try_new_unit_with_length_unstable(
+//! &icu_testdata::unstable(),
+//! &locale!("en").into(),
+//! ListLength::Wide,
+//! )
+//! .expect("Data should load successfully");
+//!
+//! assert_writeable_eq!(
+//! list_formatter.format(["1ft", "2in"].iter()),
+//! "1ft, 2in",
+//! );
+//! ```
+//! Note: this last example is not fully internationalized. See [icu4x/2192](https://github.com/unicode-org/icu4x/issues/2192)
+//! for full unit handling.
+
+#![cfg_attr(not(feature = "std"), no_std)]
+#![cfg_attr(
+ not(test),
+ deny(
+ clippy::indexing_slicing,
+ clippy::unwrap_used,
+ clippy::expect_used,
+ clippy::panic,
+ clippy::exhaustive_structs,
+ clippy::exhaustive_enums,
+ // TODO(#2266): enable missing_debug_implementations,
+ )
+)]
+#![warn(missing_docs)]
+
+extern crate alloc;
+
+mod error;
+mod list_formatter;
+mod string_matcher;
+
+pub mod provider;
+
+pub use list_formatter::*;
+
+pub use error::ListError;
+
+#[doc(inline)]
+pub use ListError as Error;
+
+/// Represents the style of a list. See the
+/// [CLDR spec](https://unicode.org/reports/tr35/tr35-general.html#ListPatterns)
+/// for an explanation of the different styles.
+#[derive(Copy, Clone, PartialEq, Debug)]
+#[non_exhaustive]
+pub enum ListLength {
+ /// A typical list
+ Wide,
+ /// A shorter list
+ Short,
+ /// The shortest type of list
+ Narrow,
+ // *Important*: When adding a variant here, make sure the code in
+ // ListFormatterPatterns::{start, middle, end, pair} stays panic-free!
+}
diff --git a/vendor/icu_list/src/list_formatter.rs b/vendor/icu_list/src/list_formatter.rs
new file mode 100644
index 000000000..36f5fbb7b
--- /dev/null
+++ b/vendor/icu_list/src/list_formatter.rs
@@ -0,0 +1,319 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+use crate::provider::{AndListV1Marker, ErasedListV1Marker, OrListV1Marker, UnitListV1Marker};
+use crate::ListError;
+use crate::ListLength;
+use core::fmt::{self, Write};
+use icu_provider::prelude::*;
+use writeable::*;
+
+/// A formatter that renders sequences of items in an i18n-friendly way. See the
+/// [crate-level documentation](crate) for more details.
+pub struct ListFormatter {
+ data: DataPayload<ErasedListV1Marker>,
+ length: ListLength,
+}
+
+macro_rules! constructor {
+ ($name: ident, $name_any: ident, $name_buffer: ident, $marker: ty, $doc: literal) => {
+ #[doc = concat!("Creates a new [`ListFormatter`] that produces a ", $doc, "-type list.\n\nSee the [CLDR spec]",
+ "(https://unicode.org/reports/tr35/tr35-general.html#ListPatterns) for an explanation of the different types.\n\n",
+ "[📚 Help choosing a constructor](icu_provider::constructors)\n\n",
+ "<div class=\"stab unstable\">⚠️ The bounds on this function may change over time, including in SemVer minor releases.</div>")]
+ pub fn $name<D: DataProvider<$marker> + ?Sized>(
+ data_provider: &D,
+ locale: &DataLocale,
+ length: ListLength,
+ ) -> Result<Self, ListError> {
+ let data = data_provider
+ .load(DataRequest {
+ locale,
+ metadata: Default::default(),
+ })?
+ .take_payload()?.cast();
+ Ok(Self { data, length })
+ }
+ icu_provider::gen_any_buffer_constructors!(
+ locale: include,
+ style: ListLength,
+ error: ListError,
+ functions: [
+ Self::$name,
+ $name_any,
+ $name_buffer
+ ]
+ );
+ };
+}
+
+impl ListFormatter {
+ constructor!(
+ try_new_and_with_length_unstable,
+ try_new_and_with_length_with_any_provider,
+ try_new_and_with_length_with_buffer_provider,
+ AndListV1Marker,
+ "and"
+ );
+ constructor!(
+ try_new_or_with_length_unstable,
+ try_new_or_with_length_with_any_provider,
+ try_new_or_with_length_with_buffer_provider,
+ OrListV1Marker,
+ "or"
+ );
+ constructor!(
+ try_new_unit_with_length_unstable,
+ try_new_unit_with_length_with_any_provider,
+ try_new_unit_with_length_with_buffer_provider,
+ UnitListV1Marker,
+ "unit"
+ );
+
+ /// Returns a [`Writeable`] composed of the input [`Writeable`]s and the language-dependent
+ /// formatting. The first layer of parts contains [`parts::ELEMENT`] for input
+ /// elements, and [`parts::LITERAL`] for list literals.
+ pub fn format<'a, W: Writeable + 'a, I: Iterator<Item = W> + Clone + 'a>(
+ &'a self,
+ values: I,
+ ) -> FormattedList<'a, W, I> {
+ FormattedList {
+ formatter: self,
+ values,
+ }
+ }
+
+ /// Returns a [`String`] composed of the input [`Writeable`]s and the language-dependent
+ /// formatting.
+ pub fn format_to_string<W: Writeable, I: Iterator<Item = W> + Clone>(
+ &self,
+ values: I,
+ ) -> alloc::string::String {
+ self.format(values).write_to_string().into_owned()
+ }
+}
+
+/// The [`Part`]s used by [`ListFormatter`].
+pub mod parts {
+ use writeable::Part;
+
+ /// The [`Part`] used by [`FormattedList`](super::FormattedList) to mark the part of the string that is an element.
+ pub const ELEMENT: Part = Part {
+ category: "list",
+ value: "element",
+ };
+
+ /// The [`Part`] used by [`FormattedList`](super::FormattedList) to mark the part of the string that is a list literal,
+ /// such as ", " or " and ".
+ pub const LITERAL: Part = Part {
+ category: "list",
+ value: "literal",
+ };
+}
+
+/// The [`Writeable`] implementation that is returned by [`ListFormatter::format`]. See
+/// the [`writeable`] crate for how to consume this.
+pub struct FormattedList<'a, W: Writeable + 'a, I: Iterator<Item = W> + Clone + 'a> {
+ formatter: &'a ListFormatter,
+ values: I,
+}
+
+impl<'a, W: Writeable + 'a, I: Iterator<Item = W> + Clone + 'a> Writeable
+ for FormattedList<'a, W, I>
+{
+ fn write_to_parts<V: PartsWrite + ?Sized>(&self, sink: &mut V) -> fmt::Result {
+ macro_rules! literal {
+ ($lit:ident) => {
+ sink.with_part(parts::LITERAL, |l| l.write_str($lit))
+ };
+ }
+ macro_rules! value {
+ ($val:expr) => {
+ sink.with_part(parts::ELEMENT, |e| $val.write_to_parts(e))
+ };
+ }
+
+ let mut values = self.values.clone();
+
+ if let Some(first) = values.next() {
+ if let Some(second) = values.next() {
+ if let Some(third) = values.next() {
+ // Start(values[0], middle(..., middle(values[n-3], End(values[n-2], values[n-1]))...)) =
+ // start_before + values[0] + start_between + (values[1..n-3] + middle_between)* +
+ // values[n-2] + end_between + values[n-1] + end_after
+
+ let (start_before, start_between, _) = self
+ .formatter
+ .data
+ .get()
+ .start(self.formatter.length)
+ .parts(&second);
+
+ literal!(start_before)?;
+ value!(first)?;
+ literal!(start_between)?;
+ value!(second)?;
+
+ let mut next = third;
+
+ for next_next in values {
+ let (_, between, _) = self
+ .formatter
+ .data
+ .get()
+ .middle(self.formatter.length)
+ .parts(&next);
+ literal!(between)?;
+ value!(next)?;
+ next = next_next;
+ }
+
+ let (_, end_between, end_after) = self
+ .formatter
+ .data
+ .get()
+ .end(self.formatter.length)
+ .parts(&next);
+ literal!(end_between)?;
+ value!(next)?;
+ literal!(end_after)
+ } else {
+ // Pair(values[0], values[1]) = pair_before + values[0] + pair_between + values[1] + pair_after
+ let (before, between, after) = self
+ .formatter
+ .data
+ .get()
+ .pair(self.formatter.length)
+ .parts(&second);
+ literal!(before)?;
+ value!(first)?;
+ literal!(between)?;
+ value!(second)?;
+ literal!(after)
+ }
+ } else {
+ value!(first)
+ }
+ } else {
+ Ok(())
+ }
+ }
+
+ fn writeable_length_hint(&self) -> LengthHint {
+ let mut count = 0;
+ let item_length = self
+ .values
+ .clone()
+ .map(|w| {
+ count += 1;
+ w.writeable_length_hint()
+ })
+ .sum::<LengthHint>();
+ item_length
+ + self
+ .formatter
+ .data
+ .get()
+ .size_hint(self.formatter.length, count)
+ }
+}
+
+impl<'a, W: Writeable + 'a, I: Iterator<Item = W> + Clone + 'a> core::fmt::Display
+ for FormattedList<'a, W, I>
+{
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ self.write_to(f)
+ }
+}
+
+#[cfg(all(test, feature = "datagen"))]
+mod tests {
+ use super::*;
+ use writeable::{assert_writeable_eq, assert_writeable_parts_eq};
+
+ fn formatter(length: ListLength) -> ListFormatter {
+ ListFormatter {
+ data: DataPayload::from_owned(crate::provider::test::test_patterns()),
+ length,
+ }
+ }
+
+ #[test]
+ fn test_slices() {
+ let formatter = formatter(ListLength::Wide);
+ let values = ["one", "two", "three", "four", "five"];
+
+ assert_writeable_eq!(formatter.format(values[0..0].iter()), "");
+ assert_writeable_eq!(formatter.format(values[0..1].iter()), "one");
+ assert_writeable_eq!(formatter.format(values[0..2].iter()), "$one;two+");
+ assert_writeable_eq!(formatter.format(values[0..3].iter()), "@one:two.three!");
+ assert_writeable_eq!(
+ formatter.format(values[0..4].iter()),
+ "@one:two,three.four!"
+ );
+
+ assert_writeable_parts_eq!(
+ formatter.format(values.iter()),
+ "@one:two,three,four.five!",
+ [
+ (0, 1, parts::LITERAL),
+ (1, 4, parts::ELEMENT),
+ (4, 5, parts::LITERAL),
+ (5, 8, parts::ELEMENT),
+ (8, 9, parts::LITERAL),
+ (9, 14, parts::ELEMENT),
+ (14, 15, parts::LITERAL),
+ (15, 19, parts::ELEMENT),
+ (19, 20, parts::LITERAL),
+ (20, 24, parts::ELEMENT),
+ (24, 25, parts::LITERAL)
+ ]
+ );
+ }
+
+ #[test]
+ fn test_into_iterator() {
+ let formatter = formatter(ListLength::Wide);
+
+ let mut vecdeque = std::collections::vec_deque::VecDeque::<u8>::new();
+ vecdeque.push_back(10);
+ vecdeque.push_front(48);
+
+ assert_writeable_parts_eq!(
+ formatter.format(vecdeque.iter()),
+ "$48;10+",
+ [
+ (0, 1, parts::LITERAL),
+ (1, 3, parts::ELEMENT),
+ (3, 4, parts::LITERAL),
+ (4, 6, parts::ELEMENT),
+ (6, 7, parts::LITERAL),
+ ]
+ );
+ }
+
+ #[test]
+ fn test_iterator() {
+ let formatter = formatter(ListLength::Wide);
+
+ assert_writeable_parts_eq!(
+ formatter.format(core::iter::repeat(5).take(2)),
+ "$5;5+",
+ [
+ (0, 1, parts::LITERAL),
+ (1, 2, parts::ELEMENT),
+ (2, 3, parts::LITERAL),
+ (3, 4, parts::ELEMENT),
+ (4, 5, parts::LITERAL),
+ ]
+ );
+ }
+
+ #[test]
+ fn test_conditional() {
+ let formatter = formatter(ListLength::Narrow);
+
+ assert_writeable_eq!(formatter.format(["Beta", "Alpha"].iter()), "Beta :o Alpha");
+ }
+}
diff --git a/vendor/icu_list/src/provider.rs b/vendor/icu_list/src/provider.rs
new file mode 100644
index 000000000..27f3e4fec
--- /dev/null
+++ b/vendor/icu_list/src/provider.rs
@@ -0,0 +1,465 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+// Provider structs must be stable
+#![allow(clippy::exhaustive_structs, clippy::exhaustive_enums)]
+
+//! Data provider struct definitions for this ICU4X component.
+//!
+//! Read more about data providers: [`icu_provider`]
+
+use crate::ListLength;
+use alloc::borrow::Cow;
+use icu_provider::DataMarker;
+use icu_provider::{yoke, zerofrom};
+use writeable::{LengthHint, Writeable};
+
+pub use crate::string_matcher::StringMatcher;
+
+/// Symbols and metadata required for [`ListFormatter`](crate::ListFormatter).
+#[icu_provider::data_struct(
+ AndListV1Marker = "list/and@1",
+ OrListV1Marker = "list/or@1",
+ UnitListV1Marker = "list/unit@1"
+)]
+#[derive(Clone, Debug)]
+#[cfg_attr(
+ feature = "datagen",
+ derive(serde::Serialize, databake::Bake),
+ databake(path = icu_list::provider),
+)]
+pub struct ListFormatterPatternsV1<'data>(
+ #[cfg_attr(feature = "datagen", serde(with = "deduplicating_array"))]
+ /// The patterns in the order start, middle, end, pair, short_start, short_middle,
+ /// short_end, short_pair, narrow_start, narrow_middle, narrow_end, narrow_pair,
+ pub [ConditionalListJoinerPattern<'data>; 12],
+);
+
+#[cfg(feature = "serde")]
+impl<'de> serde::Deserialize<'de> for ListFormatterPatternsV1<'de> {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::de::Deserializer<'de>,
+ {
+ #[cfg(not(feature = "serde_human"))]
+ if deserializer.is_human_readable() {
+ use serde::de::Error;
+ return Err(D::Error::custom(
+ "Deserializing human-readable ListFormatter data requires the 'serde_human' feature",
+ ));
+ }
+
+ Ok(ListFormatterPatternsV1(deduplicating_array::deserialize(
+ deserializer,
+ )?))
+ }
+}
+
+pub(crate) struct ErasedListV1Marker;
+
+impl DataMarker for ErasedListV1Marker {
+ type Yokeable = ListFormatterPatternsV1<'static>;
+}
+
+impl<'data> ListFormatterPatternsV1<'data> {
+ pub(crate) fn start(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
+ #![allow(clippy::indexing_slicing)] // style as usize < 3
+ &self.0[4 * (style as usize)]
+ }
+
+ pub(crate) fn middle(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
+ #![allow(clippy::indexing_slicing)] // style as usize < 3
+ &self.0[4 * (style as usize) + 1]
+ }
+
+ pub(crate) fn end(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
+ #![allow(clippy::indexing_slicing)] // style as usize < 3
+ &self.0[4 * (style as usize) + 2]
+ }
+
+ pub(crate) fn pair(&self, style: ListLength) -> &ConditionalListJoinerPattern<'data> {
+ #![allow(clippy::indexing_slicing)] // style as usize < 3
+ &self.0[4 * (style as usize) + 3]
+ }
+
+ /// The range of the number of bytes required by the list literals to join a
+ /// list of length `len`. If none of the patterns are conditional, this is exact.
+ pub(crate) fn size_hint(&self, style: ListLength, len: usize) -> LengthHint {
+ match len {
+ 0 | 1 => LengthHint::exact(0),
+ 2 => self.pair(style).size_hint(),
+ n => {
+ self.start(style).size_hint()
+ + self.middle(style).size_hint() * (n - 3)
+ + self.end(style).size_hint()
+ }
+ }
+ }
+}
+
+/// A pattern that can behave conditionally on the next element.
+#[derive(Clone, Debug, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)]
+#[cfg_attr(
+ feature = "datagen",
+ derive(serde::Serialize, databake::Bake),
+ databake(path = icu_list::provider),
+)]
+#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
+pub struct ConditionalListJoinerPattern<'data> {
+ /// The default pattern
+ #[cfg_attr(feature = "serde", serde(borrow))]
+ pub default: ListJoinerPattern<'data>,
+ /// And optional special case
+ #[cfg_attr(feature = "serde", serde(borrow))]
+ pub special_case: Option<SpecialCasePattern<'data>>,
+}
+
+/// The special case of a [`ConditionalListJoinerPattern`]
+#[derive(Clone, Debug, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)]
+#[cfg_attr(
+ feature = "datagen",
+ derive(serde::Serialize, databake::Bake),
+ databake(path = icu_list::provider),
+)]
+#[cfg_attr(feature = "serde", derive(serde::Deserialize))]
+pub struct SpecialCasePattern<'data> {
+ /// The condition on the following element
+ #[cfg_attr(feature = "serde", serde(borrow))]
+ pub condition: StringMatcher<'data>,
+ /// The pattern if the condition matches
+ #[cfg_attr(feature = "serde", serde(borrow))]
+ pub pattern: ListJoinerPattern<'data>,
+}
+
+/// A pattern containing two numeric placeholders ("{0}, and {1}.")
+#[derive(Clone, Debug, PartialEq, yoke::Yokeable, zerofrom::ZeroFrom)]
+#[cfg_attr(feature = "datagen", derive(serde::Serialize))]
+pub struct ListJoinerPattern<'data> {
+ /// The pattern string without the placeholders
+ string: Cow<'data, str>,
+ /// The index of the first placeholder. Always <= index_1.
+ // Always 0 for CLDR data, so we don't need to serialize it.
+ // In-memory we have free space for it as index_1 doesn't
+ // fill a word.
+ #[cfg_attr(feature = "datagen", serde(skip))]
+ index_0: u8,
+ /// The index of the second placeholder. Always < string.len().
+ index_1: u8,
+}
+
+#[cfg(feature = "serde")]
+impl<'de: 'data, 'data> serde::Deserialize<'de> for ListJoinerPattern<'data> {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::Deserializer<'de>,
+ {
+ #[derive(serde::Deserialize)]
+ struct Dummy<'data> {
+ #[cfg_attr(feature = "serde", serde(borrow))]
+ string: Cow<'data, str>,
+ index_1: u8,
+ }
+ let Dummy { string, index_1 } = Dummy::deserialize(deserializer)?;
+
+ if index_1 as usize > string.len() {
+ use serde::de::Error;
+ Err(D::Error::custom("invalid index_1"))
+ } else {
+ Ok(ListJoinerPattern {
+ string,
+ index_0: 0,
+ index_1,
+ })
+ }
+ }
+}
+
+impl<'a> ListJoinerPattern<'a> {
+ /// Constructs a [`ListJoinerPattern`] from raw parts. Used by databake.
+ ///
+ /// # Safety
+ /// index_1 may be at most string.len()
+ pub const unsafe fn from_parts_unchecked(string: &'a str, index_1: u8) -> Self {
+ Self {
+ string: Cow::Borrowed(string),
+ index_0: 0,
+ index_1,
+ }
+ }
+}
+
+pub(crate) type PatternParts<'a> = (&'a str, &'a str, &'a str);
+
+impl<'a> ConditionalListJoinerPattern<'a> {
+ pub(crate) fn parts<'b, W: Writeable + ?Sized>(
+ &'a self,
+ following_value: &'b W,
+ ) -> PatternParts<'a> {
+ match &self.special_case {
+ Some(SpecialCasePattern { condition, pattern })
+ // TODO: Implement lookahead instead of materializing here.
+ if condition.test(&*following_value.write_to_string()) =>
+ {
+ pattern.borrow_tuple()
+ }
+ _ => self.default.borrow_tuple(),
+ }
+ }
+
+ /// The expected length of this pattern
+ pub fn size_hint(&'a self) -> LengthHint {
+ let mut hint = self.default.size_hint();
+ if let Some(special_case) = &self.special_case {
+ hint |= special_case.pattern.size_hint()
+ }
+ hint
+ }
+}
+
+impl<'data> ListJoinerPattern<'data> {
+ fn borrow_tuple(&'data self) -> PatternParts<'data> {
+ #![allow(clippy::indexing_slicing)] // by invariant
+ let index_0 = self.index_0 as usize;
+ let index_1 = self.index_1 as usize;
+ (
+ &self.string[0..index_0],
+ &self.string[index_0..index_1],
+ &self.string[index_1..],
+ )
+ }
+
+ fn size_hint(&self) -> LengthHint {
+ LengthHint::exact(self.string.len())
+ }
+}
+
+#[cfg(feature = "datagen")]
+mod datagen {
+ #![allow(clippy::indexing_slicing)] // datagen
+
+ use super::*;
+ use icu_provider::DataError;
+
+ impl<'data> ListFormatterPatternsV1<'data> {
+ /// The patterns in the order start, middle, end, pair, short_start, short_middle,
+ /// short_end, short_pair, narrow_start, narrow_middle, narrow_end, narrow_pair,
+ pub fn try_new(patterns: [&str; 12]) -> Result<Self, DataError> {
+ Ok(Self([
+ ListJoinerPattern::from_str(patterns[0], true, false)?.into(),
+ ListJoinerPattern::from_str(patterns[1], false, false)?.into(),
+ ListJoinerPattern::from_str(patterns[2], false, true)?.into(),
+ ListJoinerPattern::from_str(patterns[3], true, true)?.into(),
+ ListJoinerPattern::from_str(patterns[4], true, false)?.into(),
+ ListJoinerPattern::from_str(patterns[5], false, false)?.into(),
+ ListJoinerPattern::from_str(patterns[6], false, true)?.into(),
+ ListJoinerPattern::from_str(patterns[7], true, true)?.into(),
+ ListJoinerPattern::from_str(patterns[8], true, false)?.into(),
+ ListJoinerPattern::from_str(patterns[9], false, false)?.into(),
+ ListJoinerPattern::from_str(patterns[10], false, true)?.into(),
+ ListJoinerPattern::from_str(patterns[11], true, true)?.into(),
+ ]))
+ }
+
+ /// Adds a special case to all `pattern`s that will evaluate to
+ /// `alternative_pattern` when `regex` matches the following element.
+ /// The regex is interpreted case-insensitive and anchored to the beginning, but
+ /// to improve efficiency does not search for full matches. If a full match is
+ /// required, use `$`.
+ pub fn make_conditional(
+ &mut self,
+ pattern: &str,
+ regex: &StringMatcher<'static>,
+ alternative_pattern: &str,
+ ) -> Result<(), DataError> {
+ let old = ListJoinerPattern::from_str(pattern, true, true)?;
+ for i in 0..12 {
+ if self.0[i].default == old {
+ self.0[i].special_case = Some(SpecialCasePattern {
+ condition: regex.clone(),
+ pattern: ListJoinerPattern::from_str(
+ alternative_pattern,
+ i % 4 == 0 || i % 4 == 3, // allow_prefix = start or pair
+ i % 4 == 2 || i % 4 == 3, // allow_suffix = end or pair
+ )?,
+ });
+ }
+ }
+ Ok(())
+ }
+ }
+
+ impl<'data> ListJoinerPattern<'data> {
+ /// Construct the pattern from a CLDR pattern string
+ pub fn from_str(
+ pattern: &str,
+ allow_prefix: bool,
+ allow_suffix: bool,
+ ) -> Result<Self, DataError> {
+ match (pattern.find("{0}"), pattern.find("{1}")) {
+ (Some(index_0), Some(index_1))
+ if index_0 < index_1
+ && (allow_prefix || index_0 == 0)
+ && (allow_suffix || index_1 == pattern.len() - 3) =>
+ {
+ if (index_0 > 0 && !cfg!(test)) || index_1 - 3 >= 256 {
+ return Err(DataError::custom(
+ "Found valid pattern that cannot be stored in ListFormatterPatternsV1",
+ )
+ .with_debug_context(pattern));
+ }
+ Ok(ListJoinerPattern {
+ string: Cow::Owned(alloc::format!(
+ "{}{}{}",
+ &pattern[0..index_0],
+ &pattern[index_0 + 3..index_1],
+ &pattern[index_1 + 3..]
+ )),
+ index_0: index_0 as u8,
+ index_1: (index_1 - 3) as u8,
+ })
+ }
+ _ => Err(DataError::custom("Invalid list pattern").with_debug_context(pattern)),
+ }
+ }
+ }
+
+ impl<'data> From<ListJoinerPattern<'data>> for ConditionalListJoinerPattern<'data> {
+ fn from(default: ListJoinerPattern<'data>) -> Self {
+ Self {
+ default,
+ special_case: None,
+ }
+ }
+ }
+
+ impl databake::Bake for ListJoinerPattern<'_> {
+ fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
+ env.insert("icu_list");
+ let string = (&*self.string).bake(env);
+ let index_1 = self.index_1.bake(env);
+ // Safe because our own data is safe
+ databake::quote! { unsafe {
+ ::icu_list::provider::ListJoinerPattern::from_parts_unchecked(#string, #index_1)
+ }}
+ }
+ }
+}
+
+#[cfg(all(test, feature = "datagen"))]
+pub(crate) mod test {
+ use super::*;
+
+ pub fn test_patterns() -> ListFormatterPatternsV1<'static> {
+ let mut patterns = ListFormatterPatternsV1::try_new([
+ // Wide: general
+ "@{0}:{1}",
+ "{0},{1}",
+ "{0}.{1}!",
+ "${0};{1}+",
+ // Short: different pattern lengths
+ "{0}1{1}",
+ "{0}12{1}",
+ "{0}12{1}34",
+ "{0}123{1}456",
+ // Narrow: conditionals
+ "{0}: {1}",
+ "{0}, {1}",
+ "{0}. {1}",
+ "{0}. {1}",
+ ])
+ .unwrap();
+ patterns
+ .make_conditional("{0}. {1}", &StringMatcher::new("A").unwrap(), "{0} :o {1}")
+ .unwrap();
+ patterns
+ }
+
+ #[test]
+ fn rejects_bad_patterns() {
+ assert!(ListJoinerPattern::from_str("{0} and", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("and {1}", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("{1} and {0}", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("{1{0}}", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("{0\u{202e}} and {1}", true, true).is_err());
+ assert!(ListJoinerPattern::from_str("{{0}} {{1}}", true, true).is_ok());
+
+ assert!(ListJoinerPattern::from_str("{0} and {1} ", true, true).is_ok());
+ assert!(ListJoinerPattern::from_str("{0} and {1} ", true, false).is_err());
+ assert!(ListJoinerPattern::from_str(" {0} and {1}", true, true).is_ok());
+ assert!(ListJoinerPattern::from_str(" {0} and {1}", false, true).is_err());
+ }
+
+ #[test]
+ fn produces_correct_parts() {
+ assert_eq!(
+ test_patterns().pair(ListLength::Wide).parts(""),
+ ("$", ";", "+")
+ );
+ }
+
+ #[test]
+ fn produces_correct_parts_conditionally() {
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("A"),
+ ("", " :o ", "")
+ );
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("a"),
+ ("", " :o ", "")
+ );
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("ab"),
+ ("", " :o ", "")
+ );
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("B"),
+ ("", ". ", "")
+ );
+ assert_eq!(
+ test_patterns().end(ListLength::Narrow).parts("BA"),
+ ("", ". ", "")
+ );
+ }
+
+ #[test]
+ fn size_hint_works() {
+ let pattern = test_patterns();
+
+ assert_eq!(
+ pattern.size_hint(ListLength::Short, 0),
+ LengthHint::exact(0)
+ );
+ assert_eq!(
+ pattern.size_hint(ListLength::Short, 1),
+ LengthHint::exact(0)
+ );
+
+ // pair pattern "{0}123{1}456"
+ assert_eq!(
+ pattern.size_hint(ListLength::Short, 2),
+ LengthHint::exact(6)
+ );
+
+ // patterns "{0}1{1}", "{0}12{1}" (x197), and "{0}12{1}34"
+ assert_eq!(
+ pattern.size_hint(ListLength::Short, 200),
+ LengthHint::exact(1 + 2 * 197 + 4)
+ );
+
+ // patterns "{0}: {1}", "{0}, {1}" (x197), and "{0} :o {1}" or "{0}. {1}"
+ assert_eq!(
+ pattern.size_hint(ListLength::Narrow, 200),
+ LengthHint::exact(2 + 197 * 2) + LengthHint::between(2, 4)
+ );
+ }
+
+ #[test]
+ fn databake() {
+ databake::test_bake!(
+ ListJoinerPattern,
+ const: unsafe { crate::provider::ListJoinerPattern::from_parts_unchecked(", ", 2u8) },
+ icu_list
+ );
+ }
+}
diff --git a/vendor/icu_list/src/string_matcher.rs b/vendor/icu_list/src/string_matcher.rs
new file mode 100644
index 000000000..ba4833605
--- /dev/null
+++ b/vendor/icu_list/src/string_matcher.rs
@@ -0,0 +1,213 @@
+// This file is part of ICU4X. For terms of use, please see the file
+// called LICENSE at the top level of the ICU4X source tree
+// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
+
+use alloc::borrow::Cow;
+#[cfg(any(feature = "serde_human", feature = "datagen"))]
+use alloc::string::ToString;
+use icu_provider::{yoke, zerofrom};
+use regex_automata::dfa::sparse::DFA;
+use regex_automata::dfa::Automaton;
+
+/// A precompiled regex
+#[derive(Clone, Debug, yoke::Yokeable, zerofrom::ZeroFrom)]
+#[allow(clippy::exhaustive_structs)] // not a public API
+pub struct StringMatcher<'data> {
+ // Safety: These always represent a valid DFA (DFA::from_bytes(dfa_bytes).is_ok())
+ dfa_bytes: Cow<'data, [u8]>,
+ pattern: Option<Cow<'data, str>>,
+}
+
+impl PartialEq for StringMatcher<'_> {
+ fn eq(&self, other: &Self) -> bool {
+ self.dfa_bytes == other.dfa_bytes
+ }
+}
+
+#[cfg(feature = "datagen")]
+impl databake::Bake for StringMatcher<'_> {
+ fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream {
+ env.insert("icu_list");
+ let bytes = (&&*self.dfa_bytes).bake(env);
+ // Safe because our own data is safe
+ databake::quote! {
+ unsafe { ::icu_list::provider::StringMatcher::from_dfa_bytes_unchecked(#bytes) }
+ }
+ }
+}
+
+#[cfg(feature = "datagen")]
+impl serde::Serialize for StringMatcher<'_> {
+ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+ where
+ S: serde::ser::Serializer,
+ {
+ if serializer.is_human_readable() {
+ self.pattern
+ .as_ref()
+ .map(|pattern| pattern.serialize(serializer))
+ .unwrap_or_else(|| {
+ use serde::ser::Error;
+ Err(S::Error::custom(
+ "cannot serialize a deserialized bincode StringMatcher to JSON",
+ ))
+ })
+ } else {
+ self.dfa_bytes.serialize(serializer)
+ }
+ }
+}
+
+#[cfg(feature = "serde")]
+impl<'de: 'data, 'data> serde::Deserialize<'de> for StringMatcher<'data> {
+ fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+ where
+ D: serde::de::Deserializer<'de>,
+ {
+ use icu_provider::serde::borrow_de_utils::CowBytesWrap;
+
+ #[cfg(feature = "serde_human")]
+ if deserializer.is_human_readable() {
+ use serde::de::Error;
+ return StringMatcher::new(<&str>::deserialize(deserializer)?)
+ .map_err(|e| D::Error::custom(e.to_string()));
+ }
+
+ if cfg!(target_endian = "big") {
+ // TODO: Convert LE to BE. For now we just behave like the
+ // accept-nothing DFA on BE systems.
+ return Ok(StringMatcher {
+ dfa_bytes: Cow::Borrowed(&[]),
+ pattern: None,
+ });
+ }
+
+ let dfa_bytes = <CowBytesWrap<'de>>::deserialize(deserializer)?.0;
+
+ // Verify safety invariant
+ DFA::from_bytes(&dfa_bytes).map_err(|e| {
+ use serde::de::Error;
+ D::Error::custom(alloc::format!("Invalid DFA bytes: {}", e))
+ })?;
+
+ Ok(StringMatcher {
+ dfa_bytes,
+ pattern: None,
+ })
+ }
+}
+
+impl<'data> StringMatcher<'data> {
+ /// Creates a `StringMatcher` from a serialized DFA. Used internally by databake.
+ ///
+ /// # Safety
+ ///
+ /// `dfa_bytes` has to be a valid DFA (regex_automata::dfa::sparse::DFA::from_bytes(dfa_bytes).is_ok())
+ pub const unsafe fn from_dfa_bytes_unchecked(dfa_bytes: &'data [u8]) -> Self {
+ Self {
+ dfa_bytes: Cow::Borrowed(dfa_bytes),
+ pattern: None,
+ }
+ }
+
+ /// Creates a `StringMatcher` from regex.
+ #[cfg(any(feature = "datagen", feature = "serde_human",))]
+ pub fn new(pattern: &str) -> Result<Self, icu_provider::DataError> {
+ use regex_automata::{
+ dfa::dense::{Builder, Config},
+ SyntaxConfig,
+ };
+
+ let mut builder = Builder::new();
+ let dfa = builder
+ .syntax(SyntaxConfig::new().case_insensitive(true))
+ .configure(Config::new().anchored(true).minimize(true))
+ .build(pattern)
+ .map_err(|_| {
+ icu_provider::DataError::custom("Cannot build DFA").with_display_context(&pattern)
+ })?
+ .to_sparse()
+ .map_err(|_| {
+ icu_provider::DataError::custom("Cannot sparsify DFA")
+ .with_display_context(&pattern)
+ })?;
+
+ Ok(Self {
+ dfa_bytes: dfa.to_bytes_little_endian().into(),
+ pattern: Some(pattern.to_string().into()),
+ })
+ }
+
+ #[allow(clippy::unwrap_used)] // by invariant
+ pub(crate) fn test(&self, string: &str) -> bool {
+ cfg!(target_endian = "little")
+ && matches!(
+ // Safe due to struct invariant.
+ unsafe { DFA::from_bytes_unchecked(&self.dfa_bytes).unwrap().0 }
+ .find_earliest_fwd(string.as_bytes()),
+ Ok(Some(_))
+ )
+ }
+}
+
+#[cfg(all(test, feature = "datagen"))]
+mod test {
+ use super::*;
+
+ #[test]
+ fn test_string_matcher() {
+ let matcher = StringMatcher::new("abc.*").unwrap();
+ assert!(!matcher.test("ab"));
+ assert!(matcher.test("abc"));
+ assert!(matcher.test("abcde"));
+ }
+
+ #[test]
+ fn test_postcard_serialization() {
+ let matcher = StringMatcher::new("abc*").unwrap();
+
+ let mut bytes = postcard::to_stdvec(&matcher).unwrap();
+ assert_eq!(
+ postcard::from_bytes::<StringMatcher>(&bytes).unwrap(),
+ matcher
+ );
+
+ // A corrupted byte leads to an error
+ bytes[17] ^= 255;
+ assert!(postcard::from_bytes::<StringMatcher>(&bytes).is_err());
+ bytes[17] ^= 255;
+
+ // An extra byte leads to an error
+ bytes.insert(123, 40);
+ assert!(postcard::from_bytes::<StringMatcher>(&bytes).is_err());
+ bytes.remove(123);
+
+ // Missing bytes lead to an error
+ assert!(postcard::from_bytes::<StringMatcher>(&bytes[0..bytes.len() - 5]).is_err());
+ }
+
+ #[test]
+ #[cfg(feature = "serde_human")]
+ fn test_json_serialization() {
+ let matcher = StringMatcher::new("abc*").unwrap();
+
+ let json = serde_json::to_string(&matcher).unwrap();
+ assert_eq!(
+ serde_json::from_str::<StringMatcher>(&json).unwrap(),
+ matcher
+ );
+ assert!(serde_json::from_str::<StringMatcher>(".*[").is_err());
+ }
+
+ #[test]
+ #[ignore] // https://github.com/rust-lang/rust/issues/98906
+ fn databake() {
+ databake::test_bake!(
+ StringMatcher,
+ const: unsafe {
+ crate::provider::StringMatcher::from_dfa_bytes_unchecked(&[49u8, 50u8, 51u8, ])
+ },
+ icu_list
+ );
+ }
+}