use core::fmt::Display;
use crate::dimension::provider::{
currency::compact::ShortCurrencyCompactV1, currency::essentials::CurrencyEssentialsV1,
};
use fixed_decimal::Decimal;
use icu_decimal::preferences::CompactDecimalFormatterPreferences;
use icu_decimal::{DecimalFormatter, DecimalFormatterPreferences};
use icu_locale_core::preferences::{define_preferences, prefs_convert};
use icu_plurals::{PluralRules, PluralRulesPreferences};
use icu_provider::prelude::*;
use writeable::Writeable;
use super::{options::CurrencyFormatterOptions, CurrencyCode};
extern crate alloc;
define_preferences!(
[Copy]
CompactCurrencyFormatterPreferences,
{
numbering_system: crate::dimension::preferences::NumberingSystem
}
);
prefs_convert!(
CompactCurrencyFormatterPreferences,
DecimalFormatterPreferences,
{ numbering_system }
);
prefs_convert!(
CompactCurrencyFormatterPreferences,
CompactDecimalFormatterPreferences
);
prefs_convert!(CompactCurrencyFormatterPreferences, PluralRulesPreferences);
#[derive(Debug)]
pub struct CompactCurrencyFormatter {
_short_currency_compact: DataPayload<ShortCurrencyCompactV1>,
essential: DataPayload<CurrencyEssentialsV1>,
decimal_formatter: DecimalFormatter,
compact_data: DataPayload<icu_decimal::provider::DecimalCompactShortV1>,
plural_rules: PluralRules,
options: CurrencyFormatterOptions,
}
impl CompactCurrencyFormatter {
icu_provider::gen_buffer_data_constructors!(
(prefs: CompactCurrencyFormatterPreferences, 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: CompactCurrencyFormatterPreferences,
options: CurrencyFormatterOptions,
) -> Result<Self, DataError> {
let short_locale = ShortCurrencyCompactV1::make_locale(prefs.locale_preferences);
let short_currency_compact = crate::provider::Baked
.load(DataRequest {
id: DataIdentifierBorrowed::for_locale(&short_locale),
..Default::default()
})?
.payload;
let essential_locale = CurrencyEssentialsV1::make_locale(prefs.locale_preferences);
let essential = crate::provider::Baked
.load(DataRequest {
id: DataIdentifierBorrowed::for_locale(&essential_locale),
..Default::default()
})?
.payload;
let decimal_formatter = DecimalFormatter::try_new((&prefs).into(), Default::default())?;
let compact_data = DataProvider::<icu_decimal::provider::DecimalCompactShortV1>::load(
&icu_decimal::provider::Baked,
DataRequest {
id: DataIdentifierBorrowed::for_locale(
&icu_decimal::provider::DecimalCompactShortV1::make_locale(
prefs.locale_preferences,
),
),
..Default::default()
},
)?
.payload
.cast();
let plural_rules = PluralRules::try_new_cardinal((&prefs).into())?;
Ok(Self {
_short_currency_compact: short_currency_compact,
essential,
decimal_formatter,
compact_data,
plural_rules,
options,
})
}
#[doc = icu_provider::gen_buffer_unstable_docs!(UNSTABLE, Self::try_new)]
pub fn try_new_unstable<D>(
provider: &D,
prefs: CompactCurrencyFormatterPreferences,
options: CurrencyFormatterOptions,
) -> Result<Self, DataError>
where
D: ?Sized
+ DataProvider<CurrencyEssentialsV1>
+ DataProvider<ShortCurrencyCompactV1>
+ DataProvider<icu_decimal::provider::DecimalCompactShortV1>
+ DataProvider<icu_decimal::provider::DecimalSymbolsV1>
+ DataProvider<icu_decimal::provider::DecimalDigitsV1>
+ DataProvider<icu_plurals::provider::PluralsCardinalV1>,
{
let locale = CurrencyEssentialsV1::make_locale(prefs.locale_preferences);
let decimal_formatter =
DecimalFormatter::try_new_unstable(provider, (&prefs).into(), Default::default())?;
let compact_data = DataProvider::<icu_decimal::provider::DecimalCompactShortV1>::load(
provider,
DataRequest {
id: DataIdentifierBorrowed::for_locale(
&icu_decimal::provider::DecimalCompactShortV1::make_locale(
prefs.locale_preferences,
),
),
..Default::default()
},
)?
.payload
.cast();
let plural_rules = PluralRules::try_new_cardinal_unstable(provider, (&prefs).into())?;
let short_currency_compact = provider
.load(DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
})?
.payload;
let essential = provider
.load(DataRequest {
id: DataIdentifierBorrowed::for_locale(&locale),
..Default::default()
})?
.payload;
Ok(Self {
_short_currency_compact: short_currency_compact,
essential,
decimal_formatter,
compact_data,
plural_rules,
options,
})
}
pub fn format_fixed_decimal<'l>(
&'l self,
value: &'l Decimal,
currency_code: &'l CurrencyCode,
) -> impl Writeable + Display + 'l {
let (currency_placeholder, pattern, _pattern_selection) = self
.essential
.get()
.name_and_pattern(self.options.width, currency_code);
let (compact_pattern, significand) = self
.compact_data
.get()
.get_pattern_and_significand(&value.absolute, &self.plural_rules);
self.decimal_formatter.format_sign(
value.sign,
pattern.interpolate((
compact_pattern
.unwrap_or(icu_pattern::SinglePlaceholderPattern::PASS_THROUGH)
.interpolate([self
.decimal_formatter
.format_unsigned(icu_decimal::Cow::Owned(significand))]),
currency_placeholder,
)),
)
}
}