icu_experimental/compactdecimal/format.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
// 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 alloc::borrow::Cow;
use fixed_decimal::{CompactDecimal, SignedFixedDecimal};
use writeable::Writeable;
use zerovec::maps::ZeroMap2dCursor;
use crate::compactdecimal::formatter::CompactDecimalFormatter;
use crate::compactdecimal::provider::{Count, PatternULE};
/// An intermediate structure returned by [`CompactDecimalFormatter`](super::CompactDecimalFormatter).
/// Use [`Writeable`][Writeable] to render the formatted decimal to a string or buffer.
#[derive(Debug)]
pub struct FormattedCompactDecimal<'l> {
pub(crate) formatter: &'l CompactDecimalFormatter,
pub(crate) value: Cow<'l, CompactDecimal>,
pub(crate) plural_map: Option<ZeroMap2dCursor<'l, 'l, i8, Count, PatternULE>>,
}
impl FormattedCompactDecimal<'_> {
/// Access the resolved [`CompactDecimal`] after formatting.
///
/// # Examples
///
/// ```
/// use fixed_decimal::SignedFixedDecimal;
/// use icu::experimental::compactdecimal::CompactDecimalFormatter;
/// use icu::locale::locale;
/// use writeable::assert_writeable_eq;
///
/// let short_english = CompactDecimalFormatter::try_new_short(
/// locale!("en").into(),
/// Default::default(),
/// )
/// .unwrap();
///
/// let formatted_compact_decimal = short_english.format_i64(2207);
///
/// assert_writeable_eq!(formatted_compact_decimal, "2.2K");
/// assert_eq!(
/// formatted_compact_decimal.get_compact_decimal().to_string(),
/// "2.2c3"
/// );
/// ```
pub fn get_compact_decimal(&self) -> &CompactDecimal {
&self.value
}
}
impl Writeable for FormattedCompactDecimal<'_> {
fn write_to<W>(&self, sink: &mut W) -> core::result::Result<(), core::fmt::Error>
where
W: core::fmt::Write + ?Sized,
{
if self.value.exponent() == 0 {
self.formatter
.fixed_decimal_formatter
.format(self.value.significand())
.write_to(sink)
} else {
let plural_map = self.plural_map.as_ref().ok_or(core::fmt::Error)?;
let chosen_pattern = (|| {
if self.value.significand() == &SignedFixedDecimal::from(1) {
if let Some(pattern) = plural_map.get1(&Count::Explicit1) {
return Some(pattern);
}
}
let plural_category = self
.formatter
.plural_rules
.category_for(self.value.significand());
plural_map
.get1(&plural_category.into())
.or_else(|| plural_map.get1(&Count::Other))
})()
.ok_or(core::fmt::Error)?;
match chosen_pattern.index {
u8::MAX => sink.write_str(&chosen_pattern.literal_text),
_ => {
let i = usize::from(chosen_pattern.index);
sink.write_str(
chosen_pattern
.literal_text
.get(..i)
.ok_or(core::fmt::Error)?,
)?;
self.formatter
.fixed_decimal_formatter
.format(self.value.significand())
.write_to(sink)?;
sink.write_str(
chosen_pattern
.literal_text
.get(i..)
.ok_or(core::fmt::Error)?,
)
}
}
}
}
}
writeable::impl_display_with_writeable!(FormattedCompactDecimal<'_>);