diff --git a/components/calendar/src/week_of.rs b/components/calendar/src/week_of.rs index ad1e39dc5dc..bdd2dd6eaa7 100644 --- a/components/calendar/src/week_of.rs +++ b/components/calendar/src/week_of.rs @@ -7,11 +7,19 @@ use crate::{ provider::*, types::{DayOfMonth, DayOfYearInfo, IsoWeekday, WeekOfMonth}, }; +use icu_locale_core::preferences::define_preferences; use icu_provider::prelude::*; /// Minimum number of days in a month unit required for using this module pub const MIN_UNIT_DAYS: u16 = 14; +define_preferences!( + /// The preferences for the week calculator. + [Copy] + WeekPreferences, + {} +); + /// Calculator for week-of-month and week-of-year based on locale-specific configurations. /// /// Note that things get subtly tricky for weeks that straddle the boundary between two years: different locales @@ -32,18 +40,19 @@ pub struct WeekCalculator { impl WeekCalculator { icu_provider::gen_any_buffer_data_constructors!( - (locale) -> error: DataError, + (prefs: WeekPreferences) -> error: DataError, /// Creates a new [`WeekCalculator`] from compiled data. ); #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)] - pub fn try_new_unstable

(provider: &P, locale: &DataLocale) -> Result + pub fn try_new_unstable

(provider: &P, prefs: WeekPreferences) -> Result where P: DataProvider + ?Sized, { + let locale = DataLocale::from_preferences_locale::(prefs.locale_prefs); provider .load(DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() }) .map(|response| WeekCalculator { @@ -68,7 +77,7 @@ impl WeekCalculator { /// use icu::calendar::week::WeekCalculator; /// /// let week_calculator = - /// WeekCalculator::try_new(&icu::locale::locale!("und-GB").into()) + /// WeekCalculator::try_new(icu::locale::locale!("und-GB").into()) /// .expect("locale should be present"); /// /// // Wednesday the 10th is in week 2: @@ -97,7 +106,7 @@ impl WeekCalculator { /// use icu::calendar::Date; /// /// let week_calculator = - /// WeekCalculator::try_new(&icu::locale::locale!("und-GB").into()) + /// WeekCalculator::try_new(icu::locale::locale!("und-GB").into()) /// .expect("locale should be present"); /// /// let iso_date = Date::try_new_iso(2022, 8, 26).unwrap(); @@ -668,7 +677,7 @@ fn test_weekend() { use icu_locale_core::locale; assert_eq!( - WeekCalculator::try_new(&locale!("und").into()) + WeekCalculator::try_new(locale!("und").into()) .unwrap() .weekend() .collect::>(), @@ -676,7 +685,7 @@ fn test_weekend() { ); assert_eq!( - WeekCalculator::try_new(&locale!("und-FR").into()) + WeekCalculator::try_new(locale!("und-FR").into()) .unwrap() .weekend() .collect::>(), @@ -684,7 +693,7 @@ fn test_weekend() { ); assert_eq!( - WeekCalculator::try_new(&locale!("und-IQ").into()) + WeekCalculator::try_new(locale!("und-IQ").into()) .unwrap() .weekend() .collect::>(), @@ -692,7 +701,7 @@ fn test_weekend() { ); assert_eq!( - WeekCalculator::try_new(&locale!("und-IR").into()) + WeekCalculator::try_new(locale!("und-IR").into()) .unwrap() .weekend() .collect::>(), diff --git a/components/experimental/src/dimension/units/formatter.rs b/components/experimental/src/dimension/units/formatter.rs index 4adcef69f51..b874dd581d0 100644 --- a/components/experimental/src/dimension/units/formatter.rs +++ b/components/experimental/src/dimension/units/formatter.rs @@ -62,7 +62,7 @@ pub struct UnitsFormatter { impl UnitsFormatter { icu_provider::gen_any_buffer_data_constructors!( - (wprefs: UnitsFormatterPreferences, unit: &str, options: super::options::UnitsFormatterOptions) -> error: DataError, + (prefs: UnitsFormatterPreferences, unit: &str, options: super::options::UnitsFormatterOptions) -> error: DataError, functions: [ try_new: skip, try_new_with_any_provider, diff --git a/components/experimental/src/displaynames/displaynames.rs b/components/experimental/src/displaynames/displaynames.rs index 71885a06b45..c7567e5410c 100644 --- a/components/experimental/src/displaynames/displaynames.rs +++ b/components/experimental/src/displaynames/displaynames.rs @@ -8,6 +8,7 @@ use crate::displaynames::options::*; use crate::displaynames::provider::*; use alloc::borrow::Cow; use alloc::string::String; +use icu_locale_core::preferences::define_preferences; use icu_locale_core::{ subtags::Language, subtags::Region, subtags::Script, subtags::Variant, LanguageIdentifier, Locale, @@ -15,6 +16,13 @@ use icu_locale_core::{ use icu_provider::prelude::*; use potential_utf::PotentialUtf8; +define_preferences!( + /// The preferences for list formatting. + [Copy] + DisplayNamesPreferences, + {} +); + /// Lookup of the locale-specific display names by region code. /// /// # Example @@ -27,7 +35,7 @@ use potential_utf::PotentialUtf8; /// /// let locale = locale!("en-001").into(); /// let options: DisplayNamesOptions = Default::default(); -/// let display_name = RegionDisplayNames::try_new(&locale, options) +/// let display_name = RegionDisplayNames::try_new(locale, options) /// .expect("Data should load successfully"); /// /// assert_eq!(display_name.of(region!("AE")), Some("United Arab Emirates")); @@ -40,7 +48,7 @@ pub struct RegionDisplayNames { impl RegionDisplayNames { icu_provider::gen_any_buffer_data_constructors!( - (locale, options: DisplayNamesOptions) -> error: DataError, + (prefs: DisplayNamesPreferences, options: DisplayNamesOptions) -> error: DataError, /// Creates a new [`RegionDisplayNames`] from locale data and an options bag using compiled data. functions: [ try_new, @@ -54,12 +62,14 @@ impl RegionDisplayNames { #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)] pub fn try_new_unstable + ?Sized>( provider: &D, - locale: &DataLocale, + prefs: DisplayNamesPreferences, options: DisplayNamesOptions, ) -> Result { + let locale = + DataLocale::from_preferences_locale::(prefs.locale_prefs); let region_data = provider .load(DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() })? .payload; @@ -94,7 +104,7 @@ impl RegionDisplayNames { /// /// let locale = locale!("en-001").into(); /// let options: DisplayNamesOptions = Default::default(); -/// let display_name = ScriptDisplayNames::try_new(&locale, options) +/// let display_name = ScriptDisplayNames::try_new(locale, options) /// .expect("Data should load successfully"); /// /// assert_eq!(display_name.of(script!("Maya")), Some("Mayan hieroglyphs")); @@ -107,7 +117,7 @@ pub struct ScriptDisplayNames { impl ScriptDisplayNames { icu_provider::gen_any_buffer_data_constructors!( - (locale, options: DisplayNamesOptions) -> error: DataError, + (prefs: DisplayNamesPreferences, options: DisplayNamesOptions) -> error: DataError, /// Creates a new [`ScriptDisplayNames`] from locale data and an options bag using compiled data. functions: [ try_new, @@ -121,12 +131,14 @@ impl ScriptDisplayNames { #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)] pub fn try_new_unstable + ?Sized>( provider: &D, - locale: &DataLocale, + prefs: DisplayNamesPreferences, options: DisplayNamesOptions, ) -> Result { + let locale = + DataLocale::from_preferences_locale::(prefs.locale_prefs); let script_data = provider .load(DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() })? .payload; @@ -161,7 +173,7 @@ impl ScriptDisplayNames { /// /// let locale = locale!("en-001").into(); /// let options: DisplayNamesOptions = Default::default(); -/// let display_name = VariantDisplayNames::try_new(&locale, options) +/// let display_name = VariantDisplayNames::try_new(locale, options) /// .expect("Data should load successfully"); /// /// assert_eq!(display_name.of(variant!("POSIX")), Some("Computer")); @@ -175,7 +187,7 @@ pub struct VariantDisplayNames { impl VariantDisplayNames { icu_provider::gen_any_buffer_data_constructors!( - (locale, options: DisplayNamesOptions) -> error: DataError, + (prefs: DisplayNamesPreferences, options: DisplayNamesOptions) -> error: DataError, /// Creates a new [`VariantDisplayNames`] from locale data and an options bag using compiled data. functions: [ try_new, @@ -189,12 +201,14 @@ impl VariantDisplayNames { #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)] pub fn try_new_unstable + ?Sized>( provider: &D, - locale: &DataLocale, + prefs: DisplayNamesPreferences, options: DisplayNamesOptions, ) -> Result { + let locale = + DataLocale::from_preferences_locale::(prefs.locale_prefs); let variant_data = provider .load(DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() })? .payload; @@ -225,7 +239,7 @@ impl VariantDisplayNames { /// /// let locale = locale!("en-001").into(); /// let options: DisplayNamesOptions = Default::default(); -/// let display_name = LanguageDisplayNames::try_new(&locale, options) +/// let display_name = LanguageDisplayNames::try_new(locale, options) /// .expect("Data should load successfully"); /// /// assert_eq!(display_name.of(language!("de")), Some("German")); @@ -238,7 +252,7 @@ pub struct LanguageDisplayNames { impl LanguageDisplayNames { icu_provider::gen_any_buffer_data_constructors!( - (locale, options: DisplayNamesOptions) -> error: DataError, + (prefs: DisplayNamesPreferences, options: DisplayNamesOptions) -> error: DataError, /// Creates a new [`LanguageDisplayNames`] from locale data and an options bag using compiled data. functions: [ try_new, @@ -252,12 +266,14 @@ impl LanguageDisplayNames { #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)] pub fn try_new_unstable + ?Sized>( provider: &D, - locale: &DataLocale, + prefs: DisplayNamesPreferences, options: DisplayNamesOptions, ) -> Result { + let locale = + DataLocale::from_preferences_locale::(prefs.locale_prefs); let language_data = provider .load(DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() })? .payload; @@ -296,7 +312,7 @@ impl LanguageDisplayNames { /// /// let locale = locale!("en-001").into(); /// let options: DisplayNamesOptions = Default::default(); -/// let display_name = LocaleDisplayNamesFormatter::try_new(&locale, options) +/// let display_name = LocaleDisplayNamesFormatter::try_new(locale, options) /// .expect("Data should load successfully"); /// /// assert_eq!(display_name.of(&locale!("en-GB")), "British English"); @@ -322,7 +338,7 @@ pub struct LocaleDisplayNamesFormatter { impl LocaleDisplayNamesFormatter { icu_provider::gen_any_buffer_data_constructors!( - (locale, options: DisplayNamesOptions) -> error: DataError, + (prefs: DisplayNamesPreferences, options: DisplayNamesOptions) -> error: DataError, /// Creates a new [`LocaleDisplayNamesFormatter`] from locale data and an options bag using compiled data. functions: [ try_new, @@ -336,7 +352,7 @@ impl LocaleDisplayNamesFormatter { #[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new)] pub fn try_new_unstable( provider: &D, - locale: &DataLocale, + prefs: DisplayNamesPreferences, options: DisplayNamesOptions, ) -> Result where @@ -347,8 +363,10 @@ impl LocaleDisplayNamesFormatter { + DataProvider + ?Sized, { + let locale = + DataLocale::from_preferences_locale::(prefs.locale_prefs); let req = DataRequest { - id: DataIdentifierBorrowed::for_locale(locale), + id: DataIdentifierBorrowed::for_locale(&locale), ..Default::default() }; @@ -503,7 +521,7 @@ fn test_language_display() { use icu_locale_core::locale; let dialect = LocaleDisplayNamesFormatter::try_new( - &locale!("en").into(), + locale!("en").into(), DisplayNamesOptions { language_display: LanguageDisplay::Dialect, ..Default::default() @@ -511,7 +529,7 @@ fn test_language_display() { ) .unwrap(); let standard = LocaleDisplayNamesFormatter::try_new( - &locale!("en").into(), + locale!("en").into(), DisplayNamesOptions { language_display: LanguageDisplay::Standard, ..Default::default() diff --git a/components/experimental/src/displaynames/options.rs b/components/experimental/src/displaynames/options.rs index 5fad55fffd9..7a533a6b512 100644 --- a/components/experimental/src/displaynames/options.rs +++ b/components/experimental/src/displaynames/options.rs @@ -17,7 +17,7 @@ /// let locale = locale!("en-001"); /// let mut options: DisplayNamesOptions = Default::default(); /// options.style = Some(Style::Short); -/// let display_name = RegionDisplayNames::try_new(&locale.into(), options) +/// let display_name = RegionDisplayNames::try_new(locale.into(), options) /// .expect("Data should load successfully"); /// /// // Full name would be "Bosnia & Herzegovina" diff --git a/components/experimental/tests/displaynames/tests.rs b/components/experimental/tests/displaynames/tests.rs index 5738015d3ee..53e558db6ea 100644 --- a/components/experimental/tests/displaynames/tests.rs +++ b/components/experimental/tests/displaynames/tests.rs @@ -82,7 +82,7 @@ fn test_concatenate() { let locale = locale!("en-001"); let options: DisplayNamesOptions = Default::default(); - let display_name = LocaleDisplayNamesFormatter::try_new(&locale.into(), options) + let display_name = LocaleDisplayNamesFormatter::try_new(locale.into(), options) .expect("Data should load successfully"); let result = display_name.of(cas.input_1); diff --git a/components/plurals/README.md b/components/plurals/README.md index 71a5e996a20..534b030576b 100644 --- a/components/plurals/README.md +++ b/components/plurals/README.md @@ -25,10 +25,10 @@ appropriate [`PluralCategory`]. ```rust use icu::locale::locale; -use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; +use icu::plurals::{PluralCategory, PluralRules}; let pr = - PluralRules::try_new(locale!("en").into(), PluralRuleType::Cardinal) + PluralRules::try_new(locale!("en").into(), Default::default()) .expect("locale should be present"); assert_eq!(pr.category_for(5_usize), PluralCategory::Other); diff --git a/components/plurals/benches/pluralrules.rs b/components/plurals/benches/pluralrules.rs index 875ab963ee3..3f96fb52f74 100644 --- a/components/plurals/benches/pluralrules.rs +++ b/components/plurals/benches/pluralrules.rs @@ -19,7 +19,8 @@ fn pluralrules(c: &mut Criterion) { c.bench_function("plurals/pluralrules/overview", |b| { b.iter(|| { for lang in &plurals_data.langs { - let pr = PluralRules::try_new(lang.into(), PluralRuleType::Cardinal).unwrap(); + let pr = + PluralRules::try_new(lang.into(), PluralRuleType::Cardinal.into()).unwrap(); for s in &numbers_data.usize { let _ = pr.category_for(*s); } @@ -35,13 +36,14 @@ fn pluralrules(c: &mut Criterion) { c.bench_function("plurals/pluralrules/construct/fs", |b| { b.iter(|| { for lang in &plurals_data.langs { - PluralRules::try_new(lang.into(), PluralRuleType::Ordinal).unwrap(); - PluralRules::try_new(lang.into(), PluralRuleType::Cardinal).unwrap(); + PluralRules::try_new(lang.into(), PluralRuleType::Ordinal.into()).unwrap(); + PluralRules::try_new(lang.into(), PluralRuleType::Cardinal.into()).unwrap(); } }); }); - let pr = PluralRules::try_new(locale!("ru").into(), PluralRuleType::Cardinal).unwrap(); + let pr = + PluralRules::try_new(locale!("ru").into(), PluralRuleType::Cardinal.into()).unwrap(); c.bench_function("plurals/pluralrules/select/fs", |b| { b.iter(|| { for s in &numbers_data.usize { diff --git a/components/plurals/src/lib.rs b/components/plurals/src/lib.rs index b027c4e37e4..3e16b7647cc 100644 --- a/components/plurals/src/lib.rs +++ b/components/plurals/src/lib.rs @@ -25,10 +25,10 @@ //! //! ``` //! use icu::locale::locale; -//! use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; +//! use icu::plurals::{PluralCategory, PluralRules}; //! //! let pr = -//! PluralRules::try_new(locale!("en").into(), PluralRuleType::Cardinal) +//! PluralRules::try_new(locale!("en").into(), Default::default()) //! .expect("locale should be present"); //! //! assert_eq!(pr.category_for(5_usize), PluralCategory::Other); @@ -77,6 +77,7 @@ extern crate alloc; mod operands; +mod options; pub mod provider; pub mod rules; @@ -85,6 +86,7 @@ use icu_locale_core::preferences::define_preferences; use icu_provider::marker::ErasedMarker; use icu_provider::prelude::*; pub use operands::PluralOperands; +pub use options::*; use provider::CardinalV1Marker; use provider::OrdinalV1Marker; use provider::PluralRulesV1; @@ -95,37 +97,6 @@ use provider::PluralRangesV1Marker; #[cfg(feature = "experimental")] use provider::UnvalidatedPluralRange; -/// A type of a plural rule which can be associated with the [`PluralRules`] struct. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] -#[non_exhaustive] -pub enum PluralRuleType { - /// Cardinal plural forms express quantities of units such as time, currency or distance, - /// used in conjunction with a number expressed in decimal digits (i.e. "2", not "two"). - /// - /// For example, English has two forms for cardinals: - /// - /// * [`One`]: `1 day` - /// * [`Other`]: `0 days`, `2 days`, `10 days`, `0.3 days` - /// - /// [`One`]: PluralCategory::One - /// [`Other`]: PluralCategory::Other - Cardinal, - /// Ordinal plural forms denote the order of items in a set and are always integers. - /// - /// For example, English has four forms for ordinals: - /// - /// * [`One`]: `1st floor`, `21st floor`, `101st floor` - /// * [`Two`]: `2nd floor`, `22nd floor`, `102nd floor` - /// * [`Few`]: `3rd floor`, `23rd floor`, `103rd floor` - /// * [`Other`]: `4th floor`, `11th floor`, `96th floor` - /// - /// [`One`]: PluralCategory::One - /// [`Two`]: PluralCategory::Two - /// [`Few`]: PluralCategory::Few - /// [`Other`]: PluralCategory::Other - Ordinal, -} - /// The plural categories are used to format messages with numeric placeholders, expressed as decimal numbers. /// /// The fundamental rule for determining plural categories is the existence of minimal pairs: whenever two different @@ -137,10 +108,10 @@ pub enum PluralRuleType { /// /// ``` /// use icu::locale::locale; -/// use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; +/// use icu::plurals::{PluralCategory, PluralRules}; /// /// let pr = -/// PluralRules::try_new(locale!("en").into(), PluralRuleType::Cardinal) +/// PluralRules::try_new(locale!("en").into(), Default::default()) /// .expect("locale should be present"); /// /// assert_eq!(pr.category_for(5_usize), PluralCategory::Other); @@ -276,10 +247,10 @@ define_preferences!( /// /// ``` /// use icu::locale::locale; -/// use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; +/// use icu::plurals::{PluralCategory, PluralRules}; /// /// let pr = -/// PluralRules::try_new(locale!("en").into(), PluralRuleType::Cardinal) +/// PluralRules::try_new(locale!("en").into(), Default::default()) /// .expect("locale should be present"); /// /// assert_eq!(pr.category_for(5_usize), PluralCategory::Other); @@ -299,22 +270,21 @@ impl AsRef for PluralRules { impl PluralRules { icu_provider::gen_any_buffer_data_constructors!( - (prefs: PluralRulesPreferences, rule_type: PluralRuleType) -> error: DataError, + (prefs: PluralRulesPreferences, options: PluralRulesOptions) -> error: DataError, /// Constructs a new `PluralRules` for a given locale and type using compiled data. /// /// # Examples /// /// ``` /// use icu::locale::locale; - /// use icu::plurals::{PluralRuleType, PluralRules}; + /// use icu::plurals::PluralRules; /// /// let _ = PluralRules::try_new( /// locale!("en").into(), - /// PluralRuleType::Cardinal, + /// Default::default(), /// ).expect("locale should be present"); /// ``` /// - /// [`type`]: PluralRuleType /// [`data provider`]: icu_provider ); @@ -322,9 +292,9 @@ impl PluralRules { pub fn try_new_unstable( provider: &(impl DataProvider + DataProvider + ?Sized), prefs: PluralRulesPreferences, - rule_type: PluralRuleType, + options: PluralRulesOptions, ) -> Result { - match rule_type { + match options.rule_type.unwrap_or_default() { PluralRuleType::Cardinal => Self::try_new_cardinal_unstable(provider, prefs), PluralRuleType::Ordinal => Self::try_new_ordinal_unstable(provider, prefs), } @@ -444,10 +414,10 @@ impl PluralRules { /// /// ``` /// use icu::locale::locale; - /// use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; + /// use icu::plurals::{PluralCategory, PluralRules}; /// /// let pr = - /// PluralRules::try_new(locale!("en").into(), PluralRuleType::Cardinal) + /// PluralRules::try_new(locale!("en").into(), Default::default()) /// .expect("locale should be present"); /// /// match pr.category_for(1_usize) { @@ -469,10 +439,9 @@ impl PluralRules { /// /// ``` /// use icu::locale::locale; - /// use icu::plurals::{PluralCategory, PluralOperands}; - /// use icu::plurals::{PluralRuleType, PluralRules}; + /// use icu::plurals::{PluralRules, PluralCategory, PluralOperands}; /// # - /// # let pr = PluralRules::try_new(locale!("en").into(), PluralRuleType::Cardinal) + /// # let pr = PluralRules::try_new(locale!("en").into(), Default::default()) /// # .expect("locale should be present"); /// /// let operands = PluralOperands::try_from(-5).expect("Failed to parse to operands."); @@ -516,10 +485,10 @@ impl PluralRules { /// /// ``` /// use icu::locale::locale; - /// use icu::plurals::{PluralCategory, PluralRuleType, PluralRules}; + /// use icu::plurals::{PluralCategory, PluralRules}; /// /// let pr = - /// PluralRules::try_new(locale!("fr").into(), PluralRuleType::Cardinal) + /// PluralRules::try_new(locale!("fr").into(), Default::default()) /// .expect("locale should be present"); /// /// let mut categories = pr.categories(); @@ -567,12 +536,11 @@ impl PluralRules { /// /// ``` /// use icu::locale::locale; -/// use icu::plurals::{PluralCategory, PluralOperands}; -/// use icu::plurals::{PluralRuleType, PluralRulesWithRanges}; +/// use icu::plurals::{PluralRulesWithRanges, PluralCategory, PluralOperands}; /// /// let ranges = PluralRulesWithRanges::try_new( /// locale!("ar").into(), -/// PluralRuleType::Cardinal, +/// Default::default(), /// ) /// .expect("locale should be present"); /// @@ -598,18 +566,18 @@ pub struct PluralRulesWithRanges { impl PluralRulesWithRanges { icu_provider::gen_any_buffer_data_constructors!( - (prefs: PluralRulesPreferences, rule_type: PluralRuleType) -> error: DataError, + (prefs: PluralRulesPreferences, options: PluralRulesOptions) -> error: DataError, /// Constructs a new `PluralRulesWithRanges` for a given locale using compiled data. /// /// # Examples /// /// ``` /// use icu::locale::locale; - /// use icu::plurals::{PluralRuleType, PluralRulesWithRanges}; + /// use icu::plurals::PluralRulesWithRanges; /// /// let _ = PluralRulesWithRanges::try_new( /// locale!("en").into(), - /// PluralRuleType::Cardinal, + /// Default::default(), /// ).expect("locale should be present"); /// ``` ); @@ -621,9 +589,9 @@ impl PluralRulesWithRanges { + DataProvider + ?Sized), prefs: PluralRulesPreferences, - rule_type: PluralRuleType, + options: PluralRulesOptions, ) -> Result { - match rule_type { + match options.rule_type.unwrap_or_default() { PluralRuleType::Cardinal => Self::try_new_cardinal_unstable(provider, prefs), PluralRuleType::Ordinal => Self::try_new_ordinal_unstable(provider, prefs), } @@ -725,9 +693,9 @@ where /// /// ``` /// use icu::locale::locale; - /// use icu::plurals::{PluralRuleType, PluralRulesWithRanges, PluralRules}; + /// use icu::plurals::{PluralRulesWithRanges, PluralRules}; /// - /// let rules = PluralRules::try_new(locale!("en").into(), PluralRuleType::Cardinal) + /// let rules = PluralRules::try_new(locale!("en").into(), Default::default()) /// .expect("locale should be present"); /// /// let _ = @@ -791,12 +759,12 @@ where /// ``` /// use icu::locale::locale; /// use icu::plurals::{ - /// PluralCategory, PluralOperands, PluralRuleType, PluralRulesWithRanges, + /// PluralCategory, PluralOperands, PluralRulesWithRanges, /// }; /// /// let ranges = PluralRulesWithRanges::try_new( /// locale!("ro").into(), - /// PluralRuleType::Cardinal, + /// Default::default(), /// ) /// .expect("locale should be present"); /// let operands: PluralOperands = @@ -833,11 +801,12 @@ where /// /// ``` /// use icu::locale::locale; - /// use icu::plurals::{PluralCategory, PluralRuleType, PluralRulesWithRanges}; + /// use icu::plurals::{PluralCategory, PluralRuleType, PluralRulesOptions, PluralRulesWithRanges}; /// /// let ranges = PluralRulesWithRanges::try_new( /// locale!("sl").into(), - /// PluralRuleType::Ordinal, + /// PluralRulesOptions::default() + /// .with_type(PluralRuleType::Ordinal), /// ) /// .expect("locale should be present"); /// diff --git a/components/plurals/src/options.rs b/components/plurals/src/options.rs new file mode 100644 index 00000000000..0182d3beb5d --- /dev/null +++ b/components/plurals/src/options.rs @@ -0,0 +1,80 @@ +// 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 ). + +/// A list of options set by the developer to adjust the behavior of the PluralRules. +/// +/// # Examples +/// ``` +/// use icu::plurals::{PluralRulesOptions, PluralRuleType}; +/// +/// let options = PluralRulesOptions::default() +/// .with_type(PluralRuleType::Cardinal); +/// ``` +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[non_exhaustive] +pub struct PluralRulesOptions { + /// Plural rule type to use. + pub rule_type: Option, +} + +impl Default for PluralRulesOptions { + fn default() -> Self { + Self::default() + } +} + +impl PluralRulesOptions { + /// Constructs a new [`PluralRulesOptions`] struct. + pub const fn default() -> Self { + Self { rule_type: None } + } + + /// Auguments the struct with the set [`PluralRuleType`]. + pub const fn with_type(mut self, rule_type: PluralRuleType) -> Self { + self.rule_type = Some(rule_type); + self + } +} + +impl From for PluralRulesOptions { + fn from(value: PluralRuleType) -> Self { + Self { + rule_type: Some(value), + } + } +} + +/// A type of a plural rule which can be associated with the [`PluralRules`] struct. +/// +/// [`PluralRules`]: crate::PluralRules +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, Default)] +#[non_exhaustive] +pub enum PluralRuleType { + /// Cardinal plural forms express quantities of units such as time, currency or distance, + /// used in conjunction with a number expressed in decimal digits (i.e. "2", not "two"). + /// + /// For example, English has two forms for cardinals: + /// + /// * [`One`]: `1 day` + /// * [`Other`]: `0 days`, `2 days`, `10 days`, `0.3 days` + /// + /// [`One`]: crate::PluralCategory::One + /// [`Other`]: crate::PluralCategory::Other + #[default] + Cardinal, + /// Ordinal plural forms denote the order of items in a set and are always integers. + /// + /// For example, English has four forms for ordinals: + /// + /// * [`One`]: `1st floor`, `21st floor`, `101st floor` + /// * [`Two`]: `2nd floor`, `22nd floor`, `102nd floor` + /// * [`Few`]: `3rd floor`, `23rd floor`, `103rd floor` + /// * [`Other`]: `4th floor`, `11th floor`, `96th floor` + /// + /// [`One`]: crate::PluralCategory::One + /// [`Two`]: crate::PluralCategory::Two + /// [`Few`]: crate::PluralCategory::Few + /// [`Other`]: crate::PluralCategory::Other + Ordinal, +} diff --git a/components/plurals/tests/fixtures/mod.rs b/components/plurals/tests/fixtures/mod.rs index 989a676e068..556080edd22 100644 --- a/components/plurals/tests/fixtures/mod.rs +++ b/components/plurals/tests/fixtures/mod.rs @@ -5,7 +5,7 @@ use fixed_decimal::FixedDecimal; #[cfg(feature = "experimental")] use icu_plurals::PluralOperands; -use icu_plurals::{PluralCategory, PluralRuleType}; +use icu_plurals::{PluralCategory, PluralRuleType, PluralRulesOptions}; use serde::Deserialize; /// Defines the data-driven test sets for the operands. @@ -133,11 +133,11 @@ pub enum PluralRuleTypeInput { Ordinal, } -impl From for PluralRuleType { +impl From for PluralRulesOptions { fn from(other: PluralRuleTypeInput) -> Self { match other { - PluralRuleTypeInput::Cardinal => PluralRuleType::Cardinal, - PluralRuleTypeInput::Ordinal => PluralRuleType::Ordinal, + PluralRuleTypeInput::Cardinal => PluralRuleType::Cardinal.into(), + PluralRuleTypeInput::Ordinal => PluralRuleType::Ordinal.into(), } } } diff --git a/components/plurals/tests/plurals.rs b/components/plurals/tests/plurals.rs index f964626fa80..df479ea8fc4 100644 --- a/components/plurals/tests/plurals.rs +++ b/components/plurals/tests/plurals.rs @@ -3,13 +3,13 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use icu_locale_core::{langid, locale}; -use icu_plurals::{provider::CardinalV1Marker, PluralCategory, PluralRuleType, PluralRules}; +use icu_plurals::{provider::CardinalV1Marker, PluralCategory, PluralRules}; use icu_provider::prelude::*; #[test] fn test_plural_rules() { assert_eq!( - PluralRules::try_new(locale!("en").into(), PluralRuleType::Cardinal) + PluralRules::try_new(locale!("en").into(), Default::default()) .unwrap() .category_for(5_usize), PluralCategory::Other diff --git a/components/plurals/tests/ranges.rs b/components/plurals/tests/ranges.rs index 0271462b14a..156ce17b13f 100644 --- a/components/plurals/tests/ranges.rs +++ b/components/plurals/tests/ranges.rs @@ -3,7 +3,7 @@ // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). use icu_locale_core::locale; -use icu_plurals::{PluralCategory, PluralOperands, PluralRuleType, PluralRulesWithRanges}; +use icu_plurals::{PluralCategory, PluralOperands, PluralRulesWithRanges}; #[test] fn test_plural_ranges_raw() { @@ -37,8 +37,7 @@ fn test_plural_ranges_missing_data_fallback() { #[test] fn test_plural_ranges_full() { - let ranges = - PluralRulesWithRanges::try_new(locale!("sl").into(), PluralRuleType::Cardinal).unwrap(); + let ranges = PluralRulesWithRanges::try_new(locale!("sl").into(), Default::default()).unwrap(); let start: PluralOperands = "0.5".parse().unwrap(); // PluralCategory::Other let end: PluralOperands = PluralOperands::from(1); // PluralCategory::One diff --git a/ffi/capi/src/displaynames.rs b/ffi/capi/src/displaynames.rs index 3234f87b8ce..0741ec95f3a 100644 --- a/ffi/capi/src/displaynames.rs +++ b/ffi/capi/src/displaynames.rs @@ -70,7 +70,7 @@ pub mod ffi { locale: &Locale, options: DisplayNamesOptionsV1, ) -> Result, DataError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); let options = icu_experimental::displaynames::DisplayNamesOptions::from(options); Ok(Box::new(LocaleDisplayNamesFormatter( @@ -79,7 +79,7 @@ pub mod ffi { icu_experimental::displaynames::LocaleDisplayNamesFormatter::try_new_with_any_provider, icu_experimental::displaynames::LocaleDisplayNamesFormatter::try_new_with_buffer_provider, provider, - &locale, + prefs, options, )?, ))) @@ -102,13 +102,13 @@ pub mod ffi { provider: &DataProvider, locale: &Locale, ) -> Result, DataError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); Ok(Box::new(RegionDisplayNames(call_constructor!( icu_experimental::displaynames::RegionDisplayNames::try_new, icu_experimental::displaynames::RegionDisplayNames::try_new_with_any_provider, icu_experimental::displaynames::RegionDisplayNames::try_new_with_buffer_provider, provider, - &locale, + prefs, Default::default() )?))) } diff --git a/ffi/capi/src/week.rs b/ffi/capi/src/week.rs index 4c7c2e3b023..8350330e389 100644 --- a/ffi/capi/src/week.rs +++ b/ffi/capi/src/week.rs @@ -40,14 +40,14 @@ pub mod ffi { provider: &DataProvider, locale: &Locale, ) -> Result, DataError> { - let locale = locale.to_datalocale(); + let prefs = (&locale.0).into(); Ok(Box::new(WeekCalculator(call_constructor!( icu_calendar::week::WeekCalculator::try_new, icu_calendar::week::WeekCalculator::try_new_with_any_provider, icu_calendar::week::WeekCalculator::try_new_with_buffer_provider, provider, - &locale, + prefs, )?))) } diff --git a/ffi/capi/tests/missing_apis.txt b/ffi/capi/tests/missing_apis.txt index 5f680e137f8..f6e6f8709e5 100644 --- a/ffi/capi/tests/missing_apis.txt +++ b/ffi/capi/tests/missing_apis.txt @@ -489,6 +489,9 @@ icu::plurals::PluralElements::with_zero_value#FnInStruct icu::plurals::PluralElements::zero#FnInStruct icu::plurals::PluralOperands::is_exactly_one#FnInStruct icu::plurals::PluralOperands::is_exactly_zero#FnInStruct +icu::plurals::PluralRulesOptions#Struct +icu::plurals::PluralRulesOptions::default#FnInStruct +icu::plurals::PluralRulesOptions::with_type#FnInStruct icu::plurals::PluralRulesPreferences#Struct icu::plurals::PluralRulesPreferences::extend#FnInStruct icu::properties::PropertyNamesLong#Struct diff --git a/ffi/ecma402/src/pluralrules.rs b/ffi/ecma402/src/pluralrules.rs index 64ca7eda5ba..baa4bc9e3ac 100644 --- a/ffi/ecma402/src/pluralrules.rs +++ b/ffi/ecma402/src/pluralrules.rs @@ -251,7 +251,7 @@ impl ecma402_traits::pluralrules::PluralRules for PluralRules { let rule_type = internal::to_icu4x_type(&opts.in_type); - let rep = ipr::PluralRules::try_new(prefs, rule_type)?; + let rep = ipr::PluralRules::try_new(prefs, rule_type.into())?; Ok(Self { opts, rep }) } diff --git a/tutorials/rust/experimental/src/main.rs b/tutorials/rust/experimental/src/main.rs index b773da04282..40ef1026391 100644 --- a/tutorials/rust/experimental/src/main.rs +++ b/tutorials/rust/experimental/src/main.rs @@ -11,7 +11,7 @@ use icu::locale::{locale, subtags::region}; fn main() { let names = RegionDisplayNames::try_new( - &locale!("fr").into(), + locale!("fr").into(), Default::default(), ) .expect("locale 'fr' should be present in compiled data");