Skip to content

Commit

Permalink
Add lower-level data API to PluralRules (#575)
Browse files Browse the repository at this point in the history
* Add lower-level data API to PluralRules

* Switch to using PluralRulesV1

* Move code to resolver module; turn into free function
  • Loading branch information
Manishearth authored Apr 8, 2021
1 parent 653c3ec commit 03be3a1
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 24 deletions.
41 changes: 17 additions & 24 deletions components/plurals/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub use error::PluralRulesError;
use icu_locid::LanguageIdentifier;
use icu_provider::prelude::*;
pub use operands::PluralOperands;
use provider::{resolver, PluralRuleStringsV1};
use std::convert::TryInto;

/// A type of a plural rule which can be associated with the [`PluralRules`] struct.
Expand Down Expand Up @@ -269,34 +270,13 @@ impl PluralRules {
///
/// [`type`]: PluralRuleType
/// [`data provider`]: icu_provider::DataProvider
pub fn try_new<'d, D: DataProvider<'d, provider::PluralRuleStringsV1<'d>> + ?Sized>(
pub fn try_new<'d, D: DataProvider<'d, PluralRuleStringsV1<'d>> + ?Sized>(
langid: LanguageIdentifier,
data_provider: &D,
type_: PluralRuleType,
) -> Result<Self, PluralRulesError> {
let key = match type_ {
PluralRuleType::Cardinal => provider::key::CARDINAL_V1,
PluralRuleType::Ordinal => provider::key::ORDINAL_V1,
};
let plurals_data = data_provider
.load_payload(&DataRequest {
resource_path: ResourcePath {
key,
options: ResourceOptions {
variant: None,
langid: Some(langid.clone()),
},
},
})?
.payload
.take()?;

let list: data::PluralRuleList = (&*plurals_data).try_into()?;

Ok(Self {
_langid: langid,
selector: list.into(),
})
let data = resolver::resolve_plural_data(langid.clone(), data_provider, type_)?;
Self::new_from_data(langid, &data)
}

/// Returns the [`Plural Category`] appropriate for the given number.
Expand Down Expand Up @@ -359,4 +339,17 @@ impl PluralRules {
pub fn select<I: Into<PluralOperands>>(&self, input: I) -> PluralCategory {
self.selector.select(&input.into())
}

/// Lower-level constructor that allows constructing a PluralRules directly from
/// data obtained from a provider
pub fn new_from_data<'d>(
langid: LanguageIdentifier,
data: &PluralRuleStringsV1<'d>,
) -> Result<Self, PluralRulesError> {
let data: data::PluralRuleList = data.try_into()?;
Ok(Self {
_langid: langid,
selector: data.into(),
})
}
}
2 changes: 2 additions & 0 deletions components/plurals/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub mod key {
pub const ORDINAL_V1: ResourceKey = resource_key!(plurals, "ordinal", 1);
}

pub mod resolver;

/// Plural rule strings conforming to UTS 35 syntax. Includes separate fields for five of the six
/// standard plural forms. If none of the rules match, the "other" category is assumed.
///
Expand Down
32 changes: 32 additions & 0 deletions components/plurals/src/provider/resolver.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// 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::PluralRuleStringsV1;
use crate::{PluralRuleType, PluralRulesError};
use icu_locid::LanguageIdentifier;
use icu_provider::prelude::*;
use std::borrow::Cow;

pub fn resolve_plural_data<'s, D: DataProvider<'s, PluralRuleStringsV1<'s>> + ?Sized>(
langid: LanguageIdentifier,
data_provider: &D,
type_: PluralRuleType,
) -> Result<Cow<'s, PluralRuleStringsV1<'s>>, PluralRulesError> {
let key = match type_ {
PluralRuleType::Cardinal => super::key::CARDINAL_V1,
PluralRuleType::Ordinal => super::key::ORDINAL_V1,
};
Ok(data_provider
.load_payload(&DataRequest {
resource_path: ResourcePath {
key,
options: ResourceOptions {
variant: None,
langid: Some(langid),
},
},
})?
.payload
.take()?)
}

0 comments on commit 03be3a1

Please sign in to comment.