#[diplomat::bridge]
#[diplomat::abi_rename = "icu4x_{0}_mv1"]
#[diplomat::attr(auto, namespace = "icu4x")]
pub mod ffi {
use alloc::boxed::Box;
#[cfg(any(feature = "compiled_data", feature = "buffer_provider"))]
use crate::locale_core::ffi::Locale;
#[cfg(feature = "buffer_provider")]
use crate::provider::ffi::DataProvider;
use crate::{errors::ffi::DataError, fixed_decimal::ffi::Decimal};
use icu_decimal::options::DecimalFormatterOptions;
#[cfg(any(feature = "compiled_data", feature = "buffer_provider"))]
use icu_decimal::DecimalFormatterPreferences;
use writeable::Writeable;
#[diplomat::opaque]
#[diplomat::rust_link(icu::decimal::DecimalFormatter, Struct)]
#[diplomat::rust_link(icu::datetime::FormattedDecimal, Struct, hidden)]
pub struct DecimalFormatter(pub icu_decimal::DecimalFormatter);
#[diplomat::rust_link(icu::decimal::options::GroupingStrategy, Enum)]
#[diplomat::enum_convert(icu_decimal::options::GroupingStrategy, needs_wildcard)]
pub enum DecimalGroupingStrategy {
Auto,
Never,
Always,
Min2,
}
impl DecimalFormatter {
#[diplomat::rust_link(icu::decimal::DecimalFormatter::try_new, FnInStruct)]
#[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_grouping_strategy")]
#[diplomat::demo(default_constructor)]
#[cfg(feature = "compiled_data")]
pub fn create_with_grouping_strategy(
locale: &Locale,
grouping_strategy: Option<DecimalGroupingStrategy>,
) -> Result<Box<DecimalFormatter>, DataError> {
let prefs = DecimalFormatterPreferences::from(&locale.0);
let mut options = DecimalFormatterOptions::default();
options.grouping_strategy = grouping_strategy.map(Into::into);
Ok(Box::new(DecimalFormatter(
icu_decimal::DecimalFormatter::try_new(prefs, options)?,
)))
}
#[diplomat::rust_link(icu::decimal::DecimalFormatter::try_new, FnInStruct)]
#[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_grouping_strategy_and_provider")]
#[diplomat::demo(default_constructor)]
#[cfg(feature = "buffer_provider")]
pub fn create_with_grouping_strategy_and_provider(
provider: &DataProvider,
locale: &Locale,
grouping_strategy: Option<DecimalGroupingStrategy>,
) -> Result<Box<DecimalFormatter>, DataError> {
let prefs = DecimalFormatterPreferences::from(&locale.0);
let mut options = DecimalFormatterOptions::default();
options.grouping_strategy = grouping_strategy.map(Into::into);
Ok(Box::new(DecimalFormatter(
icu_decimal::DecimalFormatter::try_new_with_buffer_provider(
provider.get()?,
prefs,
options,
)?,
)))
}
#[diplomat::rust_link(icu::decimal::provider::DecimalSymbolsV1, Struct)]
#[allow(clippy::too_many_arguments)]
pub fn create_with_manual_data(
plus_sign_prefix: &DiplomatStr,
plus_sign_suffix: &DiplomatStr,
minus_sign_prefix: &DiplomatStr,
minus_sign_suffix: &DiplomatStr,
decimal_separator: &DiplomatStr,
grouping_separator: &DiplomatStr,
primary_group_size: u8,
secondary_group_size: u8,
min_group_size: u8,
digits: &[DiplomatChar],
grouping_strategy: Option<DecimalGroupingStrategy>,
) -> Result<Box<DecimalFormatter>, DataError> {
use core::cell::RefCell;
use icu_provider::prelude::*;
use zerovec::VarZeroCow;
fn str_to_cow(s: &'_ diplomat_runtime::DiplomatStr) -> VarZeroCow<'_, str> {
if let Ok(s) = core::str::from_utf8(s) {
VarZeroCow::new_borrowed(s)
} else {
VarZeroCow::new_owned(
alloc::string::String::from_utf8_lossy(s)
.into_owned()
.into_boxed_str(),
)
}
}
use icu_decimal::provider::{
DecimalDigitsV1, DecimalSymbolStrsBuilder, DecimalSymbols, DecimalSymbolsV1,
GroupingSizes,
};
let mut new_digits = ['\0'; 10];
for (old, new) in digits
.iter()
.copied()
.chain(core::iter::repeat(char::REPLACEMENT_CHARACTER as u32))
.zip(new_digits.iter_mut())
{
*new = char::from_u32(old).unwrap_or(char::REPLACEMENT_CHARACTER);
}
let digits = new_digits;
let strings = DecimalSymbolStrsBuilder {
plus_sign_prefix: str_to_cow(plus_sign_prefix),
plus_sign_suffix: str_to_cow(plus_sign_suffix),
minus_sign_prefix: str_to_cow(minus_sign_prefix),
minus_sign_suffix: str_to_cow(minus_sign_suffix),
decimal_separator: str_to_cow(decimal_separator),
grouping_separator: str_to_cow(grouping_separator),
numsys: "zyyy".into(),
};
let grouping_sizes = GroupingSizes {
primary: primary_group_size,
secondary: secondary_group_size,
min_grouping: min_group_size,
};
let mut options = DecimalFormatterOptions::default();
options.grouping_strategy = grouping_strategy.map(Into::into);
struct Provider(RefCell<Option<DecimalSymbols<'static>>>, [char; 10]);
impl DataProvider<DecimalSymbolsV1> for Provider {
fn load(
&self,
_req: icu_provider::DataRequest,
) -> Result<icu_provider::DataResponse<DecimalSymbolsV1>, icu_provider::DataError>
{
Ok(DataResponse {
metadata: Default::default(),
payload: DataPayload::from_owned(
self.0
.borrow_mut()
.take()
.ok_or(DataErrorKind::Custom.into_error())?,
),
})
}
}
impl DataProvider<DecimalDigitsV1> for Provider {
fn load(
&self,
_req: icu_provider::DataRequest,
) -> Result<icu_provider::DataResponse<DecimalDigitsV1>, icu_provider::DataError>
{
Ok(DataResponse {
metadata: Default::default(),
payload: DataPayload::from_owned(self.1),
})
}
}
let provider = Provider(
RefCell::new(Some(DecimalSymbols {
strings: VarZeroCow::from_encodeable(&strings),
grouping_sizes,
})),
digits,
);
Ok(Box::new(DecimalFormatter(
icu_decimal::DecimalFormatter::try_new_unstable(
&provider,
Default::default(),
options,
)?,
)))
}
#[diplomat::rust_link(icu::decimal::DecimalFormatter::format, FnInStruct)]
#[diplomat::rust_link(icu::decimal::DecimalFormatter::format_to_string, FnInStruct, hidden)]
#[diplomat::rust_link(icu::decimal::FormattedDecimal, Struct, hidden)]
#[diplomat::rust_link(icu::decimal::FormattedDecimal::write_to, FnInStruct, hidden)]
#[diplomat::rust_link(icu::decimal::FormattedDecimal::to_string, FnInStruct, hidden)]
pub fn format(&self, value: &Decimal, write: &mut diplomat_runtime::DiplomatWrite) {
let _infallible = self.0.format(&value.0).write_to(write);
}
}
}