use core::fmt::Display;
use fixed_decimal::Decimal;
use icu_decimal::{
options::DecimalFormatterOptions, DecimalFormatter, DecimalFormatterPreferences,
};
use icu_locale_core::preferences::{define_preferences, prefs_convert};
use icu_plurals::PluralRulesPreferences;
use icu_provider::prelude::*;
use writeable::Writeable;
use super::super::provider::currency::essentials::CurrencyEssentialsV1;
use super::options::CurrencyFormatterOptions;
use super::CurrencyCode;
extern crate alloc;
define_preferences!(
[Copy]
CurrencyFormatterPreferences,
{
numbering_system: crate::dimension::preferences::NumberingSystem
}
);
prefs_convert!(CurrencyFormatterPreferences, DecimalFormatterPreferences, {
numbering_system
});
prefs_convert!(CurrencyFormatterPreferences, PluralRulesPreferences);
#[derive(Debug)]
pub struct CurrencyFormatter {
options: CurrencyFormatterOptions,
essential: DataPayload<CurrencyEssentialsV1>,
decimal_formatter: DecimalFormatter,
}
impl CurrencyFormatter {
icu_provider::gen_buffer_data_constructors!(
(prefs: CurrencyFormatterPreferences, options: CurrencyFormatterOptions) -> error: DataError,
functions: [
try_new: skip,
try_new_with_buffer_provider,
try_new_unstable,
Self
]
);
#[cfg(feature = "compiled_data")]
pub fn try_new(
prefs: CurrencyFormatterPreferences,
options: CurrencyFormatterOptions,
) -> Result<Self, DataError> {
let locale = CurrencyEssentialsV1::make_locale(prefs.locale_preferences);
let decimal_formatter =
DecimalFormatter::try_new((&prefs).into(), DecimalFormatterOptions::default())?;
let essential = crate::provider::Baked
.load(DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
})?
.payload;
Ok(Self {
options,
essential,
decimal_formatter,
})
}
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
pub fn try_new_unstable<D>(
provider: &D,
prefs: CurrencyFormatterPreferences,
options: CurrencyFormatterOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<CurrencyEssentialsV1>
+ DataProvider<icu_decimal::provider::DecimalSymbolsV1>
+ DataProvider<icu_decimal::provider::DecimalDigitsV1>,
{
let locale = CurrencyEssentialsV1::make_locale(prefs.locale_preferences);
let decimal_formatter = DecimalFormatter::try_new_unstable(
provider,
(&prefs).into(),
DecimalFormatterOptions::default(),
)?;
let essential = provider
.load(DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
})?
.payload;
Ok(Self {
options,
essential,
decimal_formatter,
})
}
pub fn format_fixed_decimal<'l>(
&'l self,
value: &'l Decimal,
currency_code: &'l CurrencyCode,
) -> impl Writeable + Display + 'l {
let (currency_str, pattern, _pattern_selection) = self
.essential
.get()
.name_and_pattern(self.options.width, currency_code);
self.decimal_formatter.format_sign(
value.sign,
pattern.interpolate((
self.decimal_formatter
.format_unsigned(icu_decimal::Cow::Borrowed(&value.absolute)),
currency_str,
)),
)
}
}