From ef24de24a82fe681581cc130f342363c47c0969a Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 7 Jun 2024 07:48:48 +0200 Subject: Merging upstream version 1.75.0+dfsg1. Signed-off-by: Daniel Baumann --- vendor/icu_provider_adapters/.cargo-checksum.json | 2 +- vendor/icu_provider_adapters/Cargo.toml | 33 +- vendor/icu_provider_adapters/LICENSE | 79 ++- vendor/icu_provider_adapters/README.md | 4 + .../icu_provider_adapters/src/fallback/adapter.rs | 284 ---------- .../src/fallback/algorithms.rs | 439 --------------- vendor/icu_provider_adapters/src/fallback/mod.rs | 624 +++++++++------------ .../icu_provider_adapters/src/fallback/provider.rs | 111 ---- vendor/icu_provider_adapters/src/filter/impls.rs | 4 +- vendor/icu_provider_adapters/src/filter/mod.rs | 2 +- vendor/icu_provider_adapters/src/fork/by_error.rs | 10 +- vendor/icu_provider_adapters/src/fork/macros.rs | 25 +- vendor/icu_provider_adapters/src/fork/mod.rs | 20 +- .../icu_provider_adapters/src/fork/predicates.rs | 7 + .../icu_provider_adapters/tests/data/blob.postcard | Bin 0 -> 5210 bytes .../icu_provider_adapters/tests/data/config.json | 21 + .../tests/data/langtest/de.json | 23 + .../tests/data/langtest/ro.json | 23 + 18 files changed, 410 insertions(+), 1301 deletions(-) delete mode 100644 vendor/icu_provider_adapters/src/fallback/adapter.rs delete mode 100644 vendor/icu_provider_adapters/src/fallback/algorithms.rs delete mode 100644 vendor/icu_provider_adapters/src/fallback/provider.rs create mode 100644 vendor/icu_provider_adapters/tests/data/blob.postcard create mode 100644 vendor/icu_provider_adapters/tests/data/config.json create mode 100644 vendor/icu_provider_adapters/tests/data/langtest/de.json create mode 100644 vendor/icu_provider_adapters/tests/data/langtest/ro.json (limited to 'vendor/icu_provider_adapters') diff --git a/vendor/icu_provider_adapters/.cargo-checksum.json b/vendor/icu_provider_adapters/.cargo-checksum.json index 7b2a6906a..833d0f9e7 100644 --- a/vendor/icu_provider_adapters/.cargo-checksum.json +++ b/vendor/icu_provider_adapters/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"bc35c9045058859105d040996e5f8f204a2337b832f1a23cf6f1d10fb1eb45ee","LICENSE":"4ad7541d66a407234e2c84902124cef325c29f3e966353efdb800bedb8b8da21","README.md":"e6a08c2bc307b66c93de20c2c366da896f7fd3f5e5eb402edd2eeba79476b600","src/any_payload.rs":"165d41d018a611a7ef25dab621bbd408e6ba22dde58365817944898de138be3e","src/either.rs":"02e646af7aa6d8af1a03e448bedb2498b026d418de8340a5be52b1d366ad9b6c","src/empty.rs":"1503b2f73b2a727a9e502ab7081da3261df470bc86b762ab5748c31fad8cfbc6","src/fallback/adapter.rs":"55188c9acb6ddc852b9218b14c97304e0378f9e40eedb0f0af41b5036a78e54f","src/fallback/algorithms.rs":"9409ad6f6f617d4433b9f6b303d131782877a0a10470533e3864b97355b9a3f1","src/fallback/mod.rs":"9a1ba8dcba21dbcb5acc4a019d640fffcfd2efd043bfa42a5690a9de593479d1","src/fallback/provider.rs":"ef8a835e3ed2b7871b6f6e78ae2e73575b26adc9e8e0b5a7170c8513e7fe3269","src/filter/impls.rs":"588918fdcadda3572844352bf22419910ee6430f3e5a6e7c5e012120ad2eb932","src/filter/mod.rs":"33a622b9684c5e445b2af8aec9cd3ba5dfe3b51d917dd2776b267657e6a5b72d","src/fork/by_error.rs":"450a24bfaa17e32899e4ba4286623b2b3b36af81fb5abd9b1e28a2af18c3b9dc","src/fork/macros.rs":"5aebb0134923fa9fa0fe7c16d2d85a1a29cf4ea49505187db56bf0bc8e984ad0","src/fork/mod.rs":"7378895128bf1ccc9de7f5675668ef922d3df7b84b04f68af4d5b49efe60341e","src/fork/predicates.rs":"314bf33144c6827cd3df05877d7c20fb64c9b18f6230e229340b8f04f4ccf4d3","src/helpers.rs":"0e5c8424c9e51956cd065d4ecf4f478bbc3978888b4bbb012ad3f5d6a7062fb1","src/lib.rs":"243ec29c6e5fbe59004f5774f1b252166b06a264e218a7209fe6ed83c25dd03a","tests/data/langtest/de/core/helloworld@1/de.json":"5a45b1d80567de8c4ff754f7dbe20c22477c1e00a9400b38397eb034f295b8f8","tests/data/langtest/de/manifest.json":"fa2f848cff051fd12a909389fbbc44b93ae1feb92cce466cc4381f9548443ea9","tests/data/langtest/ro/core/helloworld@1/ro.json":"b6b68292746dd6bb2d92d9c08e2753db556ec9c954a3b593b0b8999df550f298","tests/data/langtest/ro/manifest.json":"fa2f848cff051fd12a909389fbbc44b93ae1feb92cce466cc4381f9548443ea9"},"package":"f4ae1e2bd0c41728b77e7c46e9afdec5e2127d1eedacc684724667d50c126bd3"} \ No newline at end of file +{"files":{"Cargo.toml":"cc4c433c73faa394a0bd721e086c1dfcd238e4efd6540886632e4be4b62183df","LICENSE":"853f87c96f3d249f200fec6db1114427bc8bdf4afddc93c576956d78152ce978","README.md":"d91500cb944c05c04ed9e6920d139199a9d1892346de50dccbdce5cbef3b9174","src/any_payload.rs":"165d41d018a611a7ef25dab621bbd408e6ba22dde58365817944898de138be3e","src/either.rs":"02e646af7aa6d8af1a03e448bedb2498b026d418de8340a5be52b1d366ad9b6c","src/empty.rs":"1503b2f73b2a727a9e502ab7081da3261df470bc86b762ab5748c31fad8cfbc6","src/fallback/mod.rs":"7f0cfc915cb95d1681befc52ef51ecaec0c900043a15d3feba3e5a8cc23c39ff","src/filter/impls.rs":"17b6ba2c7c72b72a72fbc57f31eec0cbe52d631a87012f6604fb1bf2e9f9137d","src/filter/mod.rs":"896de77291b093886a210dcbb30498aef2c9afe4ce984bd2ac517323e96917b4","src/fork/by_error.rs":"d7fee843306ab8b6e5de2abea8efb4409d01e2faf15fcb2ab4f6ba3cb0f47a09","src/fork/macros.rs":"9e8c071d7c21b93b4d07672542ec994d2fde2c19f14dd30f5c969215c73ebda7","src/fork/mod.rs":"64502e4d8a667e1ec5aa8339e07c1f2e5b0021e6ee4ca06722f6a1793f0e2b0d","src/fork/predicates.rs":"1191f9ff1ae2196255effb50e245a3f80c2a4429ea3e46499f0284835a51c1c9","src/helpers.rs":"0e5c8424c9e51956cd065d4ecf4f478bbc3978888b4bbb012ad3f5d6a7062fb1","src/lib.rs":"243ec29c6e5fbe59004f5774f1b252166b06a264e218a7209fe6ed83c25dd03a","tests/data/blob.postcard":"ae4478ddd635aa0f816d2abae9057dc9df0d9963e6b78b1b8e8722b318a513c5","tests/data/config.json":"0ec2a3ec6338767cee5e9bd1c27dceafcc10c28b5e0380059b7faf2f0cf707b7","tests/data/langtest/de.json":"6016405e1d9c63c2df940953fc3ae064b1fc4c0e3676ed78fafe4ec84596dfa3","tests/data/langtest/de/core/helloworld@1/de.json":"5a45b1d80567de8c4ff754f7dbe20c22477c1e00a9400b38397eb034f295b8f8","tests/data/langtest/de/manifest.json":"fa2f848cff051fd12a909389fbbc44b93ae1feb92cce466cc4381f9548443ea9","tests/data/langtest/ro.json":"c6ba5912f3ef51357c2d92596cd13b78080aee257132395d900ba4c76450c9ca","tests/data/langtest/ro/core/helloworld@1/ro.json":"b6b68292746dd6bb2d92d9c08e2753db556ec9c954a3b593b0b8999df550f298","tests/data/langtest/ro/manifest.json":"fa2f848cff051fd12a909389fbbc44b93ae1feb92cce466cc4381f9548443ea9"},"package":"36b380ef2d3d93b015cd0563d7e0d005cc07f82a5503716dbc191798d0079e1d"} \ No newline at end of file diff --git a/vendor/icu_provider_adapters/Cargo.toml b/vendor/icu_provider_adapters/Cargo.toml index 291a17ffc..72f4592a7 100644 --- a/vendor/icu_provider_adapters/Cargo.toml +++ b/vendor/icu_provider_adapters/Cargo.toml @@ -11,10 +11,12 @@ [package] edition = "2021" +rust-version = "1.66" name = "icu_provider_adapters" -version = "1.2.0" +version = "1.3.2" authors = ["The ICU4X Project Developers"] include = [ + "data/**/*", "src/**/*", "examples/**/*", "benches/**/*", @@ -24,23 +26,31 @@ include = [ "README.md", ] description = "Adapters for composing and manipulating data providers." +homepage = "https://icu4x.unicode.org" readme = "README.md" categories = ["internationalization"] -license = "Unicode-DFS-2016" +license-file = "LICENSE" repository = "https://github.com/unicode-org/icu4x" [dependencies.databake] -version = "0.1.3" +version = "0.1.6" features = ["derive"] optional = true +default-features = false [dependencies.icu_locid] -version = "1.2.0" +version = "~1.3.2" features = ["zerovec"] +default-features = false + +[dependencies.icu_locid_transform] +version = "~1.3.2" +default-features = false [dependencies.icu_provider] -version = "1.2.0" +version = "~1.3.2" features = ["macros"] +default-features = false [dependencies.serde] version = "1.0" @@ -52,15 +62,14 @@ optional = true default-features = false [dependencies.tinystr] -version = "0.7.1" +version = "0.7.3" features = ["zerovec"] - -[dependencies.yoke] -version = "0.7.1" +default-features = false [dependencies.zerovec] -version = "0.9.4" +version = "0.10.0" features = ["yoke"] +default-features = false [dev-dependencies] @@ -68,15 +77,13 @@ features = ["yoke"] datagen = [ "std", "serde", - "dep:databake", "icu_provider/datagen", - "icu_locid/databake", - "zerovec/databake", ] serde = [ "dep:serde", "zerovec/serde", "icu_locid/serde", + "icu_locid_transform/serde", "icu_provider/serde", ] std = [ diff --git a/vendor/icu_provider_adapters/LICENSE b/vendor/icu_provider_adapters/LICENSE index 9858d01ab..9845aa5f4 100644 --- a/vendor/icu_provider_adapters/LICENSE +++ b/vendor/icu_provider_adapters/LICENSE @@ -1,49 +1,42 @@ -UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE - -See Terms of Use -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. +UNICODE LICENSE V3 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. +Copyright © 2020-2023 Unicode, Inc. + +NOTICE TO USER: Carefully read the following legal agreement. BY +DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR +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. + +Permission is hereby granted, free of charge, to any person obtaining a +copy of data files and any associated documentation (the "Data Files") or +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. — diff --git a/vendor/icu_provider_adapters/README.md b/vendor/icu_provider_adapters/README.md index 28a29e6bc..fcbdce2c3 100644 --- a/vendor/icu_provider_adapters/README.md +++ b/vendor/icu_provider_adapters/README.md @@ -1,5 +1,7 @@ # icu_provider_adapters [![crates.io](https://img.shields.io/crates/v/icu_provider_adapters)](https://crates.io/crates/icu_provider_adapters) + + Adapters for composing and manipulating data providers. - Use the [`fork`] module to marshall data requests between multiple possible providers. @@ -7,6 +9,8 @@ Adapters for composing and manipulating data providers. - Use the [`filter`] module to programmatically reject certain data requests. - Use the [`fallback`] module to automatically resolve arbitrary locales for data loading. + + ## 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_provider_adapters/src/fallback/adapter.rs b/vendor/icu_provider_adapters/src/fallback/adapter.rs deleted file mode 100644 index 8d9d79f2d..000000000 --- a/vendor/icu_provider_adapters/src/fallback/adapter.rs +++ /dev/null @@ -1,284 +0,0 @@ -// 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 super::*; -use crate::helpers::result_is_err_missing_locale; - -/// A data provider wrapper that performs locale fallback. This enables arbitrary locales to be -/// handled at runtime. -/// -/// # Examples -/// -/// ``` -/// use icu_locid::locale; -/// use icu_provider::prelude::*; -/// use icu_provider::hello_world::*; -/// use icu_provider_adapters::fallback::LocaleFallbackProvider; -/// -/// let provider = icu_testdata::unstable_no_fallback(); -/// -/// let req = DataRequest { -/// locale: &locale!("ja-JP").into(), -/// metadata: Default::default(), -/// }; -/// -/// // The provider does not have data for "ja-JP": -/// DataProvider::::load(&provider, req).expect_err("No fallback"); -/// -/// // But if we wrap the provider in a fallback provider... -/// let provider = LocaleFallbackProvider::try_new_unstable(provider) -/// .expect("Fallback data present"); -/// -/// // ...then we can load "ja-JP" based on "ja" data -/// let response = -/// DataProvider::::load(&provider, req).expect("successful with vertical fallback"); -/// -/// assert_eq!( -/// response.metadata.locale.unwrap(), -/// locale!("ja").into(), -/// ); -/// assert_eq!( -/// response.payload.unwrap().get().message, -/// "こんにちは世界", -/// ); -/// ``` -#[derive(Clone, Debug)] -pub struct LocaleFallbackProvider

{ - inner: P, - fallbacker: LocaleFallbacker, -} - -impl

LocaleFallbackProvider

-where - P: DataProvider - + DataProvider - + DataProvider, -{ - /// Create a [`LocaleFallbackProvider`] by wrapping another data provider and then loading - /// fallback data from it. - /// - /// If the data provider being wrapped does not contain fallback data, use - /// [`LocaleFallbackProvider::new_with_fallbacker`]. - pub fn try_new_unstable(provider: P) -> Result { - let fallbacker = LocaleFallbacker::try_new_unstable(&provider)?; - Ok(Self { - inner: provider, - fallbacker, - }) - } -} - -impl

LocaleFallbackProvider

-where - P: AnyProvider, -{ - /// Create a [`LocaleFallbackProvider`] by wrapping another data provider and then loading - /// fallback data from it. - /// - /// If the data provider being wrapped does not contain fallback data, use - /// [`LocaleFallbackProvider::new_with_fallbacker`]. - pub fn try_new_with_any_provider(provider: P) -> Result { - let fallbacker = LocaleFallbacker::try_new_with_any_provider(&provider)?; - Ok(Self { - inner: provider, - fallbacker, - }) - } -} - -#[cfg(feature = "serde")] -impl

LocaleFallbackProvider

-where - P: BufferProvider, -{ - /// Create a [`LocaleFallbackProvider`] by wrapping another data provider and then loading - /// fallback data from it. - /// - /// If the data provider being wrapped does not contain fallback data, use - /// [`LocaleFallbackProvider::new_with_fallbacker`]. - pub fn try_new_with_buffer_provider(provider: P) -> Result { - let fallbacker = LocaleFallbacker::try_new_with_buffer_provider(&provider)?; - Ok(Self { - inner: provider, - fallbacker, - }) - } -} - -impl

LocaleFallbackProvider

{ - /// Wrap a provider with an arbitrary fallback engine. - /// - /// This relaxes the requirement that the wrapped provider contains its own fallback data. - /// - /// # Examples - /// - /// ``` - /// use icu_locid::locale; - /// use icu_provider::hello_world::*; - /// use icu_provider::prelude::*; - /// use icu_provider_adapters::fallback::{ - /// LocaleFallbackProvider, LocaleFallbacker, - /// }; - /// - /// let provider = HelloWorldProvider; - /// - /// let req = DataRequest { - /// locale: &locale!("de-CH").into(), - /// metadata: Default::default(), - /// }; - /// - /// // There is no "de-CH" data in the `HelloWorldProvider` - /// DataProvider::::load(&provider, req) - /// .expect_err("No data for de-CH"); - /// - /// // `HelloWorldProvider` does not contain fallback data, - /// // but we can fetch it from `icu_testdata`, and then - /// // use it to create the fallbacking data provider. - /// let fallbacker = - /// LocaleFallbacker::try_new_unstable(&icu_testdata::unstable()) - /// .expect("Fallback data present"); - /// let provider = - /// LocaleFallbackProvider::new_with_fallbacker(provider, fallbacker); - /// - /// // Now we can load the "de-CH" data via fallback to "de". - /// let german_hello_world: DataPayload = provider - /// .load(req) - /// .expect("Loading should succeed") - /// .take_payload() - /// .expect("Data should be present"); - /// - /// assert_eq!("Hallo Welt", german_hello_world.get().message); - /// ``` - pub fn new_with_fallbacker(provider: P, fallbacker: LocaleFallbacker) -> Self { - Self { - inner: provider, - fallbacker, - } - } - - /// Returns a reference to the inner provider, bypassing fallback. - pub fn inner(&self) -> &P { - &self.inner - } - - /// Returns a mutable reference to the inner provider. - pub fn inner_mut(&mut self) -> &mut P { - &mut self.inner - } - - /// Returns ownership of the inner provider to the caller. - pub fn into_inner(self) -> P { - self.inner - } - - /// Run the fallback algorithm with the data request using the inner data provider. - /// Internal function; external clients should use one of the trait impls below. - /// - /// Function arguments: - /// - /// - F1 should perform a data load for a single DataRequest and return the result of it - /// - F2 should map from the provider-specific response type to DataResponseMetadata - fn run_fallback( - &self, - key: DataKey, - mut base_req: DataRequest, - mut f1: F1, - mut f2: F2, - ) -> Result - where - F1: FnMut(DataRequest) -> Result, - F2: FnMut(&mut R) -> &mut DataResponseMetadata, - { - let key_fallbacker = self.fallbacker.for_key(key); - let mut fallback_iterator = key_fallbacker.fallback_for(base_req.locale.clone()); - let base_silent = core::mem::replace(&mut base_req.metadata.silent, true); - loop { - let result = f1(DataRequest { - locale: fallback_iterator.get(), - metadata: base_req.metadata, - }); - if !result_is_err_missing_locale(&result) { - return result - .map(|mut res| { - f2(&mut res).locale = Some(fallback_iterator.take()); - res - }) - // Log the original request rather than the fallback request - .map_err(|e| { - base_req.metadata.silent = base_silent; - e.with_req(key, base_req) - }); - } - // If we just checked und, break out of the loop. - if fallback_iterator.get().is_empty() { - break; - } - fallback_iterator.step(); - } - base_req.metadata.silent = base_silent; - Err(DataErrorKind::MissingLocale.with_req(key, base_req)) - } -} - -impl

AnyProvider for LocaleFallbackProvider

-where - P: AnyProvider, -{ - fn load_any(&self, key: DataKey, base_req: DataRequest) -> Result { - self.run_fallback( - key, - base_req, - |req| self.inner.load_any(key, req), - |res| &mut res.metadata, - ) - } -} - -impl

BufferProvider for LocaleFallbackProvider

-where - P: BufferProvider, -{ - fn load_buffer( - &self, - key: DataKey, - base_req: DataRequest, - ) -> Result, DataError> { - self.run_fallback( - key, - base_req, - |req| self.inner.load_buffer(key, req), - |res| &mut res.metadata, - ) - } -} - -impl DynamicDataProvider for LocaleFallbackProvider

-where - P: DynamicDataProvider, - M: DataMarker, -{ - fn load_data(&self, key: DataKey, base_req: DataRequest) -> Result, DataError> { - self.run_fallback( - key, - base_req, - |req| self.inner.load_data(key, req), - |res| &mut res.metadata, - ) - } -} - -impl DataProvider for LocaleFallbackProvider

-where - P: DataProvider, - M: KeyedDataMarker, -{ - fn load(&self, base_req: DataRequest) -> Result, DataError> { - self.run_fallback( - M::KEY, - base_req, - |req| self.inner.load(req), - |res| &mut res.metadata, - ) - } -} diff --git a/vendor/icu_provider_adapters/src/fallback/algorithms.rs b/vendor/icu_provider_adapters/src/fallback/algorithms.rs deleted file mode 100644 index 0edc59304..000000000 --- a/vendor/icu_provider_adapters/src/fallback/algorithms.rs +++ /dev/null @@ -1,439 +0,0 @@ -// 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 icu_locid::extensions::unicode::Key; -use icu_locid::extensions_unicode_key as key; -use icu_locid::subtags::Language; -use icu_locid::LanguageIdentifier; -use icu_provider::FallbackPriority; - -use super::*; - -const SUBDIVISION_KEY: Key = key!("sd"); - -impl<'a> LocaleFallbackerWithConfig<'a> { - pub(crate) fn normalize(&self, locale: &mut DataLocale) { - let language = locale.language(); - // 1. Populate the region (required for region fallback only) - if self.config.priority == FallbackPriority::Region && locale.region().is_none() { - // 1a. First look for region based on language+script - if let Some(script) = locale.script() { - locale.set_region( - self.likely_subtags - .ls2r - .get_2d(&language.into(), &script.into()) - .copied(), - ); - } - // 1b. If that fails, try language only - if locale.region().is_none() { - locale.set_region(self.likely_subtags.l2r.get(&language.into()).copied()); - } - } - // 2. Remove the script if it is implied by the other subtags - if let Some(script) = locale.script() { - let default_script = self - .likely_subtags - .l2s - .get_copied(&language.into()) - .unwrap_or(DEFAULT_SCRIPT); - if let Some(region) = locale.region() { - if script - == self - .likely_subtags - .lr2s - .get_copied_2d(&language.into(), ®ion.into()) - .unwrap_or(default_script) - { - locale.set_script(None); - } - } else if script == default_script { - locale.set_script(None); - } - } - // 3. Remove irrelevant extension subtags - locale.retain_unicode_ext(|key| { - match *key { - // Always retain -u-sd - SUBDIVISION_KEY => true, - // Retain the query-specific keyword - _ if Some(*key) == self.config.extension_key => true, - // Drop all others - _ => false, - } - }); - // 4. If there is an invalid "sd" subtag, drop it - // For now, ignore it, and let fallback do it for us - } -} - -impl<'a, 'b> LocaleFallbackIteratorInner<'a, 'b> { - pub fn step(&mut self, locale: &mut DataLocale) { - match self.config.priority { - FallbackPriority::Language => self.step_language(locale), - FallbackPriority::Region => self.step_region(locale), - // TODO(#1964): Change the collation fallback rules to be different - // from the language fallback fules. - FallbackPriority::Collation => self.step_language(locale), - // This case should not normally happen, but `FallbackPriority` is non_exhaustive. - // Make it go directly to `und`. - _ => { - debug_assert!( - false, - "Unknown FallbackPriority: {:?}", - self.config.priority - ); - *locale = Default::default() - } - } - } - - fn step_language(&mut self, locale: &mut DataLocale) { - // 1. Remove the extension fallback keyword - if let Some(extension_key) = self.config.extension_key { - if let Some(value) = locale.remove_unicode_ext(&extension_key) { - self.backup_extension = Some(value); - return; - } - } - // 2. Remove the subdivision keyword - if let Some(value) = locale.remove_unicode_ext(&SUBDIVISION_KEY) { - self.backup_subdivision = Some(value); - return; - } - // 3. Assert that the locale is a language identifier - debug_assert!(!locale.has_unicode_ext()); - // 4. Remove variants - if locale.has_variants() { - self.backup_variants = Some(locale.clear_variants()); - return; - } - // 5. Check for parent override - if let Some(parent) = self.get_explicit_parent(locale) { - locale.set_langid(parent); - self.restore_extensions_variants(locale); - return; - } - // 6. Add the script subtag if necessary - if locale.script().is_none() { - if let Some(region) = locale.region() { - let language = locale.language(); - if let Some(script) = self - .likely_subtags - .lr2s - .get_copied_2d(&language.into(), ®ion.into()) - { - locale.set_script(Some(script)); - self.restore_extensions_variants(locale); - return; - } - } - } - // 7. Remove region - if locale.region().is_some() { - locale.set_region(None); - return; - } - // 8. Remove language+script - debug_assert!(!locale.language().is_empty()); // don't call .step() on und - locale.set_script(None); - locale.set_language(Language::UND); - } - - fn step_region(&mut self, locale: &mut DataLocale) { - // 1. Remove the extension fallback keyword - if let Some(extension_key) = self.config.extension_key { - if let Some(value) = locale.remove_unicode_ext(&extension_key) { - self.backup_extension = Some(value); - return; - } - } - // 2. Remove the subdivision keyword - if let Some(value) = locale.remove_unicode_ext(&SUBDIVISION_KEY) { - self.backup_subdivision = Some(value); - return; - } - // 3. Assert that the locale is a language identifier - debug_assert!(!locale.has_unicode_ext()); - // 4. Remove variants - if locale.has_variants() { - self.backup_variants = Some(locale.clear_variants()); - return; - } - // 5. Remove language+script - if !locale.language().is_empty() || locale.script().is_some() { - locale.set_script(None); - locale.set_language(Language::UND); - self.restore_extensions_variants(locale); - return; - } - // 6. Remove region - debug_assert!(locale.region().is_some()); // don't call .step() on und - locale.set_region(None); - } - - fn restore_extensions_variants(&mut self, locale: &mut DataLocale) { - if let Some(value) = self.backup_extension.take() { - #[allow(clippy::unwrap_used)] // not reachable unless extension_key is present - locale.set_unicode_ext(self.config.extension_key.unwrap(), value); - } - if let Some(value) = self.backup_subdivision.take() { - locale.set_unicode_ext(SUBDIVISION_KEY, value); - } - if let Some(variants) = self.backup_variants.take() { - locale.set_variants(variants); - } - } - - fn get_explicit_parent(&self, locale: &DataLocale) -> Option { - self.supplement - .and_then(|supplement| { - supplement - .parents - .get_copied_by(|uvstr| locale.strict_cmp(uvstr).reverse()) - }) - .or_else(|| { - self.parents - .parents - .get_copied_by(|uvstr| locale.strict_cmp(uvstr).reverse()) - }) - .map(LanguageIdentifier::from) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use icu_locid::Locale; - use std::str::FromStr; - use writeable::Writeable; - - struct TestCase { - input: &'static str, - requires_data: bool, - extension_key: Option, - fallback_supplement: Option, - // Note: The first entry in the chain is the normalized locale - expected_language_chain: &'static [&'static str], - expected_region_chain: &'static [&'static str], - } - - // TODO: Consider loading these from a JSON file - const TEST_CASES: &[TestCase] = &[ - TestCase { - input: "en-u-hc-h12-sd-usca", - requires_data: false, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["en-u-sd-usca", "en"], - expected_region_chain: &["en-u-sd-usca", "en", "und-u-sd-usca"], - }, - TestCase { - input: "en-US-u-hc-h12-sd-usca", - requires_data: false, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["en-US-u-sd-usca", "en-US", "en"], - expected_region_chain: &["en-US-u-sd-usca", "en-US", "und-US-u-sd-usca", "und-US"], - }, - TestCase { - input: "en-US-fonipa-u-hc-h12-sd-usca", - requires_data: false, - extension_key: Some(key!("hc")), - fallback_supplement: None, - expected_language_chain: &[ - "en-US-fonipa-u-hc-h12-sd-usca", - "en-US-fonipa-u-sd-usca", - "en-US-fonipa", - "en-US", - "en", - ], - expected_region_chain: &[ - "en-US-fonipa-u-hc-h12-sd-usca", - "en-US-fonipa-u-sd-usca", - "en-US-fonipa", - "en-US", - "und-US-fonipa-u-hc-h12-sd-usca", - "und-US-fonipa-u-sd-usca", - "und-US-fonipa", - "und-US", - ], - }, - TestCase { - input: "en-u-hc-h12-sd-usca", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["en-u-sd-usca", "en"], - expected_region_chain: &["en-US-u-sd-usca", "en-US", "und-US-u-sd-usca", "und-US"], - }, - TestCase { - input: "en-Latn-u-sd-usca", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["en-u-sd-usca", "en"], - expected_region_chain: &["en-US-u-sd-usca", "en-US", "und-US-u-sd-usca", "und-US"], - }, - TestCase { - input: "en-Latn-US-u-sd-usca", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["en-US-u-sd-usca", "en-US", "en"], - expected_region_chain: &["en-US-u-sd-usca", "en-US", "und-US-u-sd-usca", "und-US"], - }, - TestCase { - // NOTE: -u-rg is not yet supported; when it is, this test should be updated - input: "en-u-rg-gbxxxx", - requires_data: false, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["en"], - expected_region_chain: &["en"], - }, - TestCase { - input: "sr-ME", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["sr-ME", "sr-Latn-ME", "sr-Latn"], - expected_region_chain: &["sr-ME", "und-ME"], - }, - TestCase { - input: "sr-ME-fonipa", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &[ - "sr-ME-fonipa", - "sr-ME", - "sr-Latn-ME-fonipa", - "sr-Latn-ME", - "sr-Latn", - ], - expected_region_chain: &["sr-ME-fonipa", "sr-ME", "und-ME-fonipa", "und-ME"], - }, - TestCase { - input: "de-Latn-LI", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["de-LI", "de"], - expected_region_chain: &["de-LI", "und-LI"], - }, - TestCase { - input: "ca-ES-valencia", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["ca-ES-valencia", "ca-ES", "ca"], - expected_region_chain: &["ca-ES-valencia", "ca-ES", "und-ES-valencia", "und-ES"], - }, - TestCase { - input: "es-AR", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["es-AR", "es-419", "es"], - expected_region_chain: &["es-AR", "und-AR"], - }, - TestCase { - input: "hi-IN", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["hi-IN", "hi"], - expected_region_chain: &["hi-IN", "und-IN"], - }, - TestCase { - input: "hi-Latn-IN", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["hi-Latn-IN", "hi-Latn", "en-IN", "en-001", "en"], - expected_region_chain: &["hi-Latn-IN", "und-IN"], - }, - TestCase { - input: "zh-CN", - requires_data: true, - extension_key: None, - fallback_supplement: None, - // Note: "zh-Hans" is not reachable because it is the default script for "zh". - // The fallback algorithm does not visit the language-script bundle when the - // script is the default for the language - expected_language_chain: &["zh-CN", "zh"], - expected_region_chain: &["zh-CN", "und-CN"], - }, - TestCase { - input: "zh-TW", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["zh-TW", "zh-Hant-TW", "zh-Hant"], - expected_region_chain: &["zh-TW", "und-TW"], - }, - TestCase { - input: "yue-HK", - requires_data: true, - extension_key: None, - fallback_supplement: None, - expected_language_chain: &["yue-HK", "yue"], - expected_region_chain: &["yue-HK", "und-HK"], - }, - TestCase { - input: "yue-HK", - requires_data: true, - extension_key: None, - fallback_supplement: Some(FallbackSupplement::Collation), - // TODO(#1964): add "zh" as a target. - expected_language_chain: &["yue-HK", "yue", "zh-Hant"], - expected_region_chain: &["yue-HK", "und-HK"], - }, - ]; - - #[test] - #[cfg(feature = "serde")] - fn test_fallback() { - let fallbacker_no_data = LocaleFallbacker::new_without_data(); - let fallbacker_with_data = - LocaleFallbacker::try_new_with_buffer_provider(&icu_testdata::buffer()).unwrap(); - for cas in TEST_CASES { - for (priority, expected_chain) in [ - (FallbackPriority::Language, cas.expected_language_chain), - (FallbackPriority::Region, cas.expected_region_chain), - ] { - let config = LocaleFallbackConfig { - priority, - extension_key: cas.extension_key, - fallback_supplement: cas.fallback_supplement, - }; - let key_fallbacker = if cas.requires_data { - fallbacker_with_data.for_config(config) - } else { - fallbacker_no_data.for_config(config) - }; - let locale = DataLocale::from(Locale::from_str(cas.input).unwrap()); - let mut it = key_fallbacker.fallback_for(locale); - for &expected in expected_chain { - assert_eq!( - expected, - &*it.get().write_to_string(), - "{:?} ({:?})", - cas.input, - priority - ); - it.step(); - } - assert_eq!( - "und", - &*it.get().write_to_string(), - "{:?} ({:?})", - cas.input, - priority - ); - } - } - } -} diff --git a/vendor/icu_provider_adapters/src/fallback/mod.rs b/vendor/icu_provider_adapters/src/fallback/mod.rs index a28620b25..c0a05d14e 100644 --- a/vendor/icu_provider_adapters/src/fallback/mod.rs +++ b/vendor/icu_provider_adapters/src/fallback/mod.rs @@ -2,421 +2,297 @@ // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). -//! Tools for locale fallback, enabling arbitrary input locales to be mapped into the nearest -//! locale with data. -//! -//! The algorithm implemented in this module is called [Flexible Vertical Fallback]( -//! https://docs.google.com/document/d/1Mp7EUyl-sFh_HZYgyeVwj88vJGpCBIWxzlCwGgLCDwM/edit). -//! Watch [#2243](https://github.com/unicode-org/icu4x/issues/2243) to track improvements to -//! this algorithm and steps to enshrine the algorithm in CLDR. -//! -//! # Examples -//! -//! Run the locale fallback algorithm: -//! -//! ``` -//! use icu_locid::locale; -//! use icu_provider_adapters::fallback::LocaleFallbacker; -//! use icu_provider::prelude::*; -//! -//! // Set up a LocaleFallbacker with data. -//! let fallbacker = LocaleFallbacker::try_new_unstable(&icu_testdata::unstable()).expect("data"); -//! -//! // Create a LocaleFallbackerWithConfig with a configuration for a specific key. -//! // By default, uses language priority with no additional extension keywords. -//! let key_fallbacker = fallbacker.for_config(Default::default()); -//! -//! // Set up the fallback iterator. -//! let mut fallback_iterator = key_fallbacker.fallback_for(DataLocale::from(locale!("hi-Latn-IN"))); -//! -//! // Run the algorithm and check the results. -//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("hi-Latn-IN"))); -//! fallback_iterator.step(); -//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("hi-Latn"))); -//! fallback_iterator.step(); -//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("en-IN"))); -//! fallback_iterator.step(); -//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("en-001"))); -//! fallback_iterator.step(); -//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("en"))); -//! fallback_iterator.step(); -//! assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und"))); -//! ``` +//! A data provider wrapper that performs locale fallback. -use icu_locid::extensions::unicode::{Key, Value}; -use icu_locid::subtags::Variants; +use crate::helpers::result_is_err_missing_locale; +use icu_locid_transform::provider::*; use icu_provider::prelude::*; -use icu_provider::FallbackPriority; -use icu_provider::FallbackSupplement; -mod adapter; -mod algorithms; -pub mod provider; +#[doc(hidden)] // moved +pub use icu_locid_transform::fallback::{ + LocaleFallbackIterator, LocaleFallbacker, LocaleFallbackerWithConfig, +}; +#[doc(hidden)] // moved +pub use icu_provider::fallback::LocaleFallbackConfig; -pub use adapter::LocaleFallbackProvider; - -use provider::*; +/// A data provider wrapper that performs locale fallback. This enables arbitrary locales to be +/// handled at runtime. +/// +/// # Examples +/// +/// ``` +/// use icu_locid::locale; +/// use icu_provider::prelude::*; +/// use icu_provider::hello_world::*; +/// use icu_provider_adapters::fallback::LocaleFallbackProvider; +/// +/// # let provider = icu_provider_blob::BlobDataProvider::try_new_from_static_blob(include_bytes!("../../tests/data/blob.postcard")).unwrap(); +/// # let provider = provider.as_deserializing(); +/// +/// let req = DataRequest { +/// locale: &locale!("ja-JP").into(), +/// metadata: Default::default(), +/// }; +/// +/// // The provider does not have data for "ja-JP": +/// DataProvider::::load(&provider, req).expect_err("No fallback"); +/// +/// // But if we wrap the provider in a fallback provider... +/// let provider = LocaleFallbackProvider::try_new_unstable(provider) +/// .expect("Fallback data present"); +/// +/// // ...then we can load "ja-JP" based on "ja" data +/// let response = +/// DataProvider::::load(&provider, req).expect("successful with vertical fallback"); +/// +/// assert_eq!( +/// response.metadata.locale.unwrap(), +/// locale!("ja").into(), +/// ); +/// assert_eq!( +/// response.payload.unwrap().get().message, +/// "こんにちは世界", +/// ); +/// ``` +#[derive(Clone, Debug)] +pub struct LocaleFallbackProvider

{ + inner: P, + fallbacker: LocaleFallbacker, +} -/// Configuration settings for a particular fallback operation. -#[derive(Debug, Clone, PartialEq, Eq, Default)] -#[non_exhaustive] -pub struct LocaleFallbackConfig { - /// Strategy for choosing which subtags to drop during locale fallback. - /// - /// # Examples +impl

LocaleFallbackProvider

+where + P: DataProvider + + DataProvider + + DataProvider, +{ + /// Create a [`LocaleFallbackProvider`] by wrapping another data provider and then loading + /// fallback data from it. /// - /// Retain the language and script subtags until the final step: - /// - /// ``` - /// use icu_locid::locale; - /// use icu_provider::prelude::*; - /// use icu_provider::FallbackPriority; - /// use icu_provider_adapters::fallback::LocaleFallbackConfig; - /// use icu_provider_adapters::fallback::LocaleFallbacker; - /// - /// // Set up the fallback iterator. - /// let fallbacker = - /// LocaleFallbacker::try_new_unstable(&icu_testdata::unstable()) - /// .expect("data"); - /// let mut config = LocaleFallbackConfig::default(); - /// config.priority = FallbackPriority::Language; - /// let key_fallbacker = fallbacker.for_config(config); - /// let mut fallback_iterator = key_fallbacker - /// .fallback_for(DataLocale::from(locale!("ca-ES-valencia"))); - /// - /// // Run the algorithm and check the results. - /// assert_eq!( - /// fallback_iterator.get(), - /// &DataLocale::from(locale!("ca-ES-valencia")) - /// ); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ca-ES"))); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ca"))); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und"))); - /// ``` - /// - /// Retain the region subtag until the final step: + /// If the data provider being wrapped does not contain fallback data, use + /// [`LocaleFallbackProvider::new_with_fallbacker`]. + pub fn try_new_unstable(provider: P) -> Result { + let fallbacker = LocaleFallbacker::try_new_unstable(&provider)?; + Ok(Self { + inner: provider, + fallbacker, + }) + } +} + +impl

LocaleFallbackProvider

+where + P: AnyProvider, +{ + /// Create a [`LocaleFallbackProvider`] by wrapping another data provider and then loading + /// fallback data from it. /// - /// ``` - /// use icu_locid::locale; - /// use icu_provider::prelude::*; - /// use icu_provider::FallbackPriority; - /// use icu_provider_adapters::fallback::LocaleFallbackConfig; - /// use icu_provider_adapters::fallback::LocaleFallbacker; + /// If the data provider being wrapped does not contain fallback data, use + /// [`LocaleFallbackProvider::new_with_fallbacker`]. + pub fn try_new_with_any_provider(provider: P) -> Result { + let fallbacker = LocaleFallbacker::try_new_with_any_provider(&provider)?; + Ok(Self { + inner: provider, + fallbacker, + }) + } +} + +#[cfg(feature = "serde")] +impl

LocaleFallbackProvider

+where + P: BufferProvider, +{ + /// Create a [`LocaleFallbackProvider`] by wrapping another data provider and then loading + /// fallback data from it. /// - /// // Set up the fallback iterator. - /// let fallbacker = - /// LocaleFallbacker::try_new_unstable(&icu_testdata::unstable()) - /// .expect("data"); - /// let mut config = LocaleFallbackConfig::default(); - /// config.priority = FallbackPriority::Region; - /// let key_fallbacker = fallbacker.for_config(config); - /// let mut fallback_iterator = key_fallbacker - /// .fallback_for(DataLocale::from(locale!("ca-ES-valencia"))); + /// If the data provider being wrapped does not contain fallback data, use + /// [`LocaleFallbackProvider::new_with_fallbacker`]. + pub fn try_new_with_buffer_provider(provider: P) -> Result { + let fallbacker = LocaleFallbacker::try_new_with_buffer_provider(&provider)?; + Ok(Self { + inner: provider, + fallbacker, + }) + } +} + +impl

LocaleFallbackProvider

{ + /// Wrap a provider with an arbitrary fallback engine. /// - /// // Run the algorithm and check the results. - /// assert_eq!( - /// fallback_iterator.get(), - /// &DataLocale::from(locale!("ca-ES-valencia")) - /// ); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ca-ES"))); - /// fallback_iterator.step(); - /// assert_eq!( - /// fallback_iterator.get(), - /// &DataLocale::from(locale!("und-ES-valencia")) - /// ); - /// fallback_iterator.step(); - /// assert_eq!( - /// fallback_iterator.get(), - /// &DataLocale::from(locale!("und-ES")) - /// ); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und"))); - /// ``` - pub priority: FallbackPriority, - /// An extension keyword to retain during locale fallback. + /// This relaxes the requirement that the wrapped provider contains its own fallback data. /// /// # Examples /// /// ``` /// use icu_locid::locale; + /// use icu_locid_transform::LocaleFallbacker; + /// use icu_provider::hello_world::*; /// use icu_provider::prelude::*; - /// use icu_provider_adapters::fallback::LocaleFallbackConfig; - /// use icu_provider_adapters::fallback::LocaleFallbacker; - /// - /// // Set up the fallback iterator. - /// let fallbacker = - /// LocaleFallbacker::try_new_unstable(&icu_testdata::unstable()) - /// .expect("data"); - /// let mut config = LocaleFallbackConfig::default(); - /// config.extension_key = Some(icu_locid::extensions_unicode_key!("nu")); - /// let key_fallbacker = fallbacker.for_config(config); - /// let mut fallback_iterator = key_fallbacker - /// .fallback_for(DataLocale::from(locale!("ar-EG-u-nu-latn"))); - /// - /// // Run the algorithm and check the results. - /// assert_eq!( - /// fallback_iterator.get(), - /// &DataLocale::from(locale!("ar-EG-u-nu-latn")) - /// ); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ar-EG"))); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("ar"))); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und"))); - /// ``` - pub extension_key: Option, - /// Fallback supplement data key to customize fallback rules. + /// use icu_provider_adapters::fallback::LocaleFallbackProvider; /// - /// For example, most data keys for collation add additional parent locales, such as - /// "yue" to "zh-Hant", and data used for the `"-u-co"` extension keyword fallback. + /// let provider = HelloWorldProvider; /// - /// Currently the only supported fallback supplement is `FallbackSupplement::Collation`, but more may be - /// added in the future. + /// let req = DataRequest { + /// locale: &locale!("de-CH").into(), + /// metadata: Default::default(), + /// }; /// - /// # Examples + /// // There is no "de-CH" data in the `HelloWorldProvider` + /// DataProvider::::load(&provider, req) + /// .expect_err("No data for de-CH"); /// - /// ``` - /// use icu_locid::locale; - /// use icu_provider::prelude::*; - /// use icu_provider::FallbackPriority; - /// use icu_provider::FallbackSupplement; - /// use icu_provider_adapters::fallback::LocaleFallbackConfig; - /// use icu_provider_adapters::fallback::LocaleFallbacker; - /// use tinystr::tinystr; + /// // `HelloWorldProvider` does not contain fallback data, + /// // but we can construct a fallbacker with `icu_locid_transform`'s + /// // compiled data. + /// let provider = LocaleFallbackProvider::new_with_fallbacker( + /// provider, + /// LocaleFallbacker::new().static_to_owned(), + /// ); /// - /// // Set up the fallback iterator. - /// let fallbacker = - /// LocaleFallbacker::try_new_unstable(&icu_testdata::unstable()) - /// .expect("data"); - /// let mut config = LocaleFallbackConfig::default(); - /// config.priority = FallbackPriority::Collation; - /// config.fallback_supplement = Some(FallbackSupplement::Collation); - /// let key_fallbacker = fallbacker.for_config(config); - /// let mut fallback_iterator = - /// key_fallbacker.fallback_for(DataLocale::from(locale!("yue-HK"))); + /// // Now we can load the "de-CH" data via fallback to "de". + /// let german_hello_world: DataPayload = provider + /// .load(req) + /// .expect("Loading should succeed") + /// .take_payload() + /// .expect("Data should be present"); /// - /// // Run the algorithm and check the results. - /// // TODO(#1964): add "zh" as a target. - /// assert_eq!( - /// fallback_iterator.get(), - /// &DataLocale::from(locale!("yue-HK")) - /// ); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("yue"))); - /// fallback_iterator.step(); - /// assert_eq!( - /// fallback_iterator.get(), - /// &DataLocale::from(locale!("zh-Hant")) - /// ); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und"))); + /// assert_eq!("Hallo Welt", german_hello_world.get().message); /// ``` - pub fallback_supplement: Option, -} - -/// Entry type for locale fallbacking. -/// -/// See the module-level documentation for an example. -#[derive(Debug, Clone, PartialEq)] -pub struct LocaleFallbacker { - likely_subtags: DataPayload, - parents: DataPayload, - collation_supplement: Option>, -} + pub fn new_with_fallbacker(provider: P, fallbacker: LocaleFallbacker) -> Self { + Self { + inner: provider, + fallbacker, + } + } -/// Intermediate type for spawning locale fallback iterators based on a specific configuration. -/// -/// See the module-level documentation for an example. -#[derive(Debug, Clone, PartialEq)] -pub struct LocaleFallbackerWithConfig<'a> { - likely_subtags: &'a LocaleFallbackLikelySubtagsV1<'a>, - parents: &'a LocaleFallbackParentsV1<'a>, - supplement: Option<&'a LocaleFallbackSupplementV1<'a>>, - config: LocaleFallbackConfig, -} + /// Returns a reference to the inner provider, bypassing fallback. + pub fn inner(&self) -> &P { + &self.inner + } -/// Inner iteration type. Does not own the item under fallback. -#[derive(Debug)] -struct LocaleFallbackIteratorInner<'a, 'b> { - likely_subtags: &'a LocaleFallbackLikelySubtagsV1<'a>, - parents: &'a LocaleFallbackParentsV1<'a>, - supplement: Option<&'a LocaleFallbackSupplementV1<'a>>, - config: &'b LocaleFallbackConfig, - backup_extension: Option, - backup_subdivision: Option, - backup_variants: Option, -} + /// Returns a mutable reference to the inner provider. + pub fn inner_mut(&mut self) -> &mut P { + &mut self.inner + } -/// Iteration type for locale fallback operations. -/// -/// Because the `Iterator` trait does not allow items to borrow from the iterator, this class does -/// not implement that trait. Instead, use `.step()` and `.get()`. -#[derive(Debug)] -pub struct LocaleFallbackIterator<'a, 'b> { - current: DataLocale, - inner: LocaleFallbackIteratorInner<'a, 'b>, -} + /// Returns ownership of the inner provider to the caller. + pub fn into_inner(self) -> P { + self.inner + } -impl LocaleFallbacker { - /// Creates a [`LocaleFallbacker`] with fallback data (likely subtags and parent locales). + /// Run the fallback algorithm with the data request using the inner data provider. + /// Internal function; external clients should use one of the trait impls below. /// - /// [📚 Help choosing a constructor](icu_provider::constructors) - ///

- /// ⚠️ The bounds on this function may change over time, including in SemVer minor releases. - ///
- pub fn try_new_unstable

(provider: &P) -> Result + /// Function arguments: + /// + /// - F1 should perform a data load for a single DataRequest and return the result of it + /// - F2 should map from the provider-specific response type to DataResponseMetadata + fn run_fallback( + &self, + key: DataKey, + mut base_req: DataRequest, + mut f1: F1, + mut f2: F2, + ) -> Result where - P: DataProvider - + DataProvider - + DataProvider - + ?Sized, + F1: FnMut(DataRequest) -> Result, + F2: FnMut(&mut R) -> &mut DataResponseMetadata, { - let likely_subtags = provider.load(Default::default())?.take_payload()?; - let parents = provider.load(Default::default())?.take_payload()?; - let collation_supplement = match DataProvider::::load( - provider, - Default::default(), - ) { - Ok(response) => Some(response.take_payload()?), - // It is expected that not all keys are present - Err(DataError { - kind: DataErrorKind::MissingDataKey, - .. - }) => None, - Err(e) => return Err(e), - }; - Ok(LocaleFallbacker { - likely_subtags, - parents, - collation_supplement, - }) - } - - icu_provider::gen_any_buffer_constructors!(locale: skip, options: skip, error: DataError); - - /// Creates a [`LocaleFallbacker`] without fallback data. Using this constructor may result in - /// surprising behavior, especially in multi-script languages. - pub fn new_without_data() -> Self { - LocaleFallbacker { - likely_subtags: DataPayload::from_owned(Default::default()), - parents: DataPayload::from_owned(Default::default()), - collation_supplement: None, + if key.metadata().singleton { + return f1(base_req); } - } - - /// Creates the intermediate [`LocaleFallbackerWithConfig`] with configuration options. - pub fn for_config(&self, config: LocaleFallbackConfig) -> LocaleFallbackerWithConfig { - let supplement = match config.fallback_supplement { - Some(FallbackSupplement::Collation) => { - self.collation_supplement.as_ref().map(|p| p.get()) + let mut fallback_iterator = self + .fallbacker + .for_config(key.fallback_config()) + .fallback_for(base_req.locale.clone()); + let base_silent = core::mem::replace(&mut base_req.metadata.silent, true); + loop { + let result = f1(DataRequest { + locale: fallback_iterator.get(), + metadata: base_req.metadata, + }); + if !result_is_err_missing_locale(&result) { + return result + .map(|mut res| { + f2(&mut res).locale = Some(fallback_iterator.take()); + res + }) + // Log the original request rather than the fallback request + .map_err(|e| { + base_req.metadata.silent = base_silent; + e.with_req(key, base_req) + }); + } + // If we just checked und, break out of the loop. + if fallback_iterator.get().is_und() { + break; } - _ => None, - }; - LocaleFallbackerWithConfig { - likely_subtags: self.likely_subtags.get(), - parents: self.parents.get(), - supplement, - config, + fallback_iterator.step(); } - } - - /// Creates the intermediate [`LocaleFallbackerWithConfig`] based on a - /// [`DataKey`] and a [`DataRequestMetadata`]. - /// - /// # Examples - /// - /// ``` - /// use icu_locid::locale; - /// use icu_provider::prelude::*; - /// use icu_provider_adapters::fallback::LocaleFallbacker; - /// use std::borrow::Cow; - /// - /// // Define the data struct with key. - /// #[icu_provider::data_struct(marker( - /// FooV1Marker, - /// "demo/foo@1", - /// fallback_by = "region" - /// ))] - /// pub struct FooV1<'data> { - /// message: Cow<'data, str>, - /// }; - /// - /// // Set up the fallback iterator. - /// let fallbacker = - /// LocaleFallbacker::try_new_unstable(&icu_testdata::unstable()) - /// .expect("data"); - /// let key_fallbacker = fallbacker.for_key(FooV1Marker::KEY); - /// let mut fallback_iterator = - /// key_fallbacker.fallback_for(DataLocale::from(locale!("en-GB"))); - /// - /// // Run the algorithm and check the results. - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("en-GB"))); - /// fallback_iterator.step(); - /// assert_eq!( - /// fallback_iterator.get(), - /// &DataLocale::from(locale!("und-GB")) - /// ); - /// fallback_iterator.step(); - /// assert_eq!(fallback_iterator.get(), &DataLocale::from(locale!("und"))); - /// ``` - /// - /// [`DataRequestMetadata`]: icu_provider::DataRequestMetadata - pub fn for_key(&self, data_key: DataKey) -> LocaleFallbackerWithConfig { - let priority = data_key.metadata().fallback_priority; - let extension_key = data_key.metadata().extension_key; - let fallback_supplement = data_key.metadata().fallback_supplement; - self.for_config(LocaleFallbackConfig { - priority, - extension_key, - fallback_supplement, - }) + base_req.metadata.silent = base_silent; + Err(DataErrorKind::MissingLocale.with_req(key, base_req)) } } -impl<'a> LocaleFallbackerWithConfig<'a> { - /// Creates an iterator based on a [`DataLocale`] (which can be created from [`Locale`]). - /// - /// When first initialized, the locale is normalized according to the fallback algorithm. - /// - /// [`Locale`]: icu_locid::Locale - pub fn fallback_for<'b>(&'b self, mut locale: DataLocale) -> LocaleFallbackIterator<'a, 'b> { - self.normalize(&mut locale); - LocaleFallbackIterator { - current: locale, - inner: LocaleFallbackIteratorInner { - likely_subtags: self.likely_subtags, - parents: self.parents, - supplement: self.supplement, - config: &self.config, - backup_extension: None, - backup_subdivision: None, - backup_variants: None, - }, - } +impl

AnyProvider for LocaleFallbackProvider

+where + P: AnyProvider, +{ + fn load_any(&self, key: DataKey, base_req: DataRequest) -> Result { + self.run_fallback( + key, + base_req, + |req| self.inner.load_any(key, req), + |res| &mut res.metadata, + ) } } -impl LocaleFallbackIterator<'_, '_> { - /// Borrows the current [`DataLocale`] under fallback. - pub fn get(&self) -> &DataLocale { - &self.current +impl

BufferProvider for LocaleFallbackProvider

+where + P: BufferProvider, +{ + fn load_buffer( + &self, + key: DataKey, + base_req: DataRequest, + ) -> Result, DataError> { + self.run_fallback( + key, + base_req, + |req| self.inner.load_buffer(key, req), + |res| &mut res.metadata, + ) } +} - /// Takes the current [`DataLocale`] under fallback. - pub fn take(self) -> DataLocale { - self.current +impl DynamicDataProvider for LocaleFallbackProvider

+where + P: DynamicDataProvider, + M: DataMarker, +{ + fn load_data(&self, key: DataKey, base_req: DataRequest) -> Result, DataError> { + self.run_fallback( + key, + base_req, + |req| self.inner.load_data(key, req), + |res| &mut res.metadata, + ) } +} - /// Performs one step of the locale fallback algorithm. - /// - /// The fallback is completed once the inner [`DataLocale`] becomes `und`. - pub fn step(&mut self) -> &mut Self { - self.inner.step(&mut self.current); - self +impl DataProvider for LocaleFallbackProvider

+where + P: DataProvider, + M: KeyedDataMarker, +{ + fn load(&self, base_req: DataRequest) -> Result, DataError> { + self.run_fallback( + M::KEY, + base_req, + |req| self.inner.load(req), + |res| &mut res.metadata, + ) } } diff --git a/vendor/icu_provider_adapters/src/fallback/provider.rs b/vendor/icu_provider_adapters/src/fallback/provider.rs deleted file mode 100644 index edfa01f58..000000000 --- a/vendor/icu_provider_adapters/src/fallback/provider.rs +++ /dev/null @@ -1,111 +0,0 @@ -// 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 ). - -//! Data provider struct definitions for vertical fallback. -//! -//! Read more about data providers: [`icu_provider`] - -// Provider structs must be stable -#![allow(clippy::exhaustive_structs)] - -use icu_locid::extensions::unicode::Key; -use icu_locid::subtags::{Language, Region, Script}; -use icu_locid::{subtags_region as region, subtags_script as script}; -use tinystr::TinyAsciiStr; - -use icu_provider::prelude::*; - -use zerovec::ule::UnvalidatedStr; -use zerovec::ZeroMap; -use zerovec::ZeroMap2d; - -// We use raw TinyAsciiStrs for map keys, as we then don't have to -// validate them as subtags on deserialization. Map lookup can be -// done even if they are not valid tags (an invalid key will just -// become inaccessible). -type UnvalidatedLanguage = TinyAsciiStr<3>; -type UnvalidatedScript = TinyAsciiStr<4>; -type UnvalidatedRegion = TinyAsciiStr<3>; - -/// Locale fallback rules derived from likely subtags data. -#[icu_provider::data_struct(LocaleFallbackLikelySubtagsV1Marker = "fallback/likelysubtags@1")] -#[derive(Default, Clone, PartialEq, Debug)] -#[cfg_attr( - feature = "datagen", - derive(serde::Serialize, databake::Bake), - databake(path = icu_provider_adapters::fallback::provider), -)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[yoke(prove_covariance_manually)] -pub struct LocaleFallbackLikelySubtagsV1<'data> { - /// Map from language to the default script in that language. Languages whose default script - /// is `Latn` are not included in the map for data size savings. - /// - /// Example: "zh" defaults to "Hans", which is in this map. - #[cfg_attr(feature = "serde", serde(borrow))] - pub l2s: ZeroMap<'data, UnvalidatedLanguage, Script>, - /// Map from language-region pairs to a script. Only populated if the script is different - /// from the one in `l2s` for that language. - /// - /// Example: "zh-TW" defaults to "Hant", which is in this map. - #[cfg_attr(feature = "serde", serde(borrow))] - pub lr2s: ZeroMap2d<'data, UnvalidatedLanguage, UnvalidatedRegion, Script>, - /// Map from language to the default region in that language. Languages whose default region - /// is `ZZ` are not included in the map for data size savings. - /// - /// Example: "zh" defaults to "CN". - #[cfg_attr(feature = "serde", serde(borrow))] - pub l2r: ZeroMap<'data, UnvalidatedLanguage, Region>, - /// Map from language-script pairs to a region. Only populated if the region is different - /// from the one in `l2r` for that language. - /// - /// Example: "zh-Hant" defaults to "TW". - #[cfg_attr(feature = "serde", serde(borrow))] - pub ls2r: ZeroMap2d<'data, UnvalidatedLanguage, UnvalidatedScript, Region>, -} - -/// `Latn` is the most common script, so it is defaulted for data size savings. -pub const DEFAULT_SCRIPT: Script = script!("Latn"); - -/// `ZZ` is the most common region, so it is defaulted for data size savings. -pub const DEFAULT_REGION: Region = region!("ZZ"); - -/// Locale fallback rules derived from CLDR parent locales data. -#[icu_provider::data_struct(LocaleFallbackParentsV1Marker = "fallback/parents@1")] -#[derive(Default, Clone, PartialEq, Debug)] -#[cfg_attr( - feature = "datagen", - derive(serde::Serialize, databake::Bake), - databake(path = icu_provider_adapters::fallback::provider), -)] -#[cfg_attr(feature = "serde", derive(serde::Deserialize))] -#[yoke(prove_covariance_manually)] -pub struct LocaleFallbackParentsV1<'data> { - /// Map from language identifier to language identifier, indicating that the language on the - /// left should inherit from the language on the right. - #[cfg_attr(feature = "serde", serde(borrow))] - pub parents: ZeroMap<'data, UnvalidatedStr, (Language, Option