//! 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::locid::extensions::unicode::{Key, Value}; //! use icu::locid::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)); //! ``` //! //! [`LanguageIdentifier`]: super::LanguageIdentifier //! [`Locale`]: super::Locale //! [`subtags`]: super::subtags //! [`Other Extensions`]: other //! [`Private Use Extensions`]: private //! [`Transform Extensions`]: transform //! [`Unicode Extensions`]: unicode pubmod other; pubmod private; pubmod transform; pubmod unicode;
use core::cmp::Ordering;
use other::Other; use private::Private; use transform::Transform; use unicode::Unicode;
/// Defines the type of extension. #[derive(Debug, PartialEq, Eq, Clone, Hash, PartialOrd, Ord, Copy)] #[non_exhaustive] pubenum 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),
}
/// A map of extensions associated with a given [`Locale`](crate::Locale). #[derive(Debug, Default, PartialEq, Eq, Clone, Hash)] #[non_exhaustive] pubstruct 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. pub other: Vec<Other>,
}
impl Extensions { /// Returns a new empty map of extensions. Same as [`default()`](Default::default()), but is `const`. /// /// # Examples /// /// ``` /// use icu::locid::extensions::Extensions; /// /// assert_eq!(Extensions::new(), Extensions::default()); /// ``` #[inline] pubconstfn new() -> Self { Self {
unicode: Unicode::new(),
transform: Transform::new(),
private: Private::new(),
other: Vec::new(),
}
}
/// Function to create a new map of extensions containing exactly one unicode extension, callable in `const` /// context. #[inline] pubconstfn from_unicode(unicode: Unicode) -> Self { Self {
unicode,
transform: Transform::new(),
private: Private::new(),
other: Vec::new(),
}
}
/// Returns whether there are no extensions present. /// /// # Examples /// /// ``` /// use icu::locid::Locale; /// /// let loc: Locale = "en-US-u-foo".parse().expect("Parsing failed."); /// /// assert!(!loc.extensions.is_empty()); /// ``` pubfn is_empty(&self) -> bool { self.unicode.is_empty()
&& self.transform.is_empty()
&& self.private.is_empty()
&& self.other.is_empty()
}
/// 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 pubfn total_cmp(&self, other: &Self) -> Ordering { self.as_tuple().cmp(&other.as_tuple())
}
/// Retains the specified extension types, clearing all others. /// /// # Examples /// /// ``` /// use icu::locid::extensions::ExtensionType; /// use icu::locid::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()); /// ``` pubfn retain_by_type<F>(&mutself, 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();
} self.other
.retain(|o| predicate(ExtensionType::Other(o.get_ext_byte())));
}
pub(crate) fn for_each_subtag_str<E, F>(&self, f: &mut F) -> Result<(), E> where
F: FnMut(&str) -> Result<(), E>,
{ letmut wrote_tu = false; // Alphabetic by singleton self.other.iter().try_for_each(|other| { if other.get_ext() > 't' && !wrote_tu { // Since 't' and 'u' are next to each other in alphabetical // order, write both now. self.transform.for_each_subtag_str(f)?; self.unicode.for_each_subtag_str(f)?;
wrote_tu = true;
}
other.for_each_subtag_str(f)?;
Ok(())
})?;
if !wrote_tu { self.transform.for_each_subtag_str(f)?; self.unicode.for_each_subtag_str(f)?;
}
// 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)?;
Ok(())
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.