// This file is part of ICU4X. For terms of use, please see the file // called LICENSE at the top level of the ICU4X source tree // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). //! Data and APIs for supporting both Script and Script_Extensions property //! values in an efficient structure. use crate::error::PropertiesError; use crate::props::Script; use crate::props::ScriptULE; use crate::provider::*; use core::iter::FromIterator; use core::ops::RangeInclusive; use icu_collections::codepointinvlist::CodePointInversionList; use icu_provider::prelude::*; use zerovec::{ule::AsULE, ZeroSlice}; /// The number of bits at the low-end of a `ScriptWithExt` value used for /// storing the `Script` value (or `extensions` index). const SCRIPT_VAL_LENGTH: u16 = 10; /// The bit mask necessary to retrieve the `Script` value (or `extensions` index) /// from a `ScriptWithExt` value. const SCRIPT_X_SCRIPT_VAL: u16 = (1 << SCRIPT_VAL_LENGTH) - 1; /// An internal-use only pseudo-property that represents the values stored in /// the trie of the special data structure [`ScriptWithExtensionsPropertyV1`]. /// /// Note: The will assume a 12-bit layout. The 2 higher order bits in positions /// 11..10 will indicate how to deduce the Script value and Script_Extensions, /// and the lower 10 bits 9..0 indicate either the Script value or the index /// into the `extensions` structure. #[derive(Copy, Clone, Debug, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "datagen", derive(databake::Bake))] #[cfg_attr(feature = "datagen", databake(path = icu_properties::script))] #[repr(transparent)] #[doc(hidden)] // `ScriptWithExt` not intended as public-facing but for `ScriptWithExtensionsPropertyV1` constructor #[allow(clippy::exhaustive_structs)] // this type is stable pub struct ScriptWithExt(pub u16); #[allow(missing_docs)] // These constants don't need individual documentation. #[allow(non_upper_case_globals)] #[doc(hidden)] // `ScriptWithExt` not intended as public-facing but for `ScriptWithExtensionsPropertyV1` constructor impl ScriptWithExt { pub const Unknown: ScriptWithExt = ScriptWithExt(0); } impl AsULE for ScriptWithExt { type ULE = ScriptULE; #[inline] fn to_unaligned(self) -> Self::ULE { Script(self.0).to_unaligned() } #[inline] fn from_unaligned(unaligned: Self::ULE) -> Self { ScriptWithExt(Script::from_unaligned(unaligned).0) } } #[doc(hidden)] // `ScriptWithExt` not intended as public-facing but for `ScriptWithExtensionsPropertyV1` constructor impl ScriptWithExt { /// Returns whether the [`ScriptWithExt`] value has Script_Extensions and /// also indicates a Script value of [`Script::Common`]. /// /// # Examples /// /// ``` /// use icu::properties::script::ScriptWithExt; /// /// assert!(ScriptWithExt(0x04FF).is_common()); /// assert!(ScriptWithExt(0x0400).is_common()); /// /// assert!(!ScriptWithExt(0x08FF).is_common()); /// assert!(!ScriptWithExt(0x0800).is_common()); /// /// assert!(!ScriptWithExt(0x0CFF).is_common()); /// assert!(!ScriptWithExt(0x0C00).is_common()); /// /// assert!(!ScriptWithExt(0xFF).is_common()); /// assert!(!ScriptWithExt(0x0).is_common()); /// ``` pub fn is_common(&self) -> bool { self.0 >> SCRIPT_VAL_LENGTH == 1 } /// Returns whether the [`ScriptWithExt`] value has Script_Extensions and /// also indicates a Script value of [`Script::Inherited`]. /// /// # Examples /// /// ``` /// use icu::properties::script::ScriptWithExt; /// /// assert!(!ScriptWithExt(0x04FF).is_inherited()); /// assert!(!ScriptWithExt(0x0400).is_inherited()); /// /// assert!(ScriptWithExt(0x08FF).is_inherited()); /// assert!(ScriptWithExt(0x0800).is_inherited()); /// /// assert!(!ScriptWithExt(0x0CFF).is_inherited()); /// assert!(!ScriptWithExt(0x0C00).is_inherited()); /// /// assert!(!ScriptWithExt(0xFF).is_inherited()); /// assert!(!ScriptWithExt(0x0).is_inherited()); /// ``` pub fn is_inherited(&self) -> bool { self.0 >> SCRIPT_VAL_LENGTH == 2 } /// Returns whether the [`ScriptWithExt`] value has Script_Extensions and /// also indicates that the Script value is neither [`Script::Common`] nor /// [`Script::Inherited`]. /// /// # Examples /// /// ``` /// use icu::properties::script::ScriptWithExt; /// /// assert!(!ScriptWithExt(0x04FF).is_other()); /// assert!(!ScriptWithExt(0x0400).is_other()); /// /// assert!(!ScriptWithExt(0x08FF).is_other()); /// assert!(!ScriptWithExt(0x0800).is_other()); /// /// assert!(ScriptWithExt(0x0CFF).is_other()); /// assert!(ScriptWithExt(0x0C00).is_other()); /// /// assert!(!ScriptWithExt(0xFF).is_other()); /// assert!(!ScriptWithExt(0x0).is_other()); /// ``` pub fn is_other(&self) -> bool { self.0 >> SCRIPT_VAL_LENGTH == 3 } /// Returns whether the [`ScriptWithExt`] value has Script_Extensions. /// /// # Examples /// /// ``` /// use icu::properties::script::ScriptWithExt; /// /// assert!(ScriptWithExt(0x04FF).has_extensions()); /// assert!(ScriptWithExt(0x0400).has_extensions()); /// /// assert!(ScriptWithExt(0x08FF).has_extensions()); /// assert!(ScriptWithExt(0x0800).has_extensions()); /// /// assert!(ScriptWithExt(0x0CFF).has_extensions()); /// assert!(ScriptWithExt(0x0C00).has_extensions()); /// /// assert!(!ScriptWithExt(0xFF).has_extensions()); /// assert!(!ScriptWithExt(0x0).has_extensions()); /// ``` pub fn has_extensions(&self) -> bool { let high_order_bits = self.0 >> SCRIPT_VAL_LENGTH; high_order_bits > 0 } } impl From for u32 { fn from(swe: ScriptWithExt) -> Self { swe.0 as u32 } } impl From for Script { fn from(swe: ScriptWithExt) -> Self { Script(swe.0) } } /// A struct that wraps a [`Script`] array, such as in the return value for /// [`get_script_extensions_val()`](ScriptWithExtensionsBorrowed::get_script_extensions_val). #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub struct ScriptExtensionsSet<'a> { values: &'a ZeroSlice