use core::fmt::Write;
use crate::grouper;
use crate::options::*;
use crate::parts;
use crate::provider::*;
use fixed_decimal::Sign;
use fixed_decimal::SignedFixedDecimal;
use writeable::Part;
use writeable::PartsWrite;
use writeable::Writeable;
#[derive(Debug, PartialEq, Clone)]
pub struct FormattedFixedDecimal<'l> {
pub(crate) value: &'l SignedFixedDecimal,
pub(crate) options: &'l FixedDecimalFormatterOptions,
pub(crate) symbols: &'l DecimalSymbolsV2<'l>,
pub(crate) digits: &'l DecimalDigitsV1,
}
impl FormattedFixedDecimal<'_> {
fn get_affixes(&self) -> Option<(Part, (&str, &str))> {
match self.value.sign() {
Sign::None => None,
Sign::Negative => Some((parts::MINUS_SIGN, self.symbols.minus_sign_affixes())),
Sign::Positive => Some((parts::PLUS_SIGN, self.symbols.plus_sign_affixes())),
}
}
}
impl Writeable for FormattedFixedDecimal<'_> {
fn write_to_parts<W>(&self, w: &mut W) -> core::result::Result<(), core::fmt::Error>
where
W: writeable::PartsWrite + ?Sized,
{
let affixes = self.get_affixes();
if let Some((part, affixes)) = affixes {
w.with_part(part, |w| w.write_str(affixes.0))?;
}
let range = self.value.absolute.magnitude_range();
let upper_magnitude = *range.end();
let mut range = range.rev();
let mut has_fraction = false;
w.with_part(parts::INTEGER, |w| {
loop {
let m = match range.next() {
Some(m) if m < 0 => {
has_fraction = true;
break Ok(());
}
Some(m) => m,
None => {
break Ok(());
}
};
#[allow(clippy::indexing_slicing)] w.write_char(self.digits.digits[self.value.digit_at(m) as usize])?;
if grouper::check(
upper_magnitude,
m,
self.options.grouping_strategy,
&self.symbols.grouping_sizes,
) {
w.with_part(parts::GROUP, |w| {
w.write_str(self.symbols.grouping_separator())
})?;
}
}
})?;
if has_fraction {
w.with_part(parts::DECIMAL, |w| {
w.write_str(self.symbols.decimal_separator())
})?;
w.with_part(parts::FRACTION, |w| {
let mut m = -1; loop {
#[allow(clippy::indexing_slicing)] w.write_char(self.digits.digits[self.value.digit_at(m) as usize])?;
m = match range.next() {
Some(m) => m,
None => {
break Ok(());
}
};
}
})?;
}
if let Some((part, affixes)) = affixes {
w.with_part(part, |w| w.write_str(affixes.1))?;
}
Ok(())
}
}
writeable::impl_display_with_writeable!(FormattedFixedDecimal<'_>);
#[cfg(test)]
mod tests {
use icu_locale_core::locale;
use writeable::assert_writeable_eq;
use crate::FixedDecimalFormatter;
#[test]
pub fn test_es_mx() {
let locale = locale!("es-MX").into();
let fmt = FixedDecimalFormatter::try_new(locale, Default::default()).unwrap();
let fd = "12345.67".parse().unwrap();
assert_writeable_eq!(fmt.format(&fd), "12,345.67");
}
}