From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- intl/icu_capi/src/pluralrules.rs | 150 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 intl/icu_capi/src/pluralrules.rs (limited to 'intl/icu_capi/src/pluralrules.rs') diff --git a/intl/icu_capi/src/pluralrules.rs b/intl/icu_capi/src/pluralrules.rs new file mode 100644 index 0000000000..78720f536e --- /dev/null +++ b/intl/icu_capi/src/pluralrules.rs @@ -0,0 +1,150 @@ +// 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 ). + +#[diplomat::bridge] +pub mod ffi { + use core::str::{self}; + + use alloc::boxed::Box; + + use fixed_decimal::FixedDecimal; + use icu_plurals::{PluralCategory, PluralOperands, PluralRules}; + + use crate::{locale::ffi::ICU4XLocale, provider::ffi::ICU4XDataProvider}; + + use crate::errors::ffi::ICU4XError; + + /// FFI version of `PluralCategory`. + #[diplomat::rust_link(icu::plurals::PluralCategory, Enum)] + #[diplomat::enum_convert(PluralCategory)] + pub enum ICU4XPluralCategory { + Zero, + One, + Two, + Few, + Many, + Other, + } + + impl ICU4XPluralCategory { + /// Construct from a string in the format + /// [specified in TR35](https://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules) + #[diplomat::rust_link(icu::plurals::PluralCategory::get_for_cldr_string, FnInEnum)] + #[diplomat::rust_link(icu::plurals::PluralCategory::get_for_cldr_bytes, FnInEnum)] + pub fn get_for_cldr_string(s: &str) -> Result { + let s = s.as_bytes(); // #2520 + PluralCategory::get_for_cldr_bytes(s) + .ok_or(()) + .map(Into::into) + } + } + + /// FFI version of `PluralRules`. + #[diplomat::rust_link(icu::plurals::PluralRules, Struct)] + #[diplomat::opaque] + pub struct ICU4XPluralRules(PluralRules); + + impl ICU4XPluralRules { + /// Construct an [`ICU4XPluralRules`] for the given locale, for cardinal numbers + #[diplomat::rust_link(icu::plurals::PluralRules::try_new_cardinal, FnInStruct)] + #[diplomat::rust_link(icu::plurals::PluralRules::try_new, FnInStruct, hidden)] + #[diplomat::rust_link(icu::plurals::PluralRuleType, Enum, hidden)] + pub fn create_cardinal( + provider: &ICU4XDataProvider, + locale: &ICU4XLocale, + ) -> Result, ICU4XError> { + let locale = locale.to_datalocale(); + Ok(Box::new(ICU4XPluralRules(call_constructor!( + PluralRules::try_new_cardinal, + PluralRules::try_new_cardinal_with_any_provider, + PluralRules::try_new_cardinal_with_buffer_provider, + provider, + &locale + )?))) + } + + /// Construct an [`ICU4XPluralRules`] for the given locale, for ordinal numbers + #[diplomat::rust_link(icu::plurals::PluralRules::try_new_ordinal, FnInStruct)] + #[diplomat::rust_link(icu::plurals::PluralRules::try_new, FnInStruct, hidden)] + #[diplomat::rust_link(icu::plurals::PluralRuleType, Enum, hidden)] + pub fn create_ordinal( + provider: &ICU4XDataProvider, + locale: &ICU4XLocale, + ) -> Result, ICU4XError> { + let locale = locale.to_datalocale(); + Ok(Box::new(ICU4XPluralRules(call_constructor!( + PluralRules::try_new_ordinal, + PluralRules::try_new_ordinal_with_any_provider, + PluralRules::try_new_ordinal_with_buffer_provider, + provider, + &locale + )?))) + } + + /// Get the category for a given number represented as operands + #[diplomat::rust_link(icu::plurals::PluralRules::category_for, FnInStruct)] + pub fn category_for(&self, op: &ICU4XPluralOperands) -> ICU4XPluralCategory { + self.0.category_for(op.0).into() + } + + /// Get all of the categories needed in the current locale + #[diplomat::rust_link(icu::plurals::PluralRules::categories, FnInStruct)] + pub fn categories(&self) -> ICU4XPluralCategories { + ICU4XPluralCategories::from_iter(self.0.categories()) + } + } + + /// FFI version of `PluralOperands`. + #[diplomat::opaque] + #[diplomat::rust_link(icu::plurals::PluralOperands, Struct)] + pub struct ICU4XPluralOperands(pub icu_plurals::PluralOperands); + + impl ICU4XPluralOperands { + /// Construct for a given string representing a number + #[diplomat::rust_link(icu::plurals::PluralOperands::from_str, FnInStruct)] + pub fn create_from_string(s: &str) -> Result, ICU4XError> { + let s = s.as_bytes(); // #2520 + Ok(Box::new(ICU4XPluralOperands(PluralOperands::from( + // XXX should this have its own errors? + &FixedDecimal::try_from(s).map_err(|_| ICU4XError::PluralsParserError)?, + )))) + } + } + + /// FFI version of `PluralRules::categories()` data. + pub struct ICU4XPluralCategories { + pub zero: bool, + pub one: bool, + pub two: bool, + pub few: bool, + pub many: bool, + pub other: bool, + } + + impl ICU4XPluralCategories { + fn from_iter(i: impl Iterator) -> Self { + i.fold( + ICU4XPluralCategories { + zero: false, + one: false, + two: false, + few: false, + many: false, + other: false, + }, + |mut categories, category| { + match category { + PluralCategory::Zero => categories.zero = true, + PluralCategory::One => categories.one = true, + PluralCategory::Two => categories.two = true, + PluralCategory::Few => categories.few = true, + PluralCategory::Many => categories.many = true, + PluralCategory::Other => categories.other = true, + }; + categories + }, + ) + } + } +} -- cgit v1.2.3