Skip to content

Commit

Permalink
Redesign PluralRulesWithRanges
Browse files Browse the repository at this point in the history
  • Loading branch information
jedel1043 committed Nov 10, 2023
1 parent d06bd6f commit 85b30ca
Showing 1 changed file with 77 additions and 59 deletions.
136 changes: 77 additions & 59 deletions components/plurals/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,12 @@ impl PluralCategory {
#[derive(Debug)]
pub struct PluralRules(DataPayload<ErasedPluralRulesV1Marker>);

impl AsRef<PluralRules> for PluralRules {
fn as_ref(&self) -> &PluralRules {
self
}
}

impl PluralRules {
icu_provider::gen_any_buffer_data_constructors!(
locale: include,
Expand Down Expand Up @@ -594,13 +600,13 @@ impl PluralRules {
/// [`Plural Category`]: PluralCategory
#[cfg(feature = "experimental")]
#[derive(Debug)]
pub struct PluralRulesWithRanges {
rules: PluralRules,
pub struct PluralRulesWithRanges<R> {
rules: R,
ranges: DataPayload<PluralRangesV1Marker>,
}

#[cfg(feature = "experimental")]
impl PluralRulesWithRanges {
impl PluralRulesWithRanges<PluralRules> {
icu_provider::gen_any_buffer_data_constructors!(
locale: include,
rule_type: PluralRuleType,
Expand Down Expand Up @@ -678,14 +684,8 @@ impl PluralRulesWithRanges {
locale: &DataLocale,
) -> Result<Self, PluralsError> {
let rules = PluralRules::try_new_cardinal_unstable(provider, locale)?;
let ranges = provider
.load(DataRequest {
locale,
metadata: Default::default(),
})?
.take_payload()?;

Ok(Self { rules, ranges })
PluralRulesWithRanges::try_new_with_rules_unstable(provider, locale, rules)
}

icu_provider::gen_any_buffer_data_constructors!(
Expand Down Expand Up @@ -729,6 +729,60 @@ impl PluralRulesWithRanges {
locale: &DataLocale,
) -> Result<Self, PluralsError> {
let rules = PluralRules::try_new_ordinal_unstable(provider, locale)?;

PluralRulesWithRanges::try_new_with_rules_unstable(provider, locale, rules)
}
}

#[cfg(feature = "experimental")]
impl<R> PluralRulesWithRanges<R>
where
R: AsRef<PluralRules>,
{
icu_provider::gen_any_buffer_data_constructors!(
locale: include,
rules: R,
error: PluralsError,
/// Constructs a new `PluralRulesWithRanges` for a given locale from an existing
/// `PluralRules` (either owned or as a reference) and compiled data.
///
/// # ⚠️ Warning
///
/// The provided `locale` **MUST** be the same as the locale provided to the constructor
/// of `rules`. Otherwise, [`Self::category_for_range`] will return incorrect results.
///
/// ✨ *Enabled with the `compiled_data` Cargo feature.*
///
/// [📚 Help choosing a constructor](icu_provider::constructors)
///
/// # Examples
///
/// ```
/// use icu::locid::locale;
/// use icu::plurals::{PluralRuleType, PluralRulesWithRanges, PluralRules};
///
/// let rules = PluralRules::try_new(&locale!("en").into(), PluralRuleType::Cardinal)
/// .expect("locale should be present");
///
/// let _ =
/// PluralRulesWithRanges::try_new_with_rules(&locale!("en").into(), rules)
/// .expect("locale should be present");
/// ```
functions: [
try_new_with_rules,
try_new_with_rules_with_any_provider,
try_new_with_rules_with_buffer_provider,
try_new_with_rules_unstable,
Self,
]
);

#[doc = icu_provider::gen_any_buffer_unstable_docs!(UNSTABLE, Self::try_new_with_rules)]
pub fn try_new_with_rules_unstable(
provider: &(impl DataProvider<PluralRangesV1Marker> + ?Sized),
locale: &DataLocale,
rules: R,
) -> Result<Self, PluralsError> {
let ranges = provider
.load(DataRequest {
locale,
Expand All @@ -739,61 +793,24 @@ impl PluralRulesWithRanges {
Ok(Self { rules, ranges })
}

/// Returns the [`Plural Category`] appropriate for the given number.
///
/// See [`PluralRules::category_for`] for more information.
/// Gets a reference to the inner `PluralRules`.
///
/// # Examples
///
/// ```
/// use icu::locid::locale;
/// use icu::plurals::{PluralCategory, PluralRuleType, PluralRulesWithRanges};
///
/// let pr = PluralRulesWithRanges::try_new(
/// &locale!("en").into(),
/// PluralRuleType::Cardinal,
/// )
/// .expect("locale should be present");
///
/// match pr.category_for(1_usize) {
/// PluralCategory::One => "One item",
/// PluralCategory::Other => "Many items",
/// _ => unreachable!(),
/// };
/// ```
/// use icu::plurals::{PluralCategory, PluralRulesWithRanges};
///
/// [`Plural Category`]: PluralCategory
pub fn category_for<I: Into<PluralOperands>>(&self, input: I) -> PluralCategory {
self.rules.category_for(input)
}

/// Returns all [`Plural Categories`] appropriate for a [`PluralRulesWithRanges`] object
/// based on the [`LanguageIdentifier`](icu::locid::{LanguageIdentifier}) and [`PluralRuleType`].
///
/// See [`PluralRules::categories`] for more information.
/// let ranges =
/// PluralRulesWithRanges::try_new_cardinal(&locale!("en").into())
/// .expect("locale should be present");
///
/// # Examples
/// let rules = ranges.rules();
///
/// assert_eq!(rules.category_for(1u8), PluralCategory::One);
/// ```
/// use icu::locid::locale;
/// use icu::plurals::{PluralCategory, PluralRuleType, PluralRulesWithRanges};
///
/// let pr = PluralRulesWithRanges::try_new(
/// &locale!("es").into(),
/// PluralRuleType::Cardinal,
/// )
/// .expect("locale should be present");
///
/// let mut categories = pr.categories();
/// assert_eq!(categories.next(), Some(PluralCategory::One));
/// assert_eq!(categories.next(), Some(PluralCategory::Many));
/// assert_eq!(categories.next(), Some(PluralCategory::Other));
/// assert_eq!(categories.next(), None);
/// ```
///
/// [`Plural Categories`]: PluralCategory
pub fn categories(&self) -> impl Iterator<Item = PluralCategory> + '_ {
self.rules.categories()
pub fn rules(&self) -> &PluralRules {
self.rules.as_ref()
}

/// Returns the [`Plural Category`] appropriate for a range.
Expand All @@ -816,7 +833,7 @@ impl PluralRulesWithRanges {
/// )
/// .expect("locale should be present");
/// let operands: PluralOperands =
/// "1.5".parse().expect("parsing to operands should succeed");
/// "0.5".parse().expect("parsing to operands should succeed");
/// let operands2 = PluralOperands::from(1_usize);
///
/// assert_eq!(
Expand All @@ -831,8 +848,9 @@ impl PluralRulesWithRanges {
start: S,
end: E,
) -> PluralCategory {
let start = self.rules.category_for(start);
let end = self.rules.category_for(end);
let rules = self.rules.as_ref();
let start = rules.category_for(start);
let end = rules.category_for(end);

self.resolve_range(start, end)
}
Expand Down

0 comments on commit 85b30ca

Please sign in to comment.