From 65a1748edbf0ae901d694447718e37781ba7f771 Mon Sep 17 00:00:00 2001 From: Mohamad <192450738+piyyy314@users.noreply.github.com> Date: Sat, 22 Nov 2025 21:27:28 -0500 Subject: [PATCH 01/46] Update regress-3039.js --- deps/v8/test/mjsunit/regress/regress-3039.js | 1 - 1 file changed, 1 deletion(-) diff --git a/deps/v8/test/mjsunit/regress/regress-3039.js b/deps/v8/test/mjsunit/regress/regress-3039.js index 42640cec02894e..cdfada44237d0c 100644 --- a/deps/v8/test/mjsunit/regress/regress-3039.js +++ b/deps/v8/test/mjsunit/regress/regress-3039.js @@ -32,7 +32,6 @@ function do_div(x, y) { } // Preparation. -; %PrepareFunctionForOptimization(do_div); assertEquals(17, do_div(51, 3)); assertEquals(13, do_div(65, 5)); From 74ad033b5ef2321fb77c480acc7d046908e0a795 Mon Sep 17 00:00:00 2001 From: Mohamad Date: Sun, 19 Apr 2026 00:08:47 -0400 Subject: [PATCH 02/46] Remove vendored icu_locale_core crate Delete the vendored icu_locale_core source files under deps/crates/vendor/icu_locale_core (extensions, parser, subtags, helpers, serde, etc.). Also update deps/undici/src/package-lock.json. This cleans up the repository by removing the bundled ICU4X locale core implementation; package-lock.json was modified as part of dependency updates. Co-Authored-By: Copilot <198982749+Copilot@users.noreply.github.com> Signed-off-by: Mohamad --- .../vendor/icu_locale_core/src/databake.rs | 22 - .../icu_locale_core/src/extensions/mod.rs | 397 ----------- .../src/extensions/other/mod.rs | 264 ------- .../src/extensions/private/mod.rs | 250 ------- .../src/extensions/private/other.rs | 47 -- .../src/extensions/transform/fields.rs | 220 ------ .../src/extensions/transform/key.rs | 32 - .../src/extensions/transform/mod.rs | 331 --------- .../src/extensions/transform/value.rs | 160 ----- .../src/extensions/unicode/attribute.rs | 34 - .../src/extensions/unicode/attributes.rs | 177 ----- .../src/extensions/unicode/key.rs | 32 - .../src/extensions/unicode/keywords.rs | 418 ----------- .../src/extensions/unicode/mod.rs | 269 ------- .../src/extensions/unicode/subdivision.rs | 181 ----- .../src/extensions/unicode/value.rs | 354 ---------- .../vendor/icu_locale_core/src/helpers.rs | 425 ----------- .../vendor/icu_locale_core/src/langid.rs | 662 ------------------ deps/crates/vendor/icu_locale_core/src/lib.rs | 96 --- .../vendor/icu_locale_core/src/locale.rs | 607 ---------------- .../vendor/icu_locale_core/src/macros.rs | 187 ----- .../icu_locale_core/src/parser/errors.rs | 69 -- .../icu_locale_core/src/parser/langid.rs | 273 -------- .../icu_locale_core/src/parser/locale.rs | 42 -- .../vendor/icu_locale_core/src/parser/mod.rs | 185 ----- .../src/preferences/extensions/mod.rs | 23 - .../preferences/extensions/unicode/errors.rs | 15 - .../extensions/unicode/keywords/calendar.rs | 69 -- .../extensions/unicode/keywords/collation.rs | 79 --- .../extensions/unicode/keywords/currency.rs | 31 - .../unicode/keywords/currency_format.rs | 20 - .../unicode/keywords/dictionary_break.rs | 39 -- .../extensions/unicode/keywords/emoji.rs | 25 - .../extensions/unicode/keywords/first_day.rs | 31 - .../extensions/unicode/keywords/hour_cycle.rs | 20 - .../extensions/unicode/keywords/line_break.rs | 23 - .../unicode/keywords/line_break_word.rs | 25 - .../unicode/keywords/measurement_system.rs | 22 - .../keywords/measurement_unit_override.rs | 20 - .../extensions/unicode/keywords/mod.rs | 44 -- .../unicode/keywords/numbering_system.rs | 26 - .../unicode/keywords/region_override.rs | 63 -- .../unicode/keywords/regional_subdivision.rs | 52 -- .../unicode/keywords/sentence_supression.rs | 21 - .../extensions/unicode/keywords/timezone.rs | 26 - .../extensions/unicode/keywords/variant.rs | 16 - .../extensions/unicode/macros/enum_keyword.rs | 320 --------- .../extensions/unicode/macros/mod.rs | 13 - .../unicode/macros/struct_keyword.rs | 124 ---- .../src/preferences/extensions/unicode/mod.rs | 17 - .../icu_locale_core/src/preferences/locale.rs | 180 ----- .../icu_locale_core/src/preferences/mod.rs | 612 ---------------- .../vendor/icu_locale_core/src/serde.rs | 134 ---- .../icu_locale_core/src/shortvec/litemap.rs | 198 ------ .../icu_locale_core/src/shortvec/mod.rs | 370 ---------- .../icu_locale_core/src/subtags/language.rs | 59 -- .../vendor/icu_locale_core/src/subtags/mod.rs | 163 ----- .../icu_locale_core/src/subtags/region.rs | 60 -- .../icu_locale_core/src/subtags/script.rs | 41 -- .../icu_locale_core/src/subtags/variant.rs | 35 - .../icu_locale_core/src/subtags/variants.rs | 136 ---- .../vendor/icu_locale_core/src/zerovec.rs | 131 ---- 62 files changed, 9017 deletions(-) delete mode 100644 deps/crates/vendor/icu_locale_core/src/databake.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/other/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/private/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/private/other.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/transform/fields.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/transform/key.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/transform/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/transform/value.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/attribute.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/attributes.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/key.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/keywords.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/subdivision.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/extensions/unicode/value.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/helpers.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/langid.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/lib.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/locale.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/macros.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/parser/errors.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/parser/langid.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/parser/locale.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/parser/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/errors.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/calendar.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/collation.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/currency.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/currency_format.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/dictionary_break.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/emoji.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/first_day.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/hour_cycle.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/line_break.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/line_break_word.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/measurement_system.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/measurement_unit_override.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/numbering_system.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/region_override.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/regional_subdivision.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/sentence_supression.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/timezone.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/keywords/variant.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/macros/enum_keyword.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/macros/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/macros/struct_keyword.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/extensions/unicode/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/locale.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/preferences/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/serde.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/shortvec/litemap.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/shortvec/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/language.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/mod.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/region.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/script.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/variant.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/subtags/variants.rs delete mode 100644 deps/crates/vendor/icu_locale_core/src/zerovec.rs diff --git a/deps/crates/vendor/icu_locale_core/src/databake.rs b/deps/crates/vendor/icu_locale_core/src/databake.rs deleted file mode 100644 index 802e546e4229f3..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/databake.rs +++ /dev/null @@ -1,22 +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 crate::LanguageIdentifier; -use databake::*; - -impl Bake for LanguageIdentifier { - fn bake(&self, env: &CrateEnv) -> TokenStream { - env.insert("icu_locale_core"); - let repr = self.to_string(); - if self.variants.len() <= 1 { - quote! { - icu_locale_core::langid!(#repr) - } - } else { - quote! { - icu_locale_core::LanguageIdentifier::try_from_str(#repr).unwrap() - } - } - } -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/mod.rs deleted file mode 100644 index 1893ad7349e02c..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/mod.rs +++ /dev/null @@ -1,397 +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 ). - -//! Unicode Extensions provide a mechanism to extend the [`LanguageIdentifier`] with -//! additional bits of information - a combination of a [`LanguageIdentifier`] and [`Extensions`] -//! is called [`Locale`]. -//! -//! There are four types of extensions: -//! -//! * [`Unicode Extensions`] - marked as `u`. -//! * [`Transform Extensions`] - marked as `t`. -//! * [`Private Use Extensions`] - marked as `x`. -//! * [`Other Extensions`] - marked as any `a-z` except of `u`, `t` and `x`. -//! -//! One can think of extensions as a bag of extra information on top of basic 4 [`subtags`]. -//! -//! Notice: `Other` extension type is currently not supported. -//! -//! # Examples -//! -//! ``` -//! use icu::locale::extensions::unicode::{Key, Value}; -//! use icu::locale::Locale; -//! -//! let loc: Locale = "en-US-u-ca-buddhist-t-en-us-h0-hybrid-x-foo" -//! .parse() -//! .expect("Failed to parse."); -//! -//! assert_eq!(loc.id.language, "en".parse().unwrap()); -//! assert_eq!(loc.id.script, None); -//! assert_eq!(loc.id.region, Some("US".parse().unwrap())); -//! assert_eq!(loc.id.variants.len(), 0); -//! -//! let key: Key = "ca".parse().expect("Parsing key failed."); -//! let value: Value = "buddhist".parse().expect("Parsing value failed."); -//! assert_eq!(loc.extensions.unicode.keywords.get(&key), Some(&value)); -//! ``` -//! -//! # Syntactic vs Semantic Extension Handling -//! -//! This module is useful when you need to work with Locale extensions at a syntactic level, -//! perhaps for parsing or generating locale identifiers that include any syntactically valid -//! extensions. -//! For handling and validating known CLDR values with semantic meaning, see the -//! [`crate::preferences::extensions`] module. -//! -//! [`LanguageIdentifier`]: super::LanguageIdentifier -//! [`Locale`]: super::Locale -//! [`subtags`]: super::subtags -//! [`Other Extensions`]: other -//! [`Private Use Extensions`]: private -//! [`Transform Extensions`]: transform -//! [`Unicode Extensions`]: unicode -pub mod other; -pub mod private; -pub mod transform; -pub mod unicode; - -use core::cmp::Ordering; - -use other::Other; -use private::{Private, PRIVATE_EXT_CHAR}; -use transform::{Transform, TRANSFORM_EXT_CHAR}; -use unicode::{Unicode, UNICODE_EXT_CHAR}; - -#[cfg(feature = "alloc")] -use alloc::vec::Vec; - -use crate::parser::ParseError; -#[cfg(feature = "alloc")] -use crate::parser::SubtagIterator; -use crate::subtags; - -/// Defines the type of extension. -#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Copy)] -#[non_exhaustive] -pub enum ExtensionType { - /// Transform Extension Type marked as `t`. - Transform, - /// Unicode Extension Type marked as `u`. - Unicode, - /// Private Extension Type marked as `x`. - Private, - /// All other extension types. - Other(u8), -} - -impl ExtensionType { - #[allow(dead_code)] - pub(crate) const fn try_from_byte_slice(key: &[u8]) -> Result { - if let [b] = key { - Self::try_from_byte(*b) - } else { - Err(ParseError::InvalidExtension) - } - } - - pub(crate) const fn try_from_byte(key: u8) -> Result { - let key = key.to_ascii_lowercase(); - match key as char { - UNICODE_EXT_CHAR => Ok(Self::Unicode), - TRANSFORM_EXT_CHAR => Ok(Self::Transform), - PRIVATE_EXT_CHAR => Ok(Self::Private), - 'a'..='z' => Ok(Self::Other(key)), - _ => Err(ParseError::InvalidExtension), - } - } - - pub(crate) const fn try_from_utf8(code_units: &[u8]) -> Result { - let &[first] = code_units else { - return Err(ParseError::InvalidExtension); - }; - - Self::try_from_byte(first) - } -} - -/// A map of extensions associated with a given [`Locale`](crate::Locale). -#[derive(Debug, Default, PartialEq, Eq, Clone, Hash)] -#[non_exhaustive] -pub struct Extensions { - /// A representation of the data for a Unicode extension, when present in the locale identifier. - pub unicode: Unicode, - /// A representation of the data for a transform extension, when present in the locale identifier. - pub transform: Transform, - /// A representation of the data for a private-use extension, when present in the locale identifier. - pub private: Private, - /// A sequence of any other extensions that are present in the locale identifier but are not formally - /// [defined](https://unicode.org/reports/tr35/) and represented explicitly as [`Unicode`], [`Transform`], - /// and [`Private`] are. - #[cfg(feature = "alloc")] - pub other: Vec, - /// A sequence of any other extensions that are present in the locale identifier but are not formally - /// [defined](https://unicode.org/reports/tr35/) and represented explicitly as [`Unicode`], [`Transform`], - /// and [`Private`] are. - #[cfg(not(feature = "alloc"))] - pub other: &'static [Other], -} - -impl Extensions { - /// Returns a new empty map of extensions. Same as [`default()`](Default::default()), but is `const`. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::Extensions; - /// - /// assert_eq!(Extensions::new(), Extensions::default()); - /// ``` - #[inline] - pub const fn new() -> Self { - Self { - unicode: Unicode::new(), - transform: Transform::new(), - private: Private::new(), - #[cfg(feature = "alloc")] - other: Vec::new(), - #[cfg(not(feature = "alloc"))] - other: &[], - } - } - - /// Function to create a new map of extensions containing exactly one unicode extension, callable in `const` - /// context. - #[inline] - pub const fn from_unicode(unicode: Unicode) -> Self { - Self { - unicode, - transform: Transform::new(), - private: Private::new(), - #[cfg(feature = "alloc")] - other: Vec::new(), - #[cfg(not(feature = "alloc"))] - other: &[], - } - } - - /// Returns whether there are no extensions present. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::Locale; - /// - /// let loc: Locale = "en-US-u-foo".parse().expect("Parsing failed."); - /// - /// assert!(!loc.extensions.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { - self.unicode.is_empty() - && self.transform.is_empty() - && self.private.is_empty() - && self.other.is_empty() - } - - #[allow(clippy::type_complexity)] - pub(crate) fn as_tuple( - &self, - ) -> ( - (&unicode::Attributes, &unicode::Keywords), - ( - Option<( - subtags::Language, - Option, - Option, - &subtags::Variants, - )>, - &transform::Fields, - ), - &private::Private, - &[other::Other], - ) { - ( - self.unicode.as_tuple(), - self.transform.as_tuple(), - &self.private, - &self.other, - ) - } - - /// Returns an ordering suitable for use in [`BTreeSet`]. - /// - /// The ordering may or may not be equivalent to string ordering, and it - /// may or may not be stable across ICU4X releases. - /// - /// [`BTreeSet`]: alloc::collections::BTreeSet - pub fn total_cmp(&self, other: &Self) -> Ordering { - self.as_tuple().cmp(&other.as_tuple()) - } - - /// Retains the specified extension types, clearing all others. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::ExtensionType; - /// use icu::locale::Locale; - /// - /// let loc: Locale = - /// "und-a-hello-t-mul-u-world-z-zzz-x-extra".parse().unwrap(); - /// - /// let mut only_unicode = loc.clone(); - /// only_unicode - /// .extensions - /// .retain_by_type(|t| t == ExtensionType::Unicode); - /// assert_eq!(only_unicode, "und-u-world".parse().unwrap()); - /// - /// let mut only_t_z = loc.clone(); - /// only_t_z.extensions.retain_by_type(|t| { - /// t == ExtensionType::Transform || t == ExtensionType::Other(b'z') - /// }); - /// assert_eq!(only_t_z, "und-t-mul-z-zzz".parse().unwrap()); - /// ``` - pub fn retain_by_type(&mut self, mut predicate: F) - where - F: FnMut(ExtensionType) -> bool, - { - if !predicate(ExtensionType::Unicode) { - self.unicode.clear(); - } - if !predicate(ExtensionType::Transform) { - self.transform.clear(); - } - if !predicate(ExtensionType::Private) { - self.private.clear(); - } - #[cfg(feature = "alloc")] - self.other - .retain(|o| predicate(ExtensionType::Other(o.get_ext_byte()))); - } - - #[cfg(feature = "alloc")] - pub(crate) fn try_from_iter(iter: &mut SubtagIterator) -> Result { - let mut unicode = None; - let mut transform = None; - let mut private = None; - let mut other = Vec::new(); - - while let Some(subtag) = iter.next() { - if subtag.is_empty() { - return Err(ParseError::InvalidExtension); - } - - let &[subtag] = subtag else { - return Err(ParseError::InvalidExtension); - }; - - match ExtensionType::try_from_byte(subtag) { - Ok(ExtensionType::Unicode) => { - if unicode.is_some() { - return Err(ParseError::DuplicatedExtension); - } - unicode = Some(Unicode::try_from_iter(iter)?); - } - Ok(ExtensionType::Transform) => { - if transform.is_some() { - return Err(ParseError::DuplicatedExtension); - } - transform = Some(Transform::try_from_iter(iter)?); - } - Ok(ExtensionType::Private) => { - if private.is_some() { - return Err(ParseError::DuplicatedExtension); - } - private = Some(Private::try_from_iter(iter)?); - } - Ok(ExtensionType::Other(ext)) => { - if other.iter().any(|o: &Other| o.get_ext_byte() == ext) { - return Err(ParseError::DuplicatedExtension); - } - let parsed = Other::try_from_iter(ext, iter)?; - if let Err(idx) = other.binary_search(&parsed) { - other.insert(idx, parsed); - } else { - return Err(ParseError::InvalidExtension); - } - } - _ => return Err(ParseError::InvalidExtension), - } - } - - Ok(Self { - unicode: unicode.unwrap_or_default(), - transform: transform.unwrap_or_default(), - private: private.unwrap_or_default(), - other, - }) - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - let mut wrote_tu = false; - // Alphabetic by singleton - self.other.iter().try_for_each(|other| { - if other.get_ext() > TRANSFORM_EXT_CHAR && !wrote_tu { - // Since 't' and 'u' are next to each other in alphabetical - // order, write both now. - self.transform.for_each_subtag_str(f, true)?; - self.unicode.for_each_subtag_str(f, true)?; - wrote_tu = true; - } - other.for_each_subtag_str(f, true)?; - Ok(()) - })?; - - if !wrote_tu { - self.transform.for_each_subtag_str(f, true)?; - self.unicode.for_each_subtag_str(f, true)?; - } - - // Private must be written last, since it allows single character - // keys. Extensions must also be written in alphabetical order, - // which would seem to imply that other extensions `y` and `z` are - // invalid, but this is not specified. - self.private.for_each_subtag_str(f, true)?; - Ok(()) - } -} - -#[cfg(feature = "alloc")] -impl_writeable_for_each_subtag_str_no_test!(Extensions); - -#[test] -fn test_writeable() { - use crate::Locale; - use writeable::assert_writeable_eq; - assert_writeable_eq!(Extensions::new(), ""); - assert_writeable_eq!( - "my-t-my-d0-zawgyi".parse::().unwrap().extensions, - "t-my-d0-zawgyi", - ); - assert_writeable_eq!( - "ar-SA-u-ca-islamic-civil" - .parse::() - .unwrap() - .extensions, - "u-ca-islamic-civil", - ); - assert_writeable_eq!( - "en-001-x-foo-bar".parse::().unwrap().extensions, - "x-foo-bar", - ); - assert_writeable_eq!( - "und-t-m0-true".parse::().unwrap().extensions, - "t-m0-true", - ); - assert_writeable_eq!( - "und-a-foo-t-foo-u-foo-w-foo-z-foo-x-foo" - .parse::() - .unwrap() - .extensions, - "a-foo-t-foo-u-foo-w-foo-z-foo-x-foo", - ); -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/other/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/other/mod.rs deleted file mode 100644 index 050b379c6da0d3..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/other/mod.rs +++ /dev/null @@ -1,264 +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 ). - -//! Other Use Extensions is a list of extensions other than unicode, -//! transform or private. -//! -//! Those extensions are treated as a pass-through, and no Unicode related -//! behavior depends on them. -//! -//! The main struct for this extension is [`Other`] which is a list of [`Subtag`]s. -//! -//! # Examples -//! -//! ``` -//! use icu::locale::extensions::other::Other; -//! use icu::locale::Locale; -//! -//! let mut loc: Locale = "en-US-a-foo-faa".parse().expect("Parsing failed."); -//! ``` - -#[cfg(feature = "alloc")] -use core::str::FromStr; - -#[cfg(feature = "alloc")] -use super::ExtensionType; -#[cfg(feature = "alloc")] -use crate::parser::ParseError; -#[cfg(feature = "alloc")] -use crate::parser::SubtagIterator; -use crate::shortvec::ShortBoxSlice; -use crate::subtags::Subtag; -#[cfg(feature = "alloc")] -use alloc::vec::Vec; - -/// A list of [`Other Use Extensions`] as defined in [`Unicode Locale -/// Identifier`] specification. -/// -/// Those extensions are treated as a pass-through, and no Unicode related -/// behavior depends on them. -/// -/// # Examples -/// -/// ``` -/// use icu::locale::extensions::other::Other; -/// use icu::locale::subtags::Subtag; -/// -/// let subtag1: Subtag = "foo".parse().expect("Failed to parse a Subtag."); -/// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag."); -/// -/// let other = Other::from_vec_unchecked(b'a', vec![subtag1, subtag2]); -/// assert_eq!(&other.to_string(), "a-foo-bar"); -/// ``` -/// -/// [`Other Use Extensions`]: https://unicode.org/reports/tr35/#other_extensions -/// [`Unicode Locale Identifier`]: https://unicode.org/reports/tr35/#Unicode_locale_identifier -#[derive(Clone, PartialEq, Eq, Debug, Default, Hash, PartialOrd, Ord)] -pub struct Other { - // Safety invariant: must be ASCII - ext: u8, - keys: ShortBoxSlice, -} - -impl Other { - /// A constructor which takes a str slice, parses it and - /// produces a well-formed [`Other`]. - #[inline] - #[cfg(feature = "alloc")] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - let mut iter = SubtagIterator::new(code_units); - - let ext = iter.next().ok_or(ParseError::InvalidExtension)?; - if let ExtensionType::Other(b) = ExtensionType::try_from_byte_slice(ext)? { - return Self::try_from_iter(b, &mut iter); - } - - Err(ParseError::InvalidExtension) - } - - /// A constructor which takes a pre-sorted list of [`Subtag`]. - /// - /// # Panics - /// - /// Panics if `ext` is not ASCII alphabetic. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::other::Other; - /// use icu::locale::subtags::Subtag; - /// - /// let subtag1: Subtag = "foo".parse().expect("Failed to parse a Subtag."); - /// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag."); - /// - /// let other = Other::from_vec_unchecked(b'a', vec![subtag1, subtag2]); - /// assert_eq!(&other.to_string(), "a-foo-bar"); - /// ``` - #[cfg(feature = "alloc")] - pub fn from_vec_unchecked(ext: u8, keys: Vec) -> Self { - Self::from_short_slice_unchecked(ext, keys.into()) - } - - #[allow(dead_code)] - pub(crate) fn from_short_slice_unchecked(ext: u8, keys: ShortBoxSlice) -> Self { - assert!(ext.is_ascii_alphabetic()); - // Safety invariant upheld here: ext checked as ASCII above - Self { ext, keys } - } - - #[cfg(feature = "alloc")] - pub(crate) fn try_from_iter(ext: u8, iter: &mut SubtagIterator) -> Result { - debug_assert!(matches!( - ExtensionType::try_from_byte(ext), - Ok(ExtensionType::Other(_)), - )); - - let mut keys = ShortBoxSlice::new(); - while let Some(subtag) = iter.peek() { - if !Subtag::valid_key(subtag) { - break; - } - if let Ok(key) = Subtag::try_from_utf8(subtag) { - keys.push(key); - } - iter.next(); - } - - if keys.is_empty() { - Err(ParseError::InvalidExtension) - } else { - Ok(Self::from_short_slice_unchecked(ext, keys)) - } - } - - /// Gets the tag character for this extension as a &str. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::Locale; - /// - /// let loc: Locale = "und-a-hello-world".parse().unwrap(); - /// let other_ext = &loc.extensions.other[0]; - /// assert_eq!(other_ext.get_ext_str(), "a"); - /// ``` - pub fn get_ext_str(&self) -> &str { - debug_assert!(self.ext.is_ascii_alphabetic()); - // Safety: from safety invariant on self.ext (that it is ASCII) - unsafe { core::str::from_utf8_unchecked(core::slice::from_ref(&self.ext)) } - } - - /// Gets the tag character for this extension as a char. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::Locale; - /// - /// let loc: Locale = "und-a-hello-world".parse().unwrap(); - /// let other_ext = &loc.extensions.other[0]; - /// assert_eq!(other_ext.get_ext(), 'a'); - /// ``` - pub fn get_ext(&self) -> char { - self.ext as char - } - - /// Gets the tag character for this extension as a byte. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::Locale; - /// - /// let loc: Locale = "und-a-hello-world".parse().unwrap(); - /// let other_ext = &loc.extensions.other[0]; - /// assert_eq!(other_ext.get_ext_byte(), b'a'); - /// ``` - pub fn get_ext_byte(&self) -> u8 { - self.ext - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F, with_ext: bool) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - if self.keys.is_empty() { - return Ok(()); - } - - if with_ext { - f(self.get_ext_str())?; - } - self.keys.iter().map(|t| t.as_str()).try_for_each(f) - } -} - -#[cfg(feature = "alloc")] -impl FromStr for Other { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -writeable::impl_display_with_writeable!(Other); - -impl writeable::Writeable for Other { - fn write_to(&self, sink: &mut W) -> core::fmt::Result { - if self.keys.is_empty() { - return Ok(()); - } - sink.write_str(self.get_ext_str())?; - for key in self.keys.iter() { - sink.write_char('-')?; - writeable::Writeable::write_to(key, sink)?; - } - - Ok(()) - } - - fn writeable_length_hint(&self) -> writeable::LengthHint { - if self.keys.is_empty() { - return writeable::LengthHint::exact(0); - }; - let mut result = writeable::LengthHint::exact(1); - for key in self.keys.iter() { - result += writeable::Writeable::writeable_length_hint(key) + 1; - } - result - } - - #[cfg(feature = "alloc")] - fn write_to_string(&self) -> alloc::borrow::Cow { - if self.keys.is_empty() { - return alloc::borrow::Cow::Borrowed(""); - } - let mut string = - alloc::string::String::with_capacity(self.writeable_length_hint().capacity()); - let _ = self.write_to(&mut string); - alloc::borrow::Cow::Owned(string) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_other_extension_fromstr() { - let oe: Other = "o-foo-bar".parse().expect("Failed to parse Other"); - assert_eq!(oe.to_string(), "o-foo-bar"); - - let oe: Result = "o".parse(); - assert!(oe.is_err()); - } -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/private/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/private/mod.rs deleted file mode 100644 index ee9852921af51d..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/private/mod.rs +++ /dev/null @@ -1,250 +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 ). - -//! Private Use Extensions is a list of extensions intended for -//! private use. -//! -//! Those extensions are treated as a pass-through, and no Unicode related -//! behavior depends on them. -//! -//! The main struct for this extension is [`Private`] which is a list of [`Subtag`]s. -//! -//! # Examples -//! -//! ``` -//! use icu::locale::extensions::private::subtag; -//! use icu::locale::{locale, Locale}; -//! -//! let mut loc: Locale = "en-US-x-foo-faa".parse().expect("Parsing failed."); -//! -//! assert!(loc.extensions.private.contains(&subtag!("foo"))); -//! assert_eq!(loc.extensions.private.iter().next(), Some(&subtag!("foo"))); -//! -//! loc.extensions.private.clear(); -//! -//! assert!(loc.extensions.private.is_empty()); -//! assert_eq!(loc, locale!("en-US")); -//! ``` - -mod other; - -#[cfg(feature = "alloc")] -use alloc::vec::Vec; -use core::ops::Deref; -#[cfg(feature = "alloc")] -use core::str::FromStr; - -#[doc(inline)] -pub use other::{subtag, Subtag}; - -#[cfg(feature = "alloc")] -use super::ExtensionType; -#[cfg(feature = "alloc")] -use crate::parser::ParseError; -#[cfg(feature = "alloc")] -use crate::parser::SubtagIterator; -use crate::shortvec::ShortBoxSlice; - -pub(crate) const PRIVATE_EXT_CHAR: char = 'x'; -pub(crate) const PRIVATE_EXT_STR: &str = "x"; - -/// A list of [`Private Use Extensions`] as defined in [`Unicode Locale -/// Identifier`] specification. -/// -/// Those extensions are treated as a pass-through, and no Unicode related -/// behavior depends on them. -/// -/// # Examples -/// -/// ``` -/// use icu::locale::extensions::private::{Private, Subtag}; -/// -/// let subtag1: Subtag = "foo".parse().expect("Failed to parse a Subtag."); -/// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag."); -/// -/// let private = Private::from_vec_unchecked(vec![subtag1, subtag2]); -/// assert_eq!(&private.to_string(), "x-foo-bar"); -/// ``` -/// -/// [`Private Use Extensions`]: https://unicode.org/reports/tr35/#pu_extensions -/// [`Unicode Locale Identifier`]: https://unicode.org/reports/tr35/#Unicode_locale_identifier -#[derive(Clone, PartialEq, Eq, Debug, Default, Hash, PartialOrd, Ord)] -pub struct Private(ShortBoxSlice); - -impl Private { - /// Returns a new empty list of private-use extensions. Same as [`default()`](Default::default()), but is `const`. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::private::Private; - /// - /// assert_eq!(Private::new(), Private::default()); - /// ``` - #[inline] - pub const fn new() -> Self { - Self(ShortBoxSlice::new()) - } - - /// A constructor which takes a str slice, parses it and - /// produces a well-formed [`Private`]. - #[inline] - #[cfg(feature = "alloc")] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - let mut iter = SubtagIterator::new(code_units); - - let ext = iter.next().ok_or(ParseError::InvalidExtension)?; - if let ExtensionType::Private = ExtensionType::try_from_byte_slice(ext)? { - return Self::try_from_iter(&mut iter); - } - - Err(ParseError::InvalidExtension) - } - - /// A constructor which takes a pre-sorted list of [`Subtag`]. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::private::{Private, Subtag}; - /// - /// let subtag1: Subtag = "foo".parse().expect("Failed to parse a Subtag."); - /// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag."); - /// - /// let private = Private::from_vec_unchecked(vec![subtag1, subtag2]); - /// assert_eq!(&private.to_string(), "x-foo-bar"); - /// ``` - #[cfg(feature = "alloc")] - pub fn from_vec_unchecked(input: Vec) -> Self { - Self(input.into()) - } - - /// A constructor which takes a single [`Subtag`]. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::private::{Private, Subtag}; - /// - /// let subtag: Subtag = "foo".parse().expect("Failed to parse a Subtag."); - /// - /// let private = Private::new_single(subtag); - /// assert_eq!(&private.to_string(), "x-foo"); - /// ``` - pub const fn new_single(input: Subtag) -> Self { - Self(ShortBoxSlice::new_single(input)) - } - - /// Empties the [`Private`] list. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::private::{Private, Subtag}; - /// - /// let subtag1: Subtag = "foo".parse().expect("Failed to parse a Subtag."); - /// let subtag2: Subtag = "bar".parse().expect("Failed to parse a Subtag."); - /// let mut private = Private::from_vec_unchecked(vec![subtag1, subtag2]); - /// - /// assert_eq!(&private.to_string(), "x-foo-bar"); - /// - /// private.clear(); - /// - /// assert_eq!(private, Private::new()); - /// ``` - pub fn clear(&mut self) { - self.0.clear(); - } - - #[cfg(feature = "alloc")] - pub(crate) fn try_from_iter(iter: &mut SubtagIterator) -> Result { - let keys = iter - .map(Subtag::try_from_utf8) - .collect::, _>>()?; - - if keys.is_empty() { - Err(ParseError::InvalidExtension) - } else { - Ok(Self(keys)) - } - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F, with_ext: bool) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - if self.is_empty() { - return Ok(()); - } - if with_ext { - f(PRIVATE_EXT_STR)?; - } - self.deref().iter().map(|t| t.as_str()).try_for_each(f) - } -} - -#[cfg(feature = "alloc")] -impl FromStr for Private { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -writeable::impl_display_with_writeable!(Private); - -impl writeable::Writeable for Private { - fn write_to(&self, sink: &mut W) -> core::fmt::Result { - if self.is_empty() { - return Ok(()); - } - sink.write_char(PRIVATE_EXT_CHAR)?; - for key in self.iter() { - sink.write_char('-')?; - writeable::Writeable::write_to(key, sink)?; - } - Ok(()) - } - - fn writeable_length_hint(&self) -> writeable::LengthHint { - if self.is_empty() { - return writeable::LengthHint::exact(0); - } - let mut result = writeable::LengthHint::exact(1); - for key in self.iter() { - result += writeable::Writeable::writeable_length_hint(key) + 1; - } - result - } -} - -impl Deref for Private { - type Target = [Subtag]; - - fn deref(&self) -> &Self::Target { - self.0.deref() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_private_extension_fromstr() { - let pe: Private = "x-foo-bar-l-baz".parse().expect("Failed to parse Private"); - assert_eq!(pe.to_string(), "x-foo-bar-l-baz"); - - let pe: Result = "x".parse(); - assert!(pe.is_err()); - } -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/private/other.rs b/deps/crates/vendor/icu_locale_core/src/extensions/private/other.rs deleted file mode 100644 index b3d8e074f15e3c..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/private/other.rs +++ /dev/null @@ -1,47 +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 ). - -impl_tinystr_subtag!( - /// A single item used in a list of [`Private`](super::Private) extensions. - /// - /// The subtag has to be an ASCII alphanumerical string no shorter than - /// one character and no longer than eight. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::private::Subtag; - /// - /// let subtag1: Subtag = "Foo".parse() - /// .expect("Failed to parse a Subtag."); - /// - /// assert_eq!(subtag1.as_str(), "foo"); - /// ``` - /// - /// Notice: This is different from the generic [`Subtag`](crate::subtags::Subtag) - /// which is between two and eight characters. - /// - /// ``` - /// use icu::locale::extensions::private; - /// use icu::locale::subtags; - /// - /// let subtag: Result = "f".parse(); - /// assert!(subtag.is_ok()); - /// - /// let subtag: Result = "f".parse(); - /// assert!(subtag.is_err()); - /// ``` - Subtag, - extensions::private, - subtag, - extensions_private_subtag, - 1..=8, - s, - s.is_ascii_alphanumeric(), - s.to_ascii_lowercase(), - s.is_ascii_alphanumeric() && s.is_ascii_lowercase(), - InvalidExtension, - ["foo12"], - ["toolooong"], -); diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/transform/fields.rs b/deps/crates/vendor/icu_locale_core/src/extensions/transform/fields.rs deleted file mode 100644 index d5d9cf72484124..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/transform/fields.rs +++ /dev/null @@ -1,220 +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 core::borrow::Borrow; -use core::iter::FromIterator; -use litemap::LiteMap; - -use super::Key; -use super::Value; - -/// A list of [`Key`]-[`Value`] pairs representing functional information -/// about content transformations. -/// -/// Here are examples of fields used in Unicode: -/// - `s0`, `d0` - Transform source/destination -/// - `t0` - Machine Translation -/// - `h0` - Hybrid Locale Identifiers -/// -/// You can find the full list in [`Unicode BCP 47 T Extension`] section of LDML. -/// -/// [`Unicode BCP 47 T Extension`]: https://unicode.org/reports/tr35/tr35.html#BCP47_T_Extension -/// -/// # Examples -/// -/// ``` -/// use icu::locale::extensions::transform::{key, Fields, Value}; -/// -/// let value = "hybrid".parse::().expect("Failed to parse a Value."); -/// let fields = [(key!("h0"), value)].into_iter().collect::(); -/// -/// assert_eq!(&fields.to_string(), "h0-hybrid"); -/// ``` -#[derive(Clone, PartialEq, Eq, Debug, Default, Hash, PartialOrd, Ord)] -pub struct Fields(LiteMap); - -impl Fields { - /// Returns a new empty list of key-value pairs. Same as [`default()`](Default::default()), but is `const`. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::transform::Fields; - /// - /// assert_eq!(Fields::new(), Fields::default()); - /// ``` - #[inline] - pub const fn new() -> Self { - Self(LiteMap::new()) - } - - /// Returns `true` if there are no fields. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::locale; - /// use icu::locale::Locale; - /// - /// let loc1 = Locale::try_from_str("und-t-h0-hybrid").unwrap(); - /// let loc2 = locale!("und-u-ca-buddhist"); - /// - /// assert!(!loc1.extensions.transform.fields.is_empty()); - /// assert!(loc2.extensions.transform.fields.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Empties the [`Fields`] list. - /// - /// Returns the old list. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::transform::{key, Fields, Value}; - /// - /// let value = "hybrid".parse::().expect("Failed to parse a Value."); - /// let mut fields = [(key!("h0"), value)].into_iter().collect::(); - /// - /// assert_eq!(&fields.to_string(), "h0-hybrid"); - /// - /// fields.clear(); - /// - /// assert_eq!(fields, Fields::new()); - /// ``` - pub fn clear(&mut self) -> Self { - core::mem::take(self) - } - - /// Returns `true` if the list contains a [`Value`] for the specified [`Key`]. - /// - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::transform::{Fields, Key, Value}; - /// - /// let key: Key = "h0".parse().expect("Failed to parse a Key."); - /// let value: Value = "hybrid".parse().expect("Failed to parse a Value."); - /// let mut fields = [(key, value)].into_iter().collect::(); - /// - /// let key: Key = "h0".parse().expect("Failed to parse a Key."); - /// assert!(&fields.contains_key(&key)); - /// ``` - pub fn contains_key(&self, key: &Q) -> bool - where - Key: Borrow, - Q: Ord, - { - self.0.contains_key(key) - } - - /// Returns a reference to the [`Value`] corresponding to the [`Key`]. - /// - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::transform::{key, Fields, Value}; - /// - /// let value = "hybrid".parse::().unwrap(); - /// let fields = [(key!("h0"), value.clone())] - /// .into_iter() - /// .collect::(); - /// - /// assert_eq!(fields.get(&key!("h0")), Some(&value)); - /// ``` - pub fn get(&self, key: &Q) -> Option<&Value> - where - Key: Borrow, - Q: Ord, - { - self.0.get(key) - } - - /// Sets the specified keyword, returning the old value if it already existed. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::transform::{key, Value}; - /// use icu::locale::Locale; - /// - /// let lower = "lower".parse::().expect("valid extension subtag"); - /// let casefold = "casefold".parse::().expect("valid extension subtag"); - /// - /// let mut loc: Locale = "en-t-hi-d0-casefold" - /// .parse() - /// .expect("valid BCP-47 identifier"); - /// let old_value = loc.extensions.transform.fields.set(key!("d0"), lower); - /// - /// assert_eq!(old_value, Some(casefold)); - /// assert_eq!(loc, "en-t-hi-d0-lower".parse().unwrap()); - /// ``` - pub fn set(&mut self, key: Key, value: Value) -> Option { - self.0.insert(key, value) - } - - /// Retains a subset of fields as specified by the predicate function. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::transform::key; - /// use icu::locale::Locale; - /// - /// let mut loc: Locale = "und-t-h0-hybrid-d0-hex-m0-xml".parse().unwrap(); - /// - /// loc.extensions - /// .transform - /// .fields - /// .retain_by_key(|&k| k == key!("h0")); - /// assert_eq!(loc, "und-t-h0-hybrid".parse().unwrap()); - /// - /// loc.extensions - /// .transform - /// .fields - /// .retain_by_key(|&k| k == key!("d0")); - /// assert_eq!(loc, Locale::UNKNOWN); - /// ``` - pub fn retain_by_key(&mut self, mut predicate: F) - where - F: FnMut(&Key) -> bool, - { - self.0.retain(|k, _| predicate(k)) - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - for (k, v) in self.0.iter() { - f(k.as_str())?; - v.for_each_subtag_str(f)?; - } - Ok(()) - } - - /// This needs to be its own method to help with type inference in helpers.rs - #[cfg(test)] - pub(crate) fn from_tuple_vec(v: Vec<(Key, Value)>) -> Self { - v.into_iter().collect() - } -} - -impl From> for Fields { - fn from(map: LiteMap) -> Self { - Self(map) - } -} - -impl FromIterator<(Key, Value)> for Fields { - fn from_iter>(iter: I) -> Self { - LiteMap::from_iter(iter).into() - } -} - -impl_writeable_for_key_value!(Fields, "h0", "hybrid", "m0", "m0-true"); diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/transform/key.rs b/deps/crates/vendor/icu_locale_core/src/extensions/transform/key.rs deleted file mode 100644 index 27dc98ce99a95f..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/transform/key.rs +++ /dev/null @@ -1,32 +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 ). - -impl_tinystr_subtag!( - /// A key used in a list of [`Fields`](super::Fields). - /// - /// The key has to be a two ASCII characters long, with the first - /// character being alphabetic, and the second being a number. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::transform::Key; - /// - /// let key1: Key = "k0".parse().expect("Failed to parse a Key."); - /// - /// assert_eq!(key1.as_str(), "k0"); - /// ``` - Key, - extensions::transform, - key, - extensions_transform_key, - 2..=2, - s, - s.all_bytes()[0].is_ascii_alphabetic() && s.all_bytes()[1].is_ascii_digit(), - s.to_ascii_lowercase(), - s.all_bytes()[0].is_ascii_lowercase() && s.all_bytes()[1].is_ascii_digit(), - InvalidExtension, - ["k0"], - ["", "k", "0k", "k12"], -); diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/transform/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/transform/mod.rs deleted file mode 100644 index 8f3094f1bf2145..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/transform/mod.rs +++ /dev/null @@ -1,331 +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 ). - -//! Transform Extensions provide information on content transformations in a given locale. -//! -//! The main struct for this extension is [`Transform`] which contains [`Fields`] and an -//! optional [`LanguageIdentifier`]. -//! -//! [`LanguageIdentifier`]: super::super::LanguageIdentifier -//! -//! # Examples -//! -//! ``` -//! use icu::locale::extensions::transform::{Fields, Key, Transform, Value}; -//! use icu::locale::{LanguageIdentifier, Locale}; -//! -//! let mut loc: Locale = -//! "en-US-t-es-ar-h0-hybrid".parse().expect("Parsing failed."); -//! -//! let lang: LanguageIdentifier = -//! "es-AR".parse().expect("Parsing LanguageIdentifier failed."); -//! -//! let key: Key = "h0".parse().expect("Parsing key failed."); -//! let value: Value = "hybrid".parse().expect("Parsing value failed."); -//! -//! assert_eq!(loc.extensions.transform.lang, Some(lang)); -//! assert!(loc.extensions.transform.fields.contains_key(&key)); -//! assert_eq!(loc.extensions.transform.fields.get(&key), Some(&value)); -//! -//! assert_eq!(&loc.extensions.transform.to_string(), "t-es-ar-h0-hybrid"); -//! ``` -mod fields; -mod key; -mod value; - -use core::cmp::Ordering; -#[cfg(feature = "alloc")] -use core::str::FromStr; - -pub use fields::Fields; -#[doc(inline)] -pub use key::{key, Key}; -pub use value::Value; - -#[cfg(feature = "alloc")] -use super::ExtensionType; -#[cfg(feature = "alloc")] -use crate::parser::SubtagIterator; -#[cfg(feature = "alloc")] -use crate::parser::{parse_language_identifier_from_iter, ParseError, ParserMode}; -#[cfg(feature = "alloc")] -use crate::shortvec::ShortBoxSlice; -use crate::subtags; -#[cfg(feature = "alloc")] -use crate::subtags::Language; -use crate::LanguageIdentifier; -#[cfg(feature = "alloc")] -use litemap::LiteMap; - -pub(crate) const TRANSFORM_EXT_CHAR: char = 't'; -pub(crate) const TRANSFORM_EXT_STR: &str = "t"; - -/// A list of [`Unicode BCP47 T Extensions`] as defined in [`Unicode Locale -/// Identifier`] specification. -/// -/// Transform extension carries information about source language or script of -/// transformed content, including content that has been transliterated, transcribed, -/// or translated, or in some other way influenced by the source (See [`RFC 6497`] for details). -/// -/// # Examples -/// -/// ``` -/// use icu::locale::extensions::transform::{Key, Value}; -/// use icu::locale::{LanguageIdentifier, Locale}; -/// -/// let mut loc: Locale = -/// "de-t-en-us-h0-hybrid".parse().expect("Parsing failed."); -/// -/// let en_us: LanguageIdentifier = "en-US".parse().expect("Parsing failed."); -/// -/// assert_eq!(loc.extensions.transform.lang, Some(en_us)); -/// let key: Key = "h0".parse().expect("Parsing key failed."); -/// let value: Value = "hybrid".parse().expect("Parsing value failed."); -/// assert_eq!(loc.extensions.transform.fields.get(&key), Some(&value)); -/// ``` -/// [`Unicode BCP47 T Extensions`]: https://unicode.org/reports/tr35/#t_Extension -/// [`RFC 6497`]: https://www.ietf.org/rfc/rfc6497.txt -/// [`Unicode Locale Identifier`]: https://unicode.org/reports/tr35/#Unicode_locale_identifier -#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] -#[allow(clippy::exhaustive_structs)] // spec-backed stable datastructure -pub struct Transform { - /// The [`LanguageIdentifier`] specified with this locale extension, or `None` if not present. - pub lang: Option, - /// The key-value pairs present in this locale extension, with each extension key subtag - /// associated to its provided value subtag. - pub fields: Fields, -} - -impl Transform { - /// Returns a new empty map of Transform extensions. Same as [`default()`](Default::default()), but is `const`. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::transform::Transform; - /// - /// assert_eq!(Transform::new(), Transform::default()); - /// ``` - #[inline] - pub const fn new() -> Self { - Self { - lang: None, - fields: Fields::new(), - } - } - - /// A constructor which takes a str slice, parses it and - /// produces a well-formed [`Transform`]. - #[inline] - #[cfg(feature = "alloc")] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - let mut iter = SubtagIterator::new(code_units); - - let ext = iter.next().ok_or(ParseError::InvalidExtension)?; - if let ExtensionType::Transform = ExtensionType::try_from_byte_slice(ext)? { - return Self::try_from_iter(&mut iter); - } - - Err(ParseError::InvalidExtension) - } - - /// Returns `true` if there are no tfields and no tlang in the `TransformExtensionList`. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::Locale; - /// - /// let mut loc: Locale = "en-US-t-es-ar".parse().expect("Parsing failed."); - /// - /// assert!(!loc.extensions.transform.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { - self.lang.is_none() && self.fields.is_empty() - } - - /// Clears the transform extension, effectively removing it from the locale. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::Locale; - /// - /// let mut loc: Locale = "en-US-t-es-ar".parse().unwrap(); - /// loc.extensions.transform.clear(); - /// assert_eq!(loc, "en-US".parse().unwrap()); - /// ``` - pub fn clear(&mut self) { - self.lang = None; - self.fields.clear(); - } - - #[allow(clippy::type_complexity)] - pub(crate) fn as_tuple( - &self, - ) -> ( - Option<( - subtags::Language, - Option, - Option, - &subtags::Variants, - )>, - &Fields, - ) { - (self.lang.as_ref().map(|l| l.as_tuple()), &self.fields) - } - - /// Returns an ordering suitable for use in [`BTreeSet`]. - /// - /// The ordering may or may not be equivalent to string ordering, and it - /// may or may not be stable across ICU4X releases. - /// - /// [`BTreeSet`]: alloc::collections::BTreeSet - pub fn total_cmp(&self, other: &Self) -> Ordering { - self.as_tuple().cmp(&other.as_tuple()) - } - - #[cfg(feature = "alloc")] - pub(crate) fn try_from_iter(iter: &mut SubtagIterator) -> Result { - let mut tlang = None; - let mut tfields = LiteMap::new(); - - if let Some(subtag) = iter.peek() { - if Language::try_from_utf8(subtag).is_ok() { - tlang = Some(parse_language_identifier_from_iter( - iter, - ParserMode::Partial, - )?); - } - } - - let mut current_tkey = None; - let mut current_tvalue = ShortBoxSlice::new(); - let mut has_current_tvalue = false; - - while let Some(subtag) = iter.peek() { - if let Some(tkey) = current_tkey { - if let Ok(val) = Value::parse_subtag(subtag) { - has_current_tvalue = true; - if let Some(val) = val { - current_tvalue.push(val); - } - } else { - if !has_current_tvalue { - return Err(ParseError::InvalidExtension); - } - tfields.try_insert(tkey, Value::from_short_slice_unchecked(current_tvalue)); - current_tkey = None; - current_tvalue = ShortBoxSlice::new(); - has_current_tvalue = false; - continue; - } - } else if let Ok(tkey) = Key::try_from_utf8(subtag) { - current_tkey = Some(tkey); - } else { - break; - } - - iter.next(); - } - - if let Some(tkey) = current_tkey { - if !has_current_tvalue { - return Err(ParseError::InvalidExtension); - } - tfields.try_insert(tkey, Value::from_short_slice_unchecked(current_tvalue)); - } - - if tlang.is_none() && tfields.is_empty() { - Err(ParseError::InvalidExtension) - } else { - Ok(Self { - lang: tlang, - fields: tfields.into(), - }) - } - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F, with_ext: bool) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - if self.is_empty() { - return Ok(()); - } - if with_ext { - f(TRANSFORM_EXT_STR)?; - } - if let Some(lang) = &self.lang { - lang.for_each_subtag_str_lowercased(f)?; - } - self.fields.for_each_subtag_str(f) - } -} - -#[cfg(feature = "alloc")] -impl FromStr for Transform { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -writeable::impl_display_with_writeable!(Transform); - -impl writeable::Writeable for Transform { - fn write_to(&self, sink: &mut W) -> core::fmt::Result { - if self.is_empty() { - return Ok(()); - } - sink.write_char(TRANSFORM_EXT_CHAR)?; - if let Some(lang) = &self.lang { - sink.write_char('-')?; - lang.write_lowercased_to(sink)?; - } - if !self.fields.is_empty() { - sink.write_char('-')?; - writeable::Writeable::write_to(&self.fields, sink)?; - } - Ok(()) - } - - fn writeable_length_hint(&self) -> writeable::LengthHint { - if self.is_empty() { - return writeable::LengthHint::exact(0); - } - let mut result = writeable::LengthHint::exact(1); - if let Some(lang) = &self.lang { - result += writeable::Writeable::writeable_length_hint(lang) + 1; - } - if !self.fields.is_empty() { - result += writeable::Writeable::writeable_length_hint(&self.fields) + 1; - } - result - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_transform_extension_fromstr() { - let te: Transform = "t-en-us-h0-hybrid" - .parse() - .expect("Failed to parse Transform"); - assert_eq!(te.to_string(), "t-en-us-h0-hybrid"); - - let te: Result = "t".parse(); - assert!(te.is_err()); - } -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/transform/value.rs b/deps/crates/vendor/icu_locale_core/src/extensions/transform/value.rs deleted file mode 100644 index 3a54f739dd1b92..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/transform/value.rs +++ /dev/null @@ -1,160 +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 crate::parser::ParseError; -#[cfg(feature = "alloc")] -use crate::parser::SubtagIterator; -use crate::shortvec::ShortBoxSlice; -use crate::subtags::{subtag, Subtag}; -use core::ops::RangeInclusive; -#[cfg(feature = "alloc")] -use core::str::FromStr; - -/// A value used in a list of [`Fields`](super::Fields). -/// -/// The value has to be a sequence of one or more alphanumerical strings -/// separated by `-`. -/// Each part of the sequence has to be no shorter than three characters and no -/// longer than 8. -/// -/// # Examples -/// -/// ``` -/// use icu::locale::extensions::transform::Value; -/// -/// "hybrid".parse::().expect("Valid Value."); -/// -/// "hybrid-foobar".parse::().expect("Valid Value."); -/// -/// "no".parse::().expect_err("Invalid Value."); -/// ``` -#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Default)] -pub struct Value(ShortBoxSlice); - -#[allow(dead_code)] -const TYPE_LENGTH: RangeInclusive = 3..=8; -const TRUE_TVALUE: Subtag = subtag!("true"); - -impl Value { - /// A constructor which takes a str slice, parses it and - /// produces a well-formed [`Value`]. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::transform::Value; - /// - /// let value = Value::try_from_str("hybrid").expect("Parsing failed."); - /// ``` - #[inline] - #[cfg(feature = "alloc")] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - let mut v = ShortBoxSlice::default(); - let mut has_value = false; - - for subtag in SubtagIterator::new(code_units) { - if !Self::is_type_subtag(subtag) { - return Err(ParseError::InvalidExtension); - } - has_value = true; - let val = Subtag::try_from_utf8(subtag).map_err(|_| ParseError::InvalidExtension)?; - if val != TRUE_TVALUE { - v.push(val); - } - } - - if !has_value { - return Err(ParseError::InvalidExtension); - } - Ok(Self(v)) - } - - #[allow(dead_code)] - pub(crate) fn from_short_slice_unchecked(input: ShortBoxSlice) -> Self { - Self(input) - } - - #[allow(dead_code)] - pub(crate) fn is_type_subtag(t: &[u8]) -> bool { - TYPE_LENGTH.contains(&t.len()) && t.iter().all(u8::is_ascii_alphanumeric) - } - - #[allow(dead_code)] - pub(crate) fn parse_subtag(t: &[u8]) -> Result, ParseError> { - if !TYPE_LENGTH.contains(&t.len()) { - return Err(ParseError::InvalidExtension); - } - let s = Subtag::try_from_utf8(t).map_err(|_| ParseError::InvalidSubtag)?; - - let s = s.to_ascii_lowercase(); - - if s == TRUE_TVALUE { - Ok(None) - } else { - Ok(Some(s)) - } - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - if self.0.is_empty() { - f(TRUE_TVALUE.as_str())?; - } else { - self.0.iter().map(Subtag::as_str).try_for_each(f)?; - } - Ok(()) - } -} - -#[cfg(feature = "alloc")] -impl FromStr for Value { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -impl_writeable_for_each_subtag_str_no_test!(Value, selff, selff.0.is_empty() => alloc::borrow::Cow::Borrowed("true")); - -#[test] -fn test_writeable() { - use writeable::assert_writeable_eq; - - let hybrid = "hybrid".parse().unwrap(); - let foobar = "foobar".parse().unwrap(); - - assert_writeable_eq!(Value::default(), "true"); - assert_writeable_eq!( - Value::from_short_slice_unchecked(vec![hybrid].into()), - "hybrid" - ); - assert_writeable_eq!( - Value::from_short_slice_unchecked(vec![hybrid, foobar].into()), - "hybrid-foobar" - ); -} - -#[test] -fn test_short_tvalue() { - let value = Value::try_from_str("foo-longstag"); - assert!(value.is_ok()); - let value = value.unwrap(); - assert_eq!(value.0.len(), 2); - for (s, reference) in value.0.iter().zip(&[subtag!("foo"), subtag!("longstag")]) { - assert_eq!(s, reference); - } - - let value = Value::try_from_str("foo-ba"); - assert!(value.is_err()); -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attribute.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attribute.rs deleted file mode 100644 index 8430fbbeeae177..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attribute.rs +++ /dev/null @@ -1,34 +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 ). - -impl_tinystr_subtag!( - /// An attribute used in a set of [`Attributes`](super::Attributes). - /// - /// An attribute has to be a sequence of alphanumerical characters no - /// shorter than three and no longer than eight characters. - /// - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::{attribute, Attribute}; - /// - /// let attr: Attribute = - /// "buddhist".parse().expect("Failed to parse an Attribute."); - /// - /// assert_eq!(attr, attribute!("buddhist")); - /// ``` - Attribute, - extensions::unicode, - attribute, - extensions_unicode_attribute, - 3..=8, - s, - s.is_ascii_alphanumeric(), - s.to_ascii_lowercase(), - s.is_ascii_alphanumeric() && s.is_ascii_lowercase(), - InvalidExtension, - ["foo12"], - ["no", "toolooong"], -); diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attributes.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attributes.rs deleted file mode 100644 index 7ca0fecfcfc212..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/attributes.rs +++ /dev/null @@ -1,177 +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::Attribute; - -#[cfg(feature = "alloc")] -use crate::parser::SubtagIterator; -use crate::shortvec::ShortBoxSlice; -#[cfg(feature = "alloc")] -use crate::ParseError; -#[cfg(feature = "alloc")] -use alloc::vec::Vec; -use core::ops::Deref; -#[cfg(feature = "alloc")] -use core::str::FromStr; - -/// A set of [`Attribute`] elements as defined in [`Unicode Extension Attributes`]. -/// -/// [`Unicode Extension Attributes`]: https://unicode.org/reports/tr35/tr35.html#u_Extension -/// -/// # Examples -/// -/// ``` -/// use icu::locale::extensions::unicode::{Attribute, Attributes}; -/// -/// let attribute1: Attribute = -/// "foobar".parse().expect("Failed to parse a variant subtag."); -/// -/// let attribute2: Attribute = "testing" -/// .parse() -/// .expect("Failed to parse a variant subtag."); -/// let mut v = vec![attribute1, attribute2]; -/// v.sort(); -/// v.dedup(); -/// -/// let attributes: Attributes = Attributes::from_vec_unchecked(v); -/// assert_eq!(attributes.to_string(), "foobar-testing"); -/// ``` -#[derive(Default, Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord)] -pub struct Attributes(ShortBoxSlice); - -impl Attributes { - /// Returns a new empty set of attributes. Same as [`default()`](Default::default()), but is `const`. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::Attributes; - /// - /// assert_eq!(Attributes::new(), Attributes::default()); - /// ``` - #[inline] - pub const fn new() -> Self { - Self(ShortBoxSlice::new()) - } - - /// A constructor which takes a str slice, parses it and - /// produces a well-formed [`Attributes`]. - #[inline] - #[cfg(feature = "alloc")] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - let mut iter = SubtagIterator::new(code_units); - Self::try_from_iter(&mut iter) - } - - /// A constructor which takes a pre-sorted list of [`Attribute`] elements. - /// - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::{Attribute, Attributes}; - /// - /// let attribute1: Attribute = "foobar".parse().expect("Parsing failed."); - /// let attribute2: Attribute = "testing".parse().expect("Parsing failed."); - /// let mut v = vec![attribute1, attribute2]; - /// v.sort(); - /// v.dedup(); - /// - /// let attributes = Attributes::from_vec_unchecked(v); - /// ``` - /// - /// Notice: For performance- and memory-constrained environments, it is recommended - /// for the caller to use [`binary_search`](slice::binary_search) instead of [`sort`](slice::sort) - /// and [`dedup`](Vec::dedup()). - #[cfg(feature = "alloc")] - pub fn from_vec_unchecked(input: Vec) -> Self { - Self(input.into()) - } - - /// Empties the [`Attributes`] list. - /// - /// Returns the old list. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::{attribute, Attributes}; - /// use writeable::assert_writeable_eq; - /// - /// let mut attributes = Attributes::from_vec_unchecked(vec![ - /// attribute!("foobar"), - /// attribute!("testing"), - /// ]); - /// - /// assert_writeable_eq!(attributes, "foobar-testing"); - /// - /// attributes.clear(); - /// - /// assert_writeable_eq!(attributes, ""); - /// ``` - pub fn clear(&mut self) -> Self { - core::mem::take(self) - } - - #[cfg(feature = "alloc")] - pub(crate) fn try_from_iter(iter: &mut SubtagIterator) -> Result { - let mut attributes = ShortBoxSlice::new(); - - while let Some(subtag) = iter.peek() { - if let Ok(attr) = Attribute::try_from_utf8(subtag) { - if let Err(idx) = attributes.binary_search(&attr) { - attributes.insert(idx, attr); - } - } else { - break; - } - iter.next(); - } - Ok(Self(attributes)) - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - self.deref().iter().map(|t| t.as_str()).try_for_each(f) - } -} - -#[cfg(feature = "alloc")] -impl FromStr for Attributes { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -impl_writeable_for_subtag_list!(Attributes, "foobar", "testing"); - -impl Deref for Attributes { - type Target = [Attribute]; - - fn deref(&self) -> &[Attribute] { - self.0.deref() - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_attributes_fromstr() { - let attrs: Attributes = "foo-bar".parse().expect("Failed to parse Attributes"); - assert_eq!(attrs.to_string(), "bar-foo"); - } -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/key.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/key.rs deleted file mode 100644 index 9192a89c765386..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/key.rs +++ /dev/null @@ -1,32 +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 ). - -impl_tinystr_subtag!( - /// A key used in a list of [`Keywords`](super::Keywords). - /// - /// The key has to be a two ASCII alphanumerical characters long, with the first - /// character being alphanumeric, and the second being alphabetic. - /// - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::Key; - /// - /// assert!("ca".parse::().is_ok()); - /// ``` - Key, - extensions::unicode, - key, - extensions_unicode_key, - 2..=2, - s, - s.all_bytes()[0].is_ascii_alphanumeric() && s.all_bytes()[1].is_ascii_alphabetic(), - s.to_ascii_lowercase(), - (s.all_bytes()[0].is_ascii_lowercase() || s.all_bytes()[0].is_ascii_digit()) - && s.all_bytes()[1].is_ascii_lowercase(), - InvalidExtension, - ["ca", "8a"], - ["a", "a8", "abc"], -); diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/keywords.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/keywords.rs deleted file mode 100644 index 726b5490efc52b..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/keywords.rs +++ /dev/null @@ -1,418 +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 core::borrow::Borrow; -use core::cmp::Ordering; -#[cfg(feature = "alloc")] -use core::iter::FromIterator; -#[cfg(feature = "alloc")] -use core::str::FromStr; -use litemap::LiteMap; - -use super::Key; -use super::Value; -#[cfg(feature = "alloc")] -use crate::parser::ParseError; -#[cfg(feature = "alloc")] -use crate::parser::SubtagIterator; -use crate::shortvec::ShortBoxSlice; - -/// A list of [`Key`]-[`Value`] pairs representing functional information -/// about locale's internationalization preferences. -/// -/// Here are examples of fields used in Unicode: -/// - `hc` - Hour Cycle (`h11`, `h12`, `h23`, `h24`) -/// - `ca` - Calendar (`buddhist`, `gregory`, ...) -/// - `fw` - First Day Of the Week (`sun`, `mon`, `sat`, ...) -/// -/// You can find the full list in [`Unicode BCP 47 U Extension`] section of LDML. -/// -/// [`Unicode BCP 47 U Extension`]: https://unicode.org/reports/tr35/tr35.html#Key_And_Type_Definitions_ -/// -/// # Examples -/// -/// Manually build up a [`Keywords`] object: -/// -/// ``` -/// use icu::locale::extensions::unicode::{key, value, Keywords}; -/// -/// let keywords = [(key!("hc"), value!("h23"))] -/// .into_iter() -/// .collect::(); -/// -/// assert_eq!(&keywords.to_string(), "hc-h23"); -/// ``` -/// -/// Access a [`Keywords`] object from a [`Locale`]: -/// -/// ``` -/// use icu::locale::{ -/// extensions::unicode::{key, value}, -/// Locale, -/// }; -/// -/// let loc: Locale = "und-u-hc-h23-kc-true".parse().expect("Valid BCP-47"); -/// -/// assert_eq!(loc.extensions.unicode.keywords.get(&key!("ca")), None); -/// assert_eq!( -/// loc.extensions.unicode.keywords.get(&key!("hc")), -/// Some(&value!("h23")) -/// ); -/// assert_eq!( -/// loc.extensions.unicode.keywords.get(&key!("kc")), -/// Some(&value!("true")) -/// ); -/// -/// assert_eq!(loc.extensions.unicode.keywords.to_string(), "hc-h23-kc"); -/// ``` -/// -/// [`Locale`]: crate::Locale -#[derive(Clone, PartialEq, Eq, Debug, Default, Hash, PartialOrd, Ord)] -pub struct Keywords(LiteMap>); - -impl Keywords { - /// Returns a new empty list of key-value pairs. Same as [`default()`](Default::default()), but is `const`. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::Keywords; - /// - /// assert_eq!(Keywords::new(), Keywords::default()); - /// ``` - #[inline] - pub const fn new() -> Self { - Self(LiteMap::new()) - } - - /// Create a new list of key-value pairs having exactly one pair, callable in a `const` context. - #[inline] - pub const fn new_single(key: Key, value: Value) -> Self { - Self(LiteMap::from_sorted_store_unchecked( - ShortBoxSlice::new_single((key, value)), - )) - } - - /// A constructor which takes a str slice, parses it and - /// produces a well-formed [`Keywords`]. - #[inline] - #[cfg(feature = "alloc")] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - let mut iter = SubtagIterator::new(code_units); - Self::try_from_iter(&mut iter) - } - - /// Returns `true` if there are no keywords. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::locale; - /// use icu::locale::Locale; - /// - /// let loc1 = Locale::try_from_str("und-t-h0-hybrid").unwrap(); - /// let loc2 = locale!("und-u-ca-buddhist"); - /// - /// assert!(loc1.extensions.unicode.keywords.is_empty()); - /// assert!(!loc2.extensions.unicode.keywords.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Returns `true` if the list contains a [`Value`] for the specified [`Key`]. - /// - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::{key, value, Keywords}; - /// - /// let keywords = [(key!("ca"), value!("gregory"))] - /// .into_iter() - /// .collect::(); - /// - /// assert!(&keywords.contains_key(&key!("ca"))); - /// ``` - pub fn contains_key(&self, key: &Q) -> bool - where - Key: Borrow, - Q: Ord, - { - self.0.contains_key(key) - } - - /// Returns a reference to the [`Value`] corresponding to the [`Key`]. - /// - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::{key, value, Keywords}; - /// - /// let keywords = [(key!("ca"), value!("buddhist"))] - /// .into_iter() - /// .collect::(); - /// - /// assert_eq!(keywords.get(&key!("ca")), Some(&value!("buddhist"))); - /// ``` - pub fn get(&self, key: &Q) -> Option<&Value> - where - Key: Borrow, - Q: Ord, - { - self.0.get(key) - } - - /// Returns a mutable reference to the [`Value`] corresponding to the [`Key`]. - /// - /// Returns `None` if the key doesn't exist or if the key has no value. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::{key, value, Keywords}; - /// - /// let mut keywords = [(key!("ca"), value!("buddhist"))] - /// .into_iter() - /// .collect::(); - /// - /// if let Some(value) = keywords.get_mut(&key!("ca")) { - /// *value = value!("gregory"); - /// } - /// assert_eq!(keywords.get(&key!("ca")), Some(&value!("gregory"))); - /// ``` - #[cfg(feature = "alloc")] - pub fn get_mut(&mut self, key: &Q) -> Option<&mut Value> - where - Key: Borrow, - Q: Ord, - { - self.0.get_mut(key) - } - - /// Sets the specified keyword, returning the old value if it already existed. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::{key, value}; - /// use icu::locale::Locale; - /// - /// let mut loc: Locale = "und-u-hello-ca-buddhist-hc-h12" - /// .parse() - /// .expect("valid BCP-47 identifier"); - /// let old_value = loc - /// .extensions - /// .unicode - /// .keywords - /// .set(key!("ca"), value!("japanese")); - /// - /// assert_eq!(old_value, Some(value!("buddhist"))); - /// assert_eq!(loc, "und-u-hello-ca-japanese-hc-h12".parse().unwrap()); - /// ``` - #[cfg(feature = "alloc")] - pub fn set(&mut self, key: Key, value: Value) -> Option { - self.0.insert(key, value) - } - - /// Removes the specified keyword, returning the old value if it existed. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::key; - /// use icu::locale::Locale; - /// - /// let mut loc: Locale = "und-u-hello-ca-buddhist-hc-h12" - /// .parse() - /// .expect("valid BCP-47 identifier"); - /// loc.extensions.unicode.keywords.remove(key!("ca")); - /// assert_eq!(loc, "und-u-hello-hc-h12".parse().unwrap()); - /// ``` - #[cfg(feature = "alloc")] - pub fn remove>(&mut self, key: Q) -> Option { - self.0.remove(key.borrow()) - } - - /// Clears all Unicode extension keywords, leaving Unicode attributes. - /// - /// Returns the old Unicode extension keywords. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::Locale; - /// - /// let mut loc: Locale = "und-u-hello-ca-buddhist-hc-h12".parse().unwrap(); - /// loc.extensions.unicode.keywords.clear(); - /// assert_eq!(loc, "und-u-hello".parse().unwrap()); - /// ``` - pub fn clear(&mut self) -> Self { - core::mem::take(self) - } - - /// Retains a subset of keywords as specified by the predicate function. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::key; - /// use icu::locale::Locale; - /// - /// let mut loc: Locale = "und-u-ca-buddhist-hc-h12-ms-metric".parse().unwrap(); - /// - /// loc.extensions - /// .unicode - /// .keywords - /// .retain_by_key(|&k| k == key!("hc")); - /// assert_eq!(loc, "und-u-hc-h12".parse().unwrap()); - /// - /// loc.extensions - /// .unicode - /// .keywords - /// .retain_by_key(|&k| k == key!("ms")); - /// assert_eq!(loc, Locale::UNKNOWN); - /// ``` - #[cfg(feature = "alloc")] - pub fn retain_by_key(&mut self, mut predicate: F) - where - F: FnMut(&Key) -> bool, - { - self.0.retain(|k, _| predicate(k)) - } - - /// Compare this [`Keywords`] with BCP-47 bytes. - /// - /// The return value is equivalent to what would happen if you first converted this - /// [`Keywords`] to a BCP-47 string and then performed a byte comparison. - /// - /// This function is case-sensitive and results in a *total order*, so it is appropriate for - /// binary search. The only argument producing [`Ordering::Equal`] is `self.to_string()`. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::Locale; - /// use std::cmp::Ordering; - /// - /// let bcp47_strings: &[&str] = - /// &["ca-hebrew", "ca-japanese", "ca-japanese-nu-latn", "nu-latn"]; - /// - /// for ab in bcp47_strings.windows(2) { - /// let a = ab[0]; - /// let b = ab[1]; - /// assert!(a.cmp(b) == Ordering::Less); - /// let a_kwds = format!("und-u-{}", a) - /// .parse::() - /// .unwrap() - /// .extensions - /// .unicode - /// .keywords; - /// assert!(a_kwds.strict_cmp(a.as_bytes()) == Ordering::Equal); - /// assert!(a_kwds.strict_cmp(b.as_bytes()) == Ordering::Less); - /// } - /// ``` - pub fn strict_cmp(&self, other: &[u8]) -> Ordering { - writeable::cmp_utf8(self, other) - } - - #[cfg(feature = "alloc")] - pub(crate) fn try_from_iter(iter: &mut SubtagIterator) -> Result { - let mut keywords = LiteMap::new(); - - let mut current_keyword = None; - let mut current_value = ShortBoxSlice::new(); - - while let Some(subtag) = iter.peek() { - let slen = subtag.len(); - if slen == 2 { - if let Some(kw) = current_keyword.take() { - keywords.try_insert(kw, Value::from_short_slice_unchecked(current_value)); - current_value = ShortBoxSlice::new(); - } - current_keyword = Some(Key::try_from_utf8(subtag)?); - } else if current_keyword.is_some() { - match Value::parse_subtag_from_utf8(subtag) { - Ok(Some(t)) => current_value.push(t), - Ok(None) => {} - Err(_) => break, - } - } else { - break; - } - iter.next(); - } - - if let Some(kw) = current_keyword.take() { - keywords.try_insert(kw, Value::from_short_slice_unchecked(current_value)); - } - - Ok(keywords.into()) - } - - /// Produce an ordered iterator over key-value pairs - pub fn iter(&self) -> impl Iterator { - self.0.iter() - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - for (k, v) in self.0.iter() { - f(k.as_str())?; - v.for_each_subtag_str(f)?; - } - Ok(()) - } - - /// This needs to be its own method to help with type inference in helpers.rs - #[cfg(test)] - pub(crate) fn from_tuple_vec(v: Vec<(Key, Value)>) -> Self { - v.into_iter().collect() - } -} - -impl From>> for Keywords { - fn from(map: LiteMap>) -> Self { - Self(map) - } -} - -#[cfg(feature = "alloc")] -impl FromIterator<(Key, Value)> for Keywords { - fn from_iter>(iter: I) -> Self { - LiteMap::from_iter(iter).into() - } -} - -#[cfg(feature = "alloc")] -impl FromStr for Keywords { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -impl_writeable_for_key_value!(Keywords, "ca", "islamic-civil", "mm", "mm"); - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_keywords_fromstr() { - let kw: Keywords = "hc-h12".parse().expect("Failed to parse Keywords"); - assert_eq!(kw.to_string(), "hc-h12"); - } -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/mod.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/mod.rs deleted file mode 100644 index f51593548ba3b5..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/mod.rs +++ /dev/null @@ -1,269 +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 ). - -//! Unicode Extensions provide information about user preferences in a given locale. -//! -//! The main struct for this extension is [`Unicode`] which contains [`Keywords`] and -//! [`Attributes`]. -//! -//! -//! # Examples -//! -//! ``` -//! use icu::locale::extensions::unicode::{attribute, key, value, Unicode}; -//! use icu::locale::Locale; -//! -//! let loc: Locale = "en-US-u-foobar-hc-h12".parse().expect("Parsing failed."); -//! -//! assert_eq!( -//! loc.extensions.unicode.keywords.get(&key!("hc")), -//! Some(&value!("h12")) -//! ); -//! assert!(loc -//! .extensions -//! .unicode -//! .attributes -//! .contains(&attribute!("foobar"))); -//! ``` -mod attribute; -mod attributes; -mod key; -mod keywords; -mod subdivision; -mod value; - -use core::cmp::Ordering; -#[cfg(feature = "alloc")] -use core::str::FromStr; - -#[doc(inline)] -pub use attribute::{attribute, Attribute}; -pub use attributes::Attributes; -#[doc(inline)] -pub use key::{key, Key}; -pub use keywords::Keywords; -#[doc(inline)] -pub use subdivision::{subdivision_suffix, SubdivisionId, SubdivisionSuffix}; -#[doc(inline)] -pub use value::{value, Value}; - -#[cfg(feature = "alloc")] -use super::ExtensionType; -#[cfg(feature = "alloc")] -use crate::parser::ParseError; -#[cfg(feature = "alloc")] -use crate::parser::SubtagIterator; - -pub(crate) const UNICODE_EXT_CHAR: char = 'u'; -pub(crate) const UNICODE_EXT_STR: &str = "u"; - -/// Unicode Extensions provide information about user preferences in a given locale. -/// -/// A list of [`Unicode BCP47 U Extensions`] as defined in [`Unicode Locale -/// Identifier`] specification. -/// -/// Unicode extensions provide subtags that specify language and/or locale-based behavior -/// or refinements to language tags, according to work done by the Unicode Consortium. -/// (See [`RFC 6067`] for details). -/// -/// [`Unicode BCP47 U Extensions`]: https://unicode.org/reports/tr35/#u_Extension -/// [`RFC 6067`]: https://www.ietf.org/rfc/rfc6067.txt -/// [`Unicode Locale Identifier`]: https://unicode.org/reports/tr35/#Unicode_locale_identifier -/// -/// # Examples -/// -/// ``` -/// use icu::locale::extensions::unicode::{key, value}; -/// use icu::locale::Locale; -/// -/// let loc: Locale = -/// "de-u-hc-h12-ca-buddhist".parse().expect("Parsing failed."); -/// -/// assert_eq!( -/// loc.extensions.unicode.keywords.get(&key!("ca")), -/// Some(&value!("buddhist")) -/// ); -/// ``` -#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] -#[allow(clippy::exhaustive_structs)] // spec-backed stable datastructure -pub struct Unicode { - /// The key-value pairs present in this locale extension, with each extension key subtag - /// associated to its provided value subtag. - pub keywords: Keywords, - /// A canonically ordered sequence of single standalone subtags for this locale extension. - pub attributes: Attributes, -} - -impl Unicode { - /// Returns a new empty map of Unicode extensions. Same as [`default()`](Default::default()), but is `const`. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::Unicode; - /// - /// assert_eq!(Unicode::new(), Unicode::default()); - /// ``` - #[inline] - pub const fn new() -> Self { - Self { - keywords: Keywords::new(), - attributes: Attributes::new(), - } - } - - /// A constructor which takes a str slice, parses it and - /// produces a well-formed [`Unicode`]. - #[inline] - #[cfg(feature = "alloc")] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - let mut iter = SubtagIterator::new(code_units); - - let ext = iter.next().ok_or(ParseError::InvalidExtension)?; - if let ExtensionType::Unicode = ExtensionType::try_from_byte_slice(ext)? { - return Self::try_from_iter(&mut iter); - } - - Err(ParseError::InvalidExtension) - } - - /// Returns [`true`] if there list of keywords and attributes is empty. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::Locale; - /// - /// let loc: Locale = "en-US-u-foo".parse().expect("Parsing failed."); - /// - /// assert!(!loc.extensions.unicode.is_empty()); - /// ``` - pub fn is_empty(&self) -> bool { - self.keywords.is_empty() && self.attributes.is_empty() - } - - /// Clears all Unicode extension keywords and attributes, effectively removing - /// the Unicode extension. - /// - /// # Example - /// - /// ``` - /// use icu::locale::Locale; - /// - /// let mut loc: Locale = - /// "und-t-mul-u-hello-ca-buddhist-hc-h12".parse().unwrap(); - /// loc.extensions.unicode.clear(); - /// assert_eq!(loc, "und-t-mul".parse().unwrap()); - /// ``` - pub fn clear(&mut self) { - self.keywords.clear(); - self.attributes.clear(); - } - - pub(crate) fn as_tuple(&self) -> (&Attributes, &Keywords) { - (&self.attributes, &self.keywords) - } - - /// Returns an ordering suitable for use in [`BTreeSet`]. - /// - /// The ordering may or may not be equivalent to string ordering, and it - /// may or may not be stable across ICU4X releases. - /// - /// [`BTreeSet`]: alloc::collections::BTreeSet - pub fn total_cmp(&self, other: &Self) -> Ordering { - self.as_tuple().cmp(&other.as_tuple()) - } - - #[cfg(feature = "alloc")] - pub(crate) fn try_from_iter(iter: &mut SubtagIterator) -> Result { - let attributes = Attributes::try_from_iter(iter)?; - let keywords = Keywords::try_from_iter(iter)?; - - // Ensure we've defined at least one attribute or keyword - if attributes.is_empty() && keywords.is_empty() { - return Err(ParseError::InvalidExtension); - } - - Ok(Self { - keywords, - attributes, - }) - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F, with_ext: bool) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - if !self.is_empty() { - if with_ext { - f(UNICODE_EXT_STR)?; - } - self.attributes.for_each_subtag_str(f)?; - self.keywords.for_each_subtag_str(f)?; - } - Ok(()) - } -} - -#[cfg(feature = "alloc")] -impl FromStr for Unicode { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -writeable::impl_display_with_writeable!(Unicode); - -impl writeable::Writeable for Unicode { - fn write_to(&self, sink: &mut W) -> core::fmt::Result { - sink.write_char(UNICODE_EXT_CHAR)?; - - if !self.attributes.is_empty() { - sink.write_char('-')?; - writeable::Writeable::write_to(&self.attributes, sink)?; - } - if !self.keywords.is_empty() { - sink.write_char('-')?; - writeable::Writeable::write_to(&self.keywords, sink)?; - } - Ok(()) - } - - fn writeable_length_hint(&self) -> writeable::LengthHint { - if self.is_empty() { - return writeable::LengthHint::exact(0); - } - let mut result = writeable::LengthHint::exact(1); - if !self.attributes.is_empty() { - result += writeable::Writeable::writeable_length_hint(&self.attributes) + 1; - } - if !self.keywords.is_empty() { - result += writeable::Writeable::writeable_length_hint(&self.keywords) + 1; - } - result - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_unicode_extension_fromstr() { - let ue: Unicode = "u-foo-hc-h12".parse().expect("Failed to parse Unicode"); - assert_eq!(ue.to_string(), "u-foo-hc-h12"); - - let ue: Result = "u".parse(); - assert!(ue.is_err()); - } -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/subdivision.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/subdivision.rs deleted file mode 100644 index 5855fed7fc09d4..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/subdivision.rs +++ /dev/null @@ -1,181 +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 core::str::FromStr; - -use crate::parser::ParseError; -use crate::subtags::{Region, Subtag}; - -impl_tinystr_subtag!( - /// A subdivision suffix used in [`SubdivisionId`]. - /// - /// This suffix represents a specific subdivision code under a given [`Region`]. - /// For example the value of [`SubdivisionId`] may be `gbsct`, where the [`SubdivisionSuffix`] - /// is `sct` for Scotland. - /// - /// Such a value associated with a key `rg` means that the locale should use Unit Preferences - /// (default calendar, currency, week data, time cycle, measurement system) for Scotland, even if the - /// [`LanguageIdentifier`](crate::LanguageIdentifier) is `en-US`. - /// - /// A subdivision suffix has to be a sequence of alphanumerical characters no - /// shorter than one and no longer than four characters. - /// - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::{subdivision_suffix, SubdivisionSuffix}; - /// - /// let ss: SubdivisionSuffix = - /// "sct".parse().expect("Failed to parse a SubdivisionSuffix."); - /// - /// assert_eq!(ss, subdivision_suffix!("sct")); - /// ``` - SubdivisionSuffix, - extensions::unicode, - subdivision_suffix, - extensions_unicode_subdivision_suffix, - 1..=4, - s, - s.is_ascii_alphanumeric(), - s.to_ascii_lowercase(), - s.is_ascii_alphanumeric() && s.is_ascii_lowercase(), - InvalidExtension, - ["sct"], - ["toolooong"], -); - -/// A Subivision Id as defined in [`Unicode Locale Identifier`]. -/// -/// Subdivision Id is used in [`Unicode`] extensions: -/// * `rg` - Regional Override -/// * `sd` - Regional Subdivision -/// -/// In both cases the subdivision is composed of a [`Region`] and a [`SubdivisionSuffix`] which represents -/// different meaning depending on the key. -/// -/// [`Unicode Locale Identifier`]: https://unicode.org/reports/tr35/tr35.html#unicode_subdivision_id -/// [`Unicode`]: crate::extensions::unicode::Unicode -/// -/// # Examples -/// -/// ``` -/// use icu::locale::{ -/// extensions::unicode::{subdivision_suffix, SubdivisionId}, -/// subtags::region, -/// }; -/// -/// let ss = subdivision_suffix!("zzzz"); -/// let region = region!("gb"); -/// -/// let si = SubdivisionId::new(region, ss); -/// -/// assert_eq!(si.to_string(), "gbzzzz"); -/// ``` -#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Copy)] -#[non_exhaustive] -pub struct SubdivisionId { - /// A region field of a Subdivision Id. - pub region: Region, - /// A subdivision suffix field of a Subdivision Id. - pub suffix: SubdivisionSuffix, -} - -impl SubdivisionId { - /// Returns a new [`SubdivisionId`]. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::{ - /// extensions::unicode::{subdivision_suffix, SubdivisionId}, - /// subtags::region, - /// }; - /// - /// let ss = subdivision_suffix!("zzzz"); - /// let region = region!("gb"); - /// - /// let si = SubdivisionId::new(region, ss); - /// - /// assert_eq!(si.to_string(), "gbzzzz"); - /// ``` - pub const fn new(region: Region, suffix: SubdivisionSuffix) -> Self { - Self { region, suffix } - } - - /// A constructor which takes a str slice, parses it and - /// produces a well-formed [`SubdivisionId`]. - #[inline] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - let is_alpha = code_units - .first() - .and_then(|b| { - b.is_ascii_alphabetic() - .then_some(true) - .or_else(|| b.is_ascii_digit().then_some(false)) - }) - .ok_or(ParseError::InvalidExtension)?; - let region_len = if is_alpha { 2 } else { 3 }; - let (region_code_units, suffix_code_units) = code_units - .split_at_checked(region_len) - .ok_or(ParseError::InvalidExtension)?; - let region = - Region::try_from_utf8(region_code_units).map_err(|_| ParseError::InvalidExtension)?; - let suffix = SubdivisionSuffix::try_from_utf8(suffix_code_units)?; - Ok(Self { region, suffix }) - } - - /// Convert to [`Subtag`] - pub fn into_subtag(self) -> Subtag { - let result = self.region.to_tinystr().concat(self.suffix.to_tinystr()); - Subtag::from_tinystr_unvalidated(result) - } -} - -impl writeable::Writeable for SubdivisionId { - #[inline] - fn write_to(&self, sink: &mut W) -> core::fmt::Result { - sink.write_str(self.region.to_tinystr().to_ascii_lowercase().as_str())?; - sink.write_str(self.suffix.as_str()) - } - - #[inline] - fn writeable_length_hint(&self) -> writeable::LengthHint { - self.region.writeable_length_hint() + self.suffix.writeable_length_hint() - } -} - -writeable::impl_display_with_writeable!(SubdivisionId); - -impl FromStr for SubdivisionId { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_subdivisionid_fromstr() { - let si: SubdivisionId = "gbzzzz".parse().expect("Failed to parse SubdivisionId"); - assert_eq!(si.region.to_string(), "GB"); - assert_eq!(si.suffix.to_string(), "zzzz"); - assert_eq!(si.to_string(), "gbzzzz"); - - for sample in ["", "gb", "o"] { - let oe: Result = sample.parse(); - assert!(oe.is_err(), "Should fail: {}", sample); - } - } -} diff --git a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/value.rs b/deps/crates/vendor/icu_locale_core/src/extensions/unicode/value.rs deleted file mode 100644 index c2f3381078da5a..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/extensions/unicode/value.rs +++ /dev/null @@ -1,354 +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 crate::parser::ParseError; -#[cfg(feature = "alloc")] -use crate::parser::SubtagIterator; -use crate::shortvec::{ShortBoxSlice, ShortBoxSliceIntoIter}; -use crate::subtags::{subtag, Subtag}; -#[cfg(feature = "alloc")] -use alloc::vec::Vec; -#[cfg(feature = "alloc")] -use core::str::FromStr; - -/// A value used in a list of [`Keywords`](super::Keywords). -/// -/// The value has to be a sequence of one or more alphanumerical strings -/// separated by `-`. -/// Each part of the sequence has to be no shorter than three characters and no -/// longer than 8. -/// -/// -/// # Examples -/// -/// ``` -/// use icu::locale::extensions::unicode::{value, Value}; -/// use writeable::assert_writeable_eq; -/// -/// assert_writeable_eq!(value!("gregory"), "gregory"); -/// assert_writeable_eq!( -/// "islamic-civil".parse::().unwrap(), -/// "islamic-civil" -/// ); -/// -/// // The value "true" has the special, empty string representation -/// assert_eq!(value!("true").to_string(), ""); -/// ``` -#[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Default)] -pub struct Value(ShortBoxSlice); - -const TRUE_VALUE: Subtag = subtag!("true"); - -impl Value { - /// A constructor which str slice, parses it and - /// produces a well-formed [`Value`]. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::Value; - /// - /// Value::try_from_str("buddhist").expect("Parsing failed."); - /// ``` - #[inline] - #[cfg(feature = "alloc")] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - let mut v = ShortBoxSlice::new(); - - if !code_units.is_empty() { - for chunk in SubtagIterator::new(code_units) { - let subtag = Subtag::try_from_utf8(chunk)?; - if subtag != TRUE_VALUE { - v.push(subtag); - } - } - } - Ok(Self(v)) - } - - /// Returns a reference to a single [`Subtag`] if the [`Value`] contains exactly one - /// subtag, or `None` otherwise. - /// - /// # Examples - /// - /// ``` - /// use core::str::FromStr; - /// use icu::locale::extensions::unicode::Value; - /// - /// let value1 = Value::from_str("foo").expect("failed to parse a Value"); - /// let value2 = Value::from_str("foo-bar").expect("failed to parse a Value"); - /// - /// assert!(value1.as_single_subtag().is_some()); - /// assert!(value2.as_single_subtag().is_none()); - /// ``` - pub const fn as_single_subtag(&self) -> Option<&Subtag> { - self.0.single() - } - - /// Destructs into a single [`Subtag`] if the [`Value`] contains exactly one - /// subtag, or returns `None` otherwise. - /// - /// # Examples - /// - /// ``` - /// use core::str::FromStr; - /// use icu::locale::extensions::unicode::Value; - /// - /// let value1 = Value::from_str("foo").expect("failed to parse a Value"); - /// let value2 = Value::from_str("foo-bar").expect("failed to parse a Value"); - /// - /// assert!(value1.into_single_subtag().is_some()); - /// assert!(value2.into_single_subtag().is_none()); - /// ``` - pub fn into_single_subtag(self) -> Option { - self.0.into_single() - } - - #[doc(hidden)] - pub fn as_subtags_slice(&self) -> &[Subtag] { - &self.0 - } - - /// Appends a subtag to the back of a [`Value`]. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::{extensions::unicode::Value, subtags::subtag}; - /// - /// let mut v = Value::default(); - /// v.push_subtag(subtag!("foo")); - /// v.push_subtag(subtag!("bar")); - /// assert_eq!(v, "foo-bar"); - /// ``` - #[cfg(feature = "alloc")] - pub fn push_subtag(&mut self, subtag: Subtag) { - self.0.push(subtag); - } - - /// Returns the number of subtags in the [`Value`]. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::{extensions::unicode::Value, subtags::subtag}; - /// - /// let mut v = Value::default(); - /// assert_eq!(v.subtag_count(), 0); - /// v.push_subtag(subtag!("foo")); - /// assert_eq!(v.subtag_count(), 1); - /// ``` - pub fn subtag_count(&self) -> usize { - self.0.len() - } - - /// Creates an empty [`Value`], which corresponds to a "true" value. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::{value, Value}; - /// - /// assert_eq!(value!("true"), Value::new_empty()); - /// ``` - pub const fn new_empty() -> Self { - Self(ShortBoxSlice::new()) - } - - /// Returns `true` if the Value has no subtags. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::{extensions::unicode::Value, subtags::subtag}; - /// - /// let mut v = Value::default(); - /// assert_eq!(v.is_empty(), true); - /// ``` - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Removes and returns the subtag at position `index` within the value, - /// shifting all subtags after it to the left. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::{extensions::unicode::Value, subtags::subtag}; - /// let mut v = Value::default(); - /// v.push_subtag(subtag!("foo")); - /// v.push_subtag(subtag!("bar")); - /// v.push_subtag(subtag!("baz")); - /// - /// assert_eq!(v.remove_subtag(1), Some(subtag!("bar"))); - /// assert_eq!(v, "foo-baz"); - /// ``` - pub fn remove_subtag(&mut self, idx: usize) -> Option { - if self.0.len() < idx { - None - } else { - let item = self.0.remove(idx); - Some(item) - } - } - - /// Returns a reference to a subtag at index. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::{extensions::unicode::Value, subtags::subtag}; - /// let mut v = Value::default(); - /// v.push_subtag(subtag!("foo")); - /// v.push_subtag(subtag!("bar")); - /// v.push_subtag(subtag!("baz")); - /// - /// assert_eq!(v.get_subtag(1), Some(&subtag!("bar"))); - /// assert_eq!(v.get_subtag(3), None); - /// ``` - pub fn get_subtag(&self, idx: usize) -> Option<&Subtag> { - self.0.get(idx) - } - - #[doc(hidden)] - pub const fn from_subtag(subtag: Option) -> Self { - match subtag { - None | Some(TRUE_VALUE) => Self(ShortBoxSlice::new()), - Some(val) => Self(ShortBoxSlice::new_single(val)), - } - } - - /// A constructor which takes a pre-sorted list of [`Value`] elements. - /// - /// - /// # Examples - /// - /// ``` - /// use icu::locale::extensions::unicode::Value; - /// use icu::locale::subtags::subtag; - /// - /// let subtag1 = subtag!("foobar"); - /// let subtag2 = subtag!("testing"); - /// let mut v = vec![subtag1, subtag2]; - /// v.sort(); - /// v.dedup(); - /// - /// let value = Value::from_vec_unchecked(v); - /// ``` - /// - /// Notice: For performance- and memory-constrained environments, it is recommended - /// for the caller to use [`binary_search`](slice::binary_search) instead of [`sort`](slice::sort) - /// and [`dedup`](Vec::dedup()). - #[cfg(feature = "alloc")] - pub fn from_vec_unchecked(input: Vec) -> Self { - Self(input.into()) - } - - #[allow(dead_code)] - pub(crate) fn from_short_slice_unchecked(input: ShortBoxSlice) -> Self { - Self(input) - } - - pub(crate) const fn parse_subtag_from_utf8(t: &[u8]) -> Result, ParseError> { - match Subtag::try_from_utf8(t) { - Ok(TRUE_VALUE) => Ok(None), - Ok(s) => Ok(Some(s)), - Err(_) => Err(ParseError::InvalidSubtag), - } - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - self.0.iter().map(Subtag::as_str).try_for_each(f) - } -} - -impl IntoIterator for Value { - type Item = Subtag; - - type IntoIter = ShortBoxSliceIntoIter; - - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -#[cfg(feature = "alloc")] -impl FromIterator for Value { - fn from_iter>(iter: T) -> Self { - Self(ShortBoxSlice::from_iter(iter)) - } -} - -#[cfg(feature = "alloc")] -impl Extend for Value { - fn extend>(&mut self, iter: T) { - for i in iter { - self.0.push(i); - } - } -} - -#[cfg(feature = "alloc")] -impl FromStr for Value { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -impl PartialEq<&str> for Value { - fn eq(&self, other: &&str) -> bool { - writeable::cmp_utf8(self, other.as_bytes()).is_eq() - } -} - -impl_writeable_for_subtag_list!(Value, "islamic", "civil"); - -/// A macro allowing for compile-time construction of valid Unicode [`Value`] subtag. -/// -/// The macro only supports single-subtag values. -/// -/// # Examples -/// -/// ``` -/// use icu::locale::extensions::unicode::{key, value}; -/// use icu::locale::Locale; -/// -/// let loc: Locale = "de-u-ca-buddhist".parse().unwrap(); -/// -/// assert_eq!( -/// loc.extensions.unicode.keywords.get(&key!("ca")), -/// Some(&value!("buddhist")) -/// ); -/// ``` -/// -/// [`Value`]: crate::extensions::unicode::Value -#[macro_export] -#[doc(hidden)] // macro -macro_rules! extensions_unicode_value { - ($value:literal) => { - const { - $crate::extensions::unicode::Value::from_subtag( - match $crate::subtags::Subtag::try_from_utf8($value.as_bytes()) { - Ok(r) => Some(r), - _ => panic!(concat!("Invalid Unicode extension value: ", $value)), - }, - ) - } - }; -} -#[doc(inline)] -pub use extensions_unicode_value as value; diff --git a/deps/crates/vendor/icu_locale_core/src/helpers.rs b/deps/crates/vendor/icu_locale_core/src/helpers.rs deleted file mode 100644 index 48522f4bb1277a..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/helpers.rs +++ /dev/null @@ -1,425 +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 ). - -macro_rules! impl_tinystr_subtag { - ( - $(#[$doc:meta])* - $name:ident, - $($path:ident)::+, - $macro_name:ident, - $internal_macro_name:ident, - $len_start:literal..=$len_end:literal, - $tinystr_ident:ident, - $validate:expr, - $normalize:expr, - $is_normalized:expr, - $error:ident, - [$good_example:literal $(,$more_good_examples:literal)*], - [$bad_example:literal $(, $more_bad_examples:literal)*], - ) => { - #[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Copy)] - #[cfg_attr(feature = "serde", derive(serde::Serialize))] - #[repr(transparent)] - $(#[$doc])* - pub struct $name(tinystr::TinyAsciiStr<$len_end>); - - impl $name { - /// A constructor which takes a str slice, parses it and - #[doc = concat!("produces a well-formed [`", stringify!($name), "`].")] - /// - /// # Examples - /// - /// ``` - #[doc = concat!("use icu_locale_core::", stringify!($($path::)+), stringify!($name), ";")] - /// - #[doc = concat!("assert!(", stringify!($name), "::try_from_str(", stringify!($good_example), ").is_ok());")] - #[doc = concat!("assert!(", stringify!($name), "::try_from_str(", stringify!($bad_example), ").is_err());")] - /// ``` - #[inline] - pub const fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - pub const fn try_from_utf8( - code_units: &[u8], - ) -> Result { - #[allow(clippy::double_comparisons)] // if code_units.len() === 0 - if code_units.len() < $len_start || code_units.len() > $len_end { - return Err(crate::parser::errors::ParseError::$error); - } - - match tinystr::TinyAsciiStr::try_from_utf8(code_units) { - Ok($tinystr_ident) if $validate => Ok(Self($normalize)), - _ => Err(crate::parser::errors::ParseError::$error), - } - } - - #[doc = concat!("Safely creates a [`", stringify!($name), "`] from its raw format")] - /// as returned by [`Self::into_raw`]. Unlike [`Self::try_from_utf8`], - /// this constructor only takes normalized values. - pub const fn try_from_raw( - raw: [u8; $len_end], - ) -> Result { - if let Ok($tinystr_ident) = tinystr::TinyAsciiStr::<$len_end>::try_from_raw(raw) { - if $tinystr_ident.len() >= $len_start && $is_normalized { - Ok(Self($tinystr_ident)) - } else { - Err(crate::parser::errors::ParseError::$error) - } - } else { - Err(crate::parser::errors::ParseError::$error) - } - } - - #[doc = concat!("Unsafely creates a [`", stringify!($name), "`] from its raw format")] - /// as returned by [`Self::into_raw`]. Unlike [`Self::try_from_utf8`], - /// this constructor only takes normalized values. - /// - /// # Safety - /// - /// This function is safe iff [`Self::try_from_raw`] returns an `Ok`. This is the case - /// for inputs that are correctly normalized. - pub const unsafe fn from_raw_unchecked(v: [u8; $len_end]) -> Self { - Self(tinystr::TinyAsciiStr::from_utf8_unchecked(v)) - } - - /// Deconstructs into a raw format to be consumed by - /// [`from_raw_unchecked`](Self::from_raw_unchecked()) or - /// [`try_from_raw`](Self::try_from_raw()). - pub const fn into_raw(self) -> [u8; $len_end] { - *self.0.all_bytes() - } - - #[inline] - /// A helper function for displaying as a `&str`. - pub const fn as_str(&self) -> &str { - self.0.as_str() - } - - #[doc(hidden)] - pub const fn to_tinystr(&self) -> tinystr::TinyAsciiStr<$len_end> { - self.0 - } - - /// Compare with BCP-47 bytes. - /// - /// The return value is equivalent to what would happen if you first converted - /// `self` to a BCP-47 string and then performed a byte comparison. - /// - /// This function is case-sensitive and results in a *total order*, so it is appropriate for - /// binary search. The only argument producing [`Ordering::Equal`](core::cmp::Ordering::Equal) - /// is `self.as_str().as_bytes()`. - #[inline] - pub fn strict_cmp(self, other: &[u8]) -> core::cmp::Ordering { - self.as_str().as_bytes().cmp(other) - } - - /// Compare with a potentially unnormalized BCP-47 string. - /// - /// The return value is equivalent to what would happen if you first parsed the - /// BCP-47 string and then performed a structural comparison. - /// - #[inline] - pub fn normalizing_eq(self, other: &str) -> bool { - self.as_str().eq_ignore_ascii_case(other) - } - } - - impl core::str::FromStr for $name { - type Err = crate::parser::errors::ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } - } - - impl<'l> From<&'l $name> for &'l str { - fn from(input: &'l $name) -> Self { - input.as_str() - } - } - - impl From<$name> for tinystr::TinyAsciiStr<$len_end> { - fn from(input: $name) -> Self { - input.to_tinystr() - } - } - - impl writeable::Writeable for $name { - #[inline] - fn write_to(&self, sink: &mut W) -> core::fmt::Result { - sink.write_str(self.as_str()) - } - #[inline] - fn writeable_length_hint(&self) -> writeable::LengthHint { - writeable::LengthHint::exact(self.0.len()) - } - #[inline] - #[cfg(feature = "alloc")] - fn write_to_string(&self) -> alloc::borrow::Cow { - alloc::borrow::Cow::Borrowed(self.0.as_str()) - } - } - - writeable::impl_display_with_writeable!($name); - - #[doc = concat!("A macro allowing for compile-time construction of valid [`", stringify!($name), "`] subtags.")] - /// - /// # Examples - /// - /// Parsing errors don't have to be handled at runtime: - /// ``` - /// assert_eq!( - #[doc = concat!(" icu_locale_core::", $(stringify!($path), "::",)+ stringify!($macro_name), "!(", stringify!($good_example) ,"),")] - #[doc = concat!(" ", stringify!($good_example), ".parse::().unwrap()")] - /// ); - /// ``` - /// - /// Invalid input is a compile failure: - /// ```compile_fail,E0080 - #[doc = concat!("icu_locale_core::", $(stringify!($path), "::",)+ stringify!($macro_name), "!(", stringify!($bad_example) ,");")] - /// ``` - /// - #[doc = concat!("[`", stringify!($name), "`]: crate::", $(stringify!($path), "::",)+ stringify!($name))] - #[macro_export] - #[doc(hidden)] // macro - macro_rules! $internal_macro_name { - ($string:literal) => { const { - use $crate::$($path ::)+ $name; - match $name::try_from_utf8($string.as_bytes()) { - Ok(r) => r, - #[allow(clippy::panic)] // const context - _ => panic!(concat!("Invalid ", $(stringify!($path), "::",)+ stringify!($name), ": ", $string)), - } - }}; - } - #[doc(inline)] - pub use $internal_macro_name as $macro_name; - - #[cfg(feature = "databake")] - impl databake::Bake for $name { - fn bake(&self, env: &databake::CrateEnv) -> databake::TokenStream { - env.insert("icu_locale_core"); - let string = self.as_str(); - databake::quote! { icu_locale_core::$($path::)+ $macro_name!(#string) } - } - } - - #[cfg(feature = "databake")] - impl databake::BakeSize for $name { - fn borrows_size(&self) -> usize { - 0 - } - } - - #[test] - fn test_construction() { - let maybe = $name::try_from_utf8($good_example.as_bytes()); - assert!(maybe.is_ok()); - assert_eq!(maybe, $name::try_from_raw(maybe.unwrap().into_raw())); - assert_eq!(maybe.unwrap().as_str(), $good_example); - $( - let maybe = $name::try_from_utf8($more_good_examples.as_bytes()); - assert!(maybe.is_ok()); - assert_eq!(maybe, $name::try_from_raw(maybe.unwrap().into_raw())); - assert_eq!(maybe.unwrap().as_str(), $more_good_examples); - )* - assert!($name::try_from_utf8($bad_example.as_bytes()).is_err()); - $( - assert!($name::try_from_utf8($more_bad_examples.as_bytes()).is_err()); - )* - } - - #[test] - fn test_writeable() { - writeable::assert_writeable_eq!(&$good_example.parse::<$name>().unwrap(), $good_example); - $( - writeable::assert_writeable_eq!($more_good_examples.parse::<$name>().unwrap(), $more_good_examples); - )* - } - - #[cfg(feature = "serde")] - impl<'de> serde::Deserialize<'de> for $name { - fn deserialize(deserializer: D) -> Result - where - D: serde::de::Deserializer<'de>, - { - struct Visitor; - - impl<'de> serde::de::Visitor<'de> for Visitor { - type Value = $name; - - fn expecting( - &self, - formatter: &mut core::fmt::Formatter<'_>, - ) -> core::fmt::Result { - write!(formatter, "a valid BCP-47 {}", stringify!($name)) - } - - fn visit_str(self, s: &str) -> Result { - s.parse().map_err(serde::de::Error::custom) - } - } - - if deserializer.is_human_readable() { - deserializer.deserialize_string(Visitor) - } else { - Self::try_from_raw(serde::de::Deserialize::deserialize(deserializer)?) - .map_err(serde::de::Error::custom) - } - } - } - - // Safety checklist for ULE: - // - // 1. Must not include any uninitialized or padding bytes (true since transparent over a ULE). - // 2. Must have an alignment of 1 byte (true since transparent over a ULE). - // 3. ULE::validate_bytes() checks that the given byte slice represents a valid slice. - // 4. ULE::validate_bytes() checks that the given byte slice has a valid length. - // 5. All other methods must be left with their default impl. - // 6. Byte equality is semantic equality. - #[cfg(feature = "zerovec")] - unsafe impl zerovec::ule::ULE for $name { - fn validate_bytes(bytes: &[u8]) -> Result<(), zerovec::ule::UleError> { - let it = bytes.chunks_exact(core::mem::size_of::()); - if !it.remainder().is_empty() { - return Err(zerovec::ule::UleError::length::(bytes.len())); - } - for v in it { - // The following can be removed once `array_chunks` is stabilized. - let mut a = [0; core::mem::size_of::()]; - a.copy_from_slice(v); - if Self::try_from_raw(a).is_err() { - return Err(zerovec::ule::UleError::parse::()); - } - } - Ok(()) - } - } - - #[cfg(feature = "zerovec")] - impl zerovec::ule::NicheBytes<$len_end> for $name { - const NICHE_BIT_PATTERN: [u8; $len_end] = >::NICHE_BIT_PATTERN; - } - - #[cfg(feature = "zerovec")] - impl zerovec::ule::AsULE for $name { - type ULE = Self; - fn to_unaligned(self) -> Self::ULE { - self - } - fn from_unaligned(unaligned: Self::ULE) -> Self { - unaligned - } - } - - #[cfg(feature = "zerovec")] - impl<'a> zerovec::maps::ZeroMapKV<'a> for $name { - type Container = zerovec::ZeroVec<'a, $name>; - type Slice = zerovec::ZeroSlice<$name>; - type GetType = $name; - type OwnedType = $name; - } - }; -} - -#[macro_export] -#[doc(hidden)] -macro_rules! impl_writeable_for_each_subtag_str_no_test { - ($type:tt $(, $self:ident, $borrow_cond:expr => $borrow:expr)?) => { - impl writeable::Writeable for $type { - fn write_to(&self, sink: &mut W) -> core::fmt::Result { - let mut initial = true; - self.for_each_subtag_str(&mut |subtag| { - if initial { - initial = false; - } else { - sink.write_char('-')?; - } - sink.write_str(subtag) - }) - } - - #[inline] - fn writeable_length_hint(&self) -> writeable::LengthHint { - let mut result = writeable::LengthHint::exact(0); - let mut initial = true; - self.for_each_subtag_str::(&mut |subtag| { - if initial { - initial = false; - } else { - result += 1; - } - result += subtag.len(); - Ok(()) - }) - .expect("infallible"); - result - } - - $( - #[cfg(feature = "alloc")] - fn write_to_string(&self) -> alloc::borrow::Cow { - #[allow(clippy::unwrap_used)] // impl_writeable_for_subtag_list's $borrow uses unwrap - let $self = self; - if $borrow_cond { - $borrow - } else { - let mut output = alloc::string::String::with_capacity(self.writeable_length_hint().capacity()); - let _ = self.write_to(&mut output); - alloc::borrow::Cow::Owned(output) - } - } - )? - } - - writeable::impl_display_with_writeable!($type); - }; -} - -macro_rules! impl_writeable_for_subtag_list { - ($type:tt, $sample1:literal, $sample2:literal) => { - impl_writeable_for_each_subtag_str_no_test!($type, selff, selff.0.len() == 1 => alloc::borrow::Cow::Borrowed(selff.0.get(0).unwrap().as_str())); - - #[test] - fn test_writeable() { - writeable::assert_writeable_eq!(&$type::default(), ""); - writeable::assert_writeable_eq!( - &$type::from_vec_unchecked(alloc::vec![$sample1.parse().unwrap()]), - $sample1, - ); - writeable::assert_writeable_eq!( - &$type::from_vec_unchecked(vec![ - $sample1.parse().unwrap(), - $sample2.parse().unwrap() - ]), - core::concat!($sample1, "-", $sample2), - ); - } - }; -} - -macro_rules! impl_writeable_for_key_value { - ($type:tt, $key1:literal, $value1:literal, $key2:literal, $expected2:literal) => { - impl_writeable_for_each_subtag_str_no_test!($type); - - #[test] - fn test_writeable() { - writeable::assert_writeable_eq!(&$type::default(), ""); - writeable::assert_writeable_eq!( - &$type::from_tuple_vec(vec![($key1.parse().unwrap(), $value1.parse().unwrap())]), - core::concat!($key1, "-", $value1), - ); - writeable::assert_writeable_eq!( - &$type::from_tuple_vec(vec![ - ($key1.parse().unwrap(), $value1.parse().unwrap()), - ($key2.parse().unwrap(), "true".parse().unwrap()) - ]), - core::concat!($key1, "-", $value1, "-", $expected2), - ); - } - }; -} diff --git a/deps/crates/vendor/icu_locale_core/src/langid.rs b/deps/crates/vendor/icu_locale_core/src/langid.rs deleted file mode 100644 index 82ef5e0d44bb7f..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/langid.rs +++ /dev/null @@ -1,662 +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 core::cmp::Ordering; -#[cfg(feature = "alloc")] -use core::str::FromStr; - -use crate::parser; -use crate::subtags; -use crate::ParseError; -#[cfg(feature = "alloc")] -use alloc::borrow::Cow; - -/// A core struct representing a [`Unicode BCP47 Language Identifier`]. -/// -/// # Ordering -/// -/// This type deliberately does not implement `Ord` or `PartialOrd` because there are -/// multiple possible orderings. Depending on your use case, two orderings are available: -/// -/// 1. A string ordering, suitable for stable serialization: [`LanguageIdentifier::strict_cmp`] -/// 2. A struct ordering, suitable for use with a BTreeSet: [`LanguageIdentifier::total_cmp`] -/// -/// See issue: -/// -/// # Parsing -/// -/// Unicode recognizes three levels of standard conformance for any language identifier: -/// -/// * *well-formed* - syntactically correct -/// * *valid* - well-formed and only uses registered language, region, script and variant subtags... -/// * *canonical* - valid and no deprecated codes or structure. -/// -/// At the moment parsing normalizes a well-formed language identifier converting -/// `_` separators to `-` and adjusting casing to conform to the Unicode standard. -/// -/// Any syntactically invalid subtags will cause the parsing to fail with an error. -/// -/// This operation normalizes syntax to be well-formed. No legacy subtag replacements is performed. -/// For validation and canonicalization, see `LocaleCanonicalizer`. -/// -/// # Examples -/// -/// Simple example: -/// -/// ``` -/// use icu::locale::{ -/// langid, -/// subtags::{language, region}, -/// }; -/// -/// let li = langid!("en-US"); -/// -/// assert_eq!(li.language, language!("en")); -/// assert_eq!(li.script, None); -/// assert_eq!(li.region, Some(region!("US"))); -/// assert_eq!(li.variants.len(), 0); -/// ``` -/// -/// More complex example: -/// -/// ``` -/// use icu::locale::{ -/// langid, -/// subtags::{language, region, script, variant}, -/// }; -/// -/// let li = langid!("eN-latn-Us-Valencia"); -/// -/// assert_eq!(li.language, language!("en")); -/// assert_eq!(li.script, Some(script!("Latn"))); -/// assert_eq!(li.region, Some(region!("US"))); -/// assert_eq!(li.variants.get(0), Some(&variant!("valencia"))); -/// ``` -/// -/// [`Unicode BCP47 Language Identifier`]: https://unicode.org/reports/tr35/tr35.html#Unicode_language_identifier -#[derive(PartialEq, Eq, Clone, Hash)] // no Ord or PartialOrd: see docs -#[allow(clippy::exhaustive_structs)] // This struct is stable (and invoked by a macro) -pub struct LanguageIdentifier { - /// Language subtag of the language identifier. - pub language: subtags::Language, - /// Script subtag of the language identifier. - pub script: Option, - /// Region subtag of the language identifier. - pub region: Option, - /// Variant subtags of the language identifier. - pub variants: subtags::Variants, -} - -impl LanguageIdentifier { - /// The unknown language identifier "und". - pub const UNKNOWN: Self = crate::langid!("und"); - - /// A constructor which takes a utf8 slice, parses it and - /// produces a well-formed [`LanguageIdentifier`]. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::LanguageIdentifier; - /// - /// LanguageIdentifier::try_from_str("en-US").expect("Parsing failed"); - /// ``` - #[inline] - #[cfg(feature = "alloc")] - pub fn try_from_str(s: &str) -> Result { - Self::try_from_utf8(s.as_bytes()) - } - - /// See [`Self::try_from_str`] - #[cfg(feature = "alloc")] - pub fn try_from_utf8(code_units: &[u8]) -> Result { - crate::parser::parse_language_identifier(code_units, parser::ParserMode::LanguageIdentifier) - } - - #[doc(hidden)] // macro use - #[allow(clippy::type_complexity)] - // The return type should be `Result` once the `const_precise_live_drops` - // is stabilized ([rust-lang#73255](https://github.com/rust-lang/rust/issues/73255)). - pub const fn try_from_utf8_with_single_variant( - code_units: &[u8], - ) -> Result< - ( - subtags::Language, - Option, - Option, - Option, - ), - ParseError, - > { - crate::parser::parse_language_identifier_with_single_variant( - code_units, - parser::ParserMode::LanguageIdentifier, - ) - } - - /// A constructor which takes a utf8 slice which may contain extension keys, - /// parses it and produces a well-formed [`LanguageIdentifier`]. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::{langid, LanguageIdentifier}; - /// - /// let li = LanguageIdentifier::try_from_locale_bytes(b"en-US-x-posix") - /// .expect("Parsing failed."); - /// - /// assert_eq!(li, langid!("en-US")); - /// ``` - /// - /// This method should be used for input that may be a locale identifier. - /// All extensions will be lost. - #[cfg(feature = "alloc")] - pub fn try_from_locale_bytes(v: &[u8]) -> Result { - parser::parse_language_identifier(v, parser::ParserMode::Locale) - } - - /// Whether this [`LanguageIdentifier`] equals [`LanguageIdentifier::UNKNOWN`]. - pub const fn is_unknown(&self) -> bool { - self.language.is_unknown() - && self.script.is_none() - && self.region.is_none() - && self.variants.is_empty() - } - - /// Normalize the language identifier (operating on UTF-8 formatted byte slices) - /// - /// This operation will normalize casing and the separator. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::LanguageIdentifier; - /// - /// assert_eq!( - /// LanguageIdentifier::normalize("pL-latn-pl").as_deref(), - /// Ok("pl-Latn-PL") - /// ); - /// ``` - #[cfg(feature = "alloc")] - pub fn normalize_utf8(input: &[u8]) -> Result, ParseError> { - let lang_id = Self::try_from_utf8(input)?; - Ok(writeable::to_string_or_borrow(&lang_id, input)) - } - - /// Normalize the language identifier (operating on strings) - /// - /// This operation will normalize casing and the separator. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::LanguageIdentifier; - /// - /// assert_eq!( - /// LanguageIdentifier::normalize("pL-latn-pl").as_deref(), - /// Ok("pl-Latn-PL") - /// ); - /// ``` - #[cfg(feature = "alloc")] - pub fn normalize(input: &str) -> Result, ParseError> { - Self::normalize_utf8(input.as_bytes()) - } - - /// Compare this [`LanguageIdentifier`] with BCP-47 bytes. - /// - /// The return value is equivalent to what would happen if you first converted this - /// [`LanguageIdentifier`] to a BCP-47 string and then performed a byte comparison. - /// - /// This function is case-sensitive and results in a *total order*, so it is appropriate for - /// binary search. The only argument producing [`Ordering::Equal`] is `self.to_string()`. - /// - /// # Examples - /// - /// Sorting a list of langids with this method requires converting one of them to a string: - /// - /// ``` - /// use icu::locale::LanguageIdentifier; - /// use std::cmp::Ordering; - /// use writeable::Writeable; - /// - /// // Random input order: - /// let bcp47_strings: &[&str] = &[ - /// "ar-Latn", - /// "zh-Hant-TW", - /// "zh-TW", - /// "und-fonipa", - /// "zh-Hant", - /// "ar-SA", - /// ]; - /// - /// let mut langids = bcp47_strings - /// .iter() - /// .map(|s| s.parse().unwrap()) - /// .collect::>(); - /// langids.sort_by(|a, b| { - /// let b = b.write_to_string(); - /// a.strict_cmp(b.as_bytes()) - /// }); - /// let strict_cmp_strings = langids - /// .iter() - /// .map(|l| l.to_string()) - /// .collect::>(); - /// - /// // Output ordering, sorted alphabetically - /// let expected_ordering: &[&str] = &[ - /// "ar-Latn", - /// "ar-SA", - /// "und-fonipa", - /// "zh-Hant", - /// "zh-Hant-TW", - /// "zh-TW", - /// ]; - /// - /// assert_eq!(expected_ordering, strict_cmp_strings); - /// ``` - pub fn strict_cmp(&self, other: &[u8]) -> Ordering { - writeable::cmp_utf8(self, other) - } - - pub(crate) fn as_tuple( - &self, - ) -> ( - subtags::Language, - Option, - Option, - &subtags::Variants, - ) { - (self.language, self.script, self.region, &self.variants) - } - - /// Compare this [`LanguageIdentifier`] with another [`LanguageIdentifier`] field-by-field. - /// The result is a total ordering sufficient for use in a [`BTreeSet`]. - /// - /// Unlike [`LanguageIdentifier::strict_cmp`], the ordering may or may not be equivalent - /// to string ordering, and it may or may not be stable across ICU4X releases. - /// - /// # Examples - /// - /// This method returns a nonsensical ordering derived from the fields of the struct: - /// - /// ``` - /// use icu::locale::LanguageIdentifier; - /// use std::cmp::Ordering; - /// - /// // Input strings, sorted alphabetically - /// let bcp47_strings: &[&str] = &[ - /// "ar-Latn", - /// "ar-SA", - /// "und-fonipa", - /// "zh-Hant", - /// "zh-Hant-TW", - /// "zh-TW", - /// ]; - /// assert!(bcp47_strings.windows(2).all(|w| w[0] < w[1])); - /// - /// let mut langids = bcp47_strings - /// .iter() - /// .map(|s| s.parse().unwrap()) - /// .collect::>(); - /// langids.sort_by(LanguageIdentifier::total_cmp); - /// let total_cmp_strings = langids - /// .iter() - /// .map(|l| l.to_string()) - /// .collect::>(); - /// - /// // Output ordering, sorted arbitrarily - /// let expected_ordering: &[&str] = &[ - /// "ar-SA", - /// "ar-Latn", - /// "und-fonipa", - /// "zh-TW", - /// "zh-Hant", - /// "zh-Hant-TW", - /// ]; - /// - /// assert_eq!(expected_ordering, total_cmp_strings); - /// ``` - /// - /// Use a wrapper to add a [`LanguageIdentifier`] to a [`BTreeSet`]: - /// - /// ```no_run - /// use icu::locale::LanguageIdentifier; - /// use std::cmp::Ordering; - /// use std::collections::BTreeSet; - /// - /// #[derive(PartialEq, Eq)] - /// struct LanguageIdentifierTotalOrd(LanguageIdentifier); - /// - /// impl Ord for LanguageIdentifierTotalOrd { - /// fn cmp(&self, other: &Self) -> Ordering { - /// self.0.total_cmp(&other.0) - /// } - /// } - /// - /// impl PartialOrd for LanguageIdentifierTotalOrd { - /// fn partial_cmp(&self, other: &Self) -> Option { - /// Some(self.cmp(other)) - /// } - /// } - /// - /// let _: BTreeSet = unimplemented!(); - /// ``` - /// - /// [`BTreeSet`]: alloc::collections::BTreeSet - pub fn total_cmp(&self, other: &Self) -> Ordering { - self.as_tuple().cmp(&other.as_tuple()) - } - - /// Compare this `LanguageIdentifier` with a potentially unnormalized BCP-47 string. - /// - /// The return value is equivalent to what would happen if you first parsed the - /// BCP-47 string to a `LanguageIdentifier` and then performed a structural comparison. - /// - /// # Examples - /// - /// ``` - /// use icu::locale::LanguageIdentifier; - /// - /// let bcp47_strings: &[&str] = &[ - /// "pl-LaTn-pL", - /// "uNd", - /// "UnD-adlm", - /// "uNd-GB", - /// "UND-FONIPA", - /// "ZH", - /// ]; - /// - /// for a in bcp47_strings { - /// assert!(a.parse::().unwrap().normalizing_eq(a)); - /// } - /// ``` - pub fn normalizing_eq(&self, other: &str) -> bool { - macro_rules! subtag_matches { - ($T:ty, $iter:ident, $expected:expr) => { - $iter - .next() - .map(|b| <$T>::try_from_utf8(b) == Ok($expected)) - .unwrap_or(false) - }; - } - - let mut iter = parser::SubtagIterator::new(other.as_bytes()); - if !subtag_matches!(subtags::Language, iter, self.language) { - return false; - } - if let Some(ref script) = self.script { - if !subtag_matches!(subtags::Script, iter, *script) { - return false; - } - } - if let Some(ref region) = self.region { - if !subtag_matches!(subtags::Region, iter, *region) { - return false; - } - } - for variant in self.variants.iter() { - if !subtag_matches!(subtags::Variant, iter, *variant) { - return false; - } - } - iter.next().is_none() - } - - pub(crate) fn for_each_subtag_str(&self, f: &mut F) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - f(self.language.as_str())?; - if let Some(ref script) = self.script { - f(script.as_str())?; - } - if let Some(ref region) = self.region { - f(region.as_str())?; - } - for variant in self.variants.iter() { - f(variant.as_str())?; - } - Ok(()) - } - - /// Executes `f` on each subtag string of this `LanguageIdentifier`, with every string in - /// lowercase ascii form. - /// - /// The default normalization of language identifiers uses titlecase scripts and uppercase - /// regions. However, this differs from [RFC6497 (BCP 47 Extension T)], which specifies: - /// - /// > _The canonical form for all subtags in the extension is lowercase, with the fields - /// > ordered by the separators, alphabetically._ - /// - /// Hence, this method is used inside [`Transform Extensions`] to be able to get the correct - /// normalization of the language identifier. - /// - /// As an example, the canonical form of locale **EN-LATN-CA-T-EN-LATN-CA** is - /// **en-Latn-CA-t-en-latn-ca**, with the script and region parts lowercased inside T extensions, - /// but titlecased and uppercased outside T extensions respectively. - /// - /// [RFC6497 (BCP 47 Extension T)]: https://www.ietf.org/rfc/rfc6497.txt - /// [`Transform extensions`]: crate::extensions::transform - pub(crate) fn for_each_subtag_str_lowercased(&self, f: &mut F) -> Result<(), E> - where - F: FnMut(&str) -> Result<(), E>, - { - f(self.language.as_str())?; - if let Some(ref script) = self.script { - f(script.to_tinystr().to_ascii_lowercase().as_str())?; - } - if let Some(ref region) = self.region { - f(region.to_tinystr().to_ascii_lowercase().as_str())?; - } - for variant in self.variants.iter() { - f(variant.as_str())?; - } - Ok(()) - } - - /// Writes this `LanguageIdentifier` to a sink, replacing uppercase ascii chars with - /// lowercase ascii chars. - /// - /// The default normalization of language identifiers uses titlecase scripts and uppercase - /// regions. However, this differs from [RFC6497 (BCP 47 Extension T)], which specifies: - /// - /// > _The canonical form for all subtags in the extension is lowercase, with the fields - /// > ordered by the separators, alphabetically._ - /// - /// Hence, this method is used inside [`Transform Extensions`] to be able to get the correct - /// normalization of the language identifier. - /// - /// As an example, the canonical form of locale **EN-LATN-CA-T-EN-LATN-CA** is - /// **en-Latn-CA-t-en-latn-ca**, with the script and region parts lowercased inside T extensions, - /// but titlecased and uppercased outside T extensions respectively. - /// - /// [RFC6497 (BCP 47 Extension T)]: https://www.ietf.org/rfc/rfc6497.txt - /// [`Transform extensions`]: crate::extensions::transform - pub(crate) fn write_lowercased_to( - &self, - sink: &mut W, - ) -> core::fmt::Result { - let mut initial = true; - self.for_each_subtag_str_lowercased(&mut |subtag| { - if initial { - initial = false; - } else { - sink.write_char('-')?; - } - sink.write_str(subtag) - }) - } -} - -impl core::fmt::Debug for LanguageIdentifier { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { - core::fmt::Display::fmt(&self, f) - } -} - -#[cfg(feature = "alloc")] -impl FromStr for LanguageIdentifier { - type Err = ParseError; - - #[inline] - fn from_str(s: &str) -> Result { - Self::try_from_str(s) - } -} - -impl_writeable_for_each_subtag_str_no_test!(LanguageIdentifier, selff, selff.script.is_none() && selff.region.is_none() && selff.variants.is_empty() => selff.language.write_to_string()); - -#[test] -fn test_writeable() { - use writeable::assert_writeable_eq; - assert_writeable_eq!(LanguageIdentifier::UNKNOWN, "und"); - assert_writeable_eq!("und-001".parse::().unwrap(), "und-001"); - assert_writeable_eq!( - "und-Mymr".parse::().unwrap(), - "und-Mymr", - ); - assert_writeable_eq!( - "my-Mymr-MM".parse::().unwrap(), - "my-Mymr-MM", - ); - assert_writeable_eq!( - "my-Mymr-MM-posix".parse::().unwrap(), - "my-Mymr-MM-posix", - ); - assert_writeable_eq!( - "zh-macos-posix".parse::().unwrap(), - "zh-macos-posix", - ); -} - -/// # Examples -/// -/// ``` -/// use icu::locale::{langid, subtags::language, LanguageIdentifier}; -/// -/// assert_eq!(LanguageIdentifier::from(language!("en")), langid!("en")); -/// ``` -impl From for LanguageIdentifier { - fn from(language: subtags::Language) -> Self { - Self { - language, - script: None, - region: None, - variants: subtags::Variants::new(), - } - } -} - -/// # Examples -/// -/// ``` -/// use icu::locale::{langid, subtags::script, LanguageIdentifier}; -/// -/// assert_eq!( -/// LanguageIdentifier::from(Some(script!("latn"))), -/// langid!("und-Latn") -/// ); -/// ``` -impl From> for LanguageIdentifier { - fn from(script: Option) -> Self { - Self { - language: subtags::Language::UNKNOWN, - script, - region: None, - variants: subtags::Variants::new(), - } - } -} - -/// # Examples -/// -/// ``` -/// use icu::locale::{langid, subtags::region, LanguageIdentifier}; -/// -/// assert_eq!( -/// LanguageIdentifier::from(Some(region!("US"))), -/// langid!("und-US") -/// ); -/// ``` -impl From> for LanguageIdentifier { - fn from(region: Option) -> Self { - Self { - language: subtags::Language::UNKNOWN, - script: None, - region, - variants: subtags::Variants::new(), - } - } -} - -/// Convert from an LSR tuple to a [`LanguageIdentifier`]. -/// -/// # Examples -/// -/// ``` -/// use icu::locale::{ -/// langid, -/// subtags::{language, region, script}, -/// LanguageIdentifier, -/// }; -/// -/// let lang = language!("en"); -/// let script = script!("Latn"); -/// let region = region!("US"); -/// assert_eq!( -/// LanguageIdentifier::from((lang, Some(script), Some(region))), -/// langid!("en-Latn-US") -/// ); -/// ``` -impl - From<( - subtags::Language, - Option, - Option, - )> for LanguageIdentifier -{ - fn from( - lsr: ( - subtags::Language, - Option, - Option, - ), - ) -> Self { - Self { - language: lsr.0, - script: lsr.1, - region: lsr.2, - variants: subtags::Variants::new(), - } - } -} - -/// Convert from a [`LanguageIdentifier`] to an LSR tuple. -/// -/// # Examples -/// -/// ``` -/// use icu::locale::{ -/// langid, -/// subtags::{language, region, script}, -/// }; -/// -/// let lid = langid!("en-Latn-US"); -/// let (lang, script, region) = (&lid).into(); -/// -/// assert_eq!(lang, language!("en")); -/// assert_eq!(script, Some(script!("Latn"))); -/// assert_eq!(region, Some(region!("US"))); -/// ``` -impl From<&LanguageIdentifier> - for ( - subtags::Language, - Option, - Option, - ) -{ - fn from(langid: &LanguageIdentifier) -> Self { - (langid.language, langid.script, langid.region) - } -} diff --git a/deps/crates/vendor/icu_locale_core/src/lib.rs b/deps/crates/vendor/icu_locale_core/src/lib.rs deleted file mode 100644 index 8e8a130411c1a5..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/lib.rs +++ /dev/null @@ -1,96 +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 ). - -//! Parsing, manipulating, and serializing Unicode Language and Locale Identifiers. -//! -//! This module is published as its own crate ([`icu_locale_core`](https://docs.rs/icu_locale_core/latest/icu_locale_core/)) -//! and as part of the [`icu`](https://docs.rs/icu/latest/icu/) crate. See the latter for more details on the ICU4X project. -//! -//! The module provides algorithms for parsing a string into a well-formed language or locale identifier -//! as defined by [`UTS #35: Unicode LDML 3. Unicode Language and Locale Identifiers`]. Additionally -//! the module provides [`preferences`] interface for operations on locale preferences and conversions -//! from and to locale unicode extensions. -//! -//! [`Locale`] is the most common structure to use for storing information about a language, -//! script, region, variants and extensions. In almost all cases, this struct should be used as the -//! base unit for all locale management operations. -//! -//! [`LanguageIdentifier`] is a strict subset of [`Locale`] which can be useful in a narrow range of -//! cases where [`Unicode Extensions`] are not relevant. -//! -//! If in doubt, use [`Locale`]. -//! -//! # Examples -//! -//! ``` -//! use icu::locale::Locale; -//! use icu::locale::{ -//! locale, -//! subtags::{language, region}, -//! }; -//! -//! let mut loc: Locale = locale!("en-US"); -//! -//! assert_eq!(loc.id.language, language!("en")); -//! assert_eq!(loc.id.script, None); -//! assert_eq!(loc.id.region, Some(region!("US"))); -//! assert_eq!(loc.id.variants.len(), 0); -//! -//! loc.id.region = Some(region!("GB")); -//! -//! assert_eq!(loc, locale!("en-GB")); -//! ``` -//! -//! For more details, see [`Locale`] and [`LanguageIdentifier`]. -//! -//! [`UTS #35: Unicode LDML 3. Unicode Language and Locale Identifiers`]: https://unicode.org/reports/tr35/tr35.html#Unicode_Language_and_Locale_Identifiers -//! [`ICU4X`]: ../icu/index.html -//! [`Unicode Extensions`]: extensions - -// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations -#![cfg_attr(not(any(test, doc)), no_std)] -#![cfg_attr( - not(test), - deny( - clippy::indexing_slicing, - clippy::unwrap_used, - clippy::expect_used, - clippy::panic, - clippy::exhaustive_structs, - clippy::exhaustive_enums, - clippy::trivially_copy_pass_by_ref, - missing_debug_implementations, - ) -)] -#![warn(missing_docs)] - -#[cfg(feature = "alloc")] -extern crate alloc; - -#[macro_use] -mod helpers; - -mod data; -mod langid; -mod locale; -mod macros; -mod parser; -mod shortvec; - -pub use data::DataLocale; -pub use langid::LanguageIdentifier; -pub use locale::Locale; -pub use parser::ParseError; - -pub mod extensions; -#[macro_use] -pub mod subtags; -pub mod preferences; -pub mod zerovec; - -#[cfg(feature = "serde")] -mod serde; - -#[cfg(feature = "databake")] -mod databake; diff --git a/deps/crates/vendor/icu_locale_core/src/locale.rs b/deps/crates/vendor/icu_locale_core/src/locale.rs deleted file mode 100644 index a3435f215f9b28..00000000000000 --- a/deps/crates/vendor/icu_locale_core/src/locale.rs +++ /dev/null @@ -1,607 +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 crate::parser::*; -use crate::subtags::Subtag; -use crate::{extensions, subtags, LanguageIdentifier}; -#[cfg(feature = "alloc")] -use alloc::borrow::Cow; -use core::cmp::Ordering; -#[cfg(feature = "alloc")] -use core::str::FromStr; - -/// A core struct representing a [`Unicode Locale Identifier`]. -/// -/// A locale is made of two parts: -/// * Unicode Language Identifier -/// * A set of Unicode Extensions -/// -/// [`Locale`] exposes all of the same fields and methods as [`LanguageIdentifier`], and -/// on top of that is able to parse, manipulate and serialize unicode extension fields. -/// -/// # Ordering -/// -/// This type deliberately does not implement `Ord` or `PartialOrd` because there are -/// multiple possible orderings. Depending on your use case, two orderings are available: -/// -/// 1. A string ordering, suitable for stable serialization: [`Locale::strict_cmp`] -/// 2. A struct ordering, suitable for use with a BTreeSet: [`Locale::total_cmp`] -/// -/// See issue: -/// -/// # Parsing -/// -/// Unicode recognizes three levels of standard conformance for a locale: -/// -/// * *well-formed* - syntactically correct -/// * *valid* - well-formed and only uses registered language subtags, extensions, keywords, types... -/// * *canonical* - valid and no deprecated codes or structure. -/// -/// Any syntactically invalid subtags will cause the parsing to fail with an error. -/// -/// This operation normalizes syntax to be well-formed. No legacy subtag replacements is performed. -/// For validation and canonicalization, see `LocaleCanonicalizer`. -/// -/// ICU4X's Locale parsing does not allow for non-BCP-47-compatible locales [allowed by UTS 35 for backwards compatability][tr35-bcp]. -/// Furthermore, it currently does not allow for language tags to have more than three characters. -/// -/// # Examples -/// -/// Simple example: -/// -/// ``` -/// use icu::locale::{ -/// extensions::unicode::{key, value}, -/// locale, -/// subtags::{language, region}, -/// }; -/// -/// let loc = locale!("en-US-u-ca-buddhist"); -/// -/// assert_eq!(loc.id.language, language!("en")); -/// assert_eq!(loc.id.script, None); -/// assert_eq!(loc.id.region, Some(region!("US"))); -/// assert_eq!(loc.id.variants.len(), 0); -/// assert_eq!( -/// loc.extensions.unicode.keywords.get(&key!("ca")), -/// Some(&value!("buddhist")) -/// ); -/// ``` -/// -/// More complex example: -/// -/// ``` -/// use icu::locale::{subtags::*, Locale}; -/// -/// let loc: Locale = "eN-latn-Us-Valencia-u-hC-H12" -/// .parse() -/// .expect("Failed to parse."); -/// -/// assert_eq!(loc.id.language, "en".parse::().unwrap()); -/// assert_eq!(loc.id.script, "Latn".parse::