From 38bc73ad476e974de2563b0d898a32ccaf220b30 Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Sat, 3 Aug 2024 10:05:01 -0400 Subject: [PATCH] fmt: migrate other fractional printing to FractionalFormatter This migrates everything else over. This also explains why we were able to previously get away with hacking the DecimalFormatter to emit fractions: every other use of FractionalFormatter doesn't care about setting a fixed precision. Although we may want to expose an option to do so in the future, and it should be easy to do now! This also lets us slightly simplify DecimalFormatter, as it no longer needs to care about precision goop. --- src/fmt/offset.rs | 5 ++-- src/fmt/temporal/printer.rs | 15 ++++++----- src/fmt/util.rs | 51 +------------------------------------ 3 files changed, 11 insertions(+), 60 deletions(-) diff --git a/src/fmt/offset.rs b/src/fmt/offset.rs index 3b15b76..96da13b 100644 --- a/src/fmt/offset.rs +++ b/src/fmt/offset.rs @@ -106,7 +106,7 @@ from [Temporal's hybrid grammar]. use crate::{ error::{err, Error, ErrorContext}, fmt::{ - util::{parse_temporal_fraction, DecimalFormatter}, + util::{parse_temporal_fraction, FractionalFormatter}, Parsed, }, tz::Offset, @@ -242,8 +242,7 @@ impl core::fmt::Display for Numeric { write!(f, ":{:02}", seconds)?; } if let Some(nanos) = self.nanoseconds { - static FMT: DecimalFormatter = - DecimalFormatter::new().fractional(0, 9); + static FMT: FractionalFormatter = FractionalFormatter::new(); write!(f, ".{}", FMT.format(i64::from(nanos)).as_str())?; } Ok(()) diff --git a/src/fmt/temporal/printer.rs b/src/fmt/temporal/printer.rs index 84a291a..35557a4 100644 --- a/src/fmt/temporal/printer.rs +++ b/src/fmt/temporal/printer.rs @@ -1,7 +1,10 @@ use crate::{ civil::{Date, DateTime, Time}, error::Error, - fmt::{util::DecimalFormatter, Write, WriteExt}, + fmt::{ + util::{DecimalFormatter, FractionalFormatter}, + Write, WriteExt, + }, span::Span, tz::{Offset, TimeZone}, util::{rangeint::RFrom, t}, @@ -102,8 +105,7 @@ impl DateTimePrinter { mut wtr: W, ) -> Result<(), Error> { static FMT_TWO: DecimalFormatter = DecimalFormatter::new().padding(2); - static FMT_FRACTION: DecimalFormatter = - DecimalFormatter::new().fractional(0, 9); + static FMT_FRACTION: FractionalFormatter = FractionalFormatter::new(); wtr.write_int(&FMT_TWO, time.hour())?; wtr.write_str(":")?; @@ -113,7 +115,7 @@ impl DateTimePrinter { let fractional_nanosecond = time.subsec_nanosecond(); if fractional_nanosecond != 0 { wtr.write_str(".")?; - wtr.write_int(&FMT_FRACTION, fractional_nanosecond)?; + wtr.write_fraction(&FMT_FRACTION, fractional_nanosecond)?; } Ok(()) } @@ -214,8 +216,7 @@ impl SpanPrinter { mut wtr: W, ) -> Result<(), Error> { static FMT_INT: DecimalFormatter = DecimalFormatter::new(); - static FMT_FRACTION: DecimalFormatter = - DecimalFormatter::new().fractional(0, 9); + static FMT_FRACTION: FractionalFormatter = FractionalFormatter::new(); if span.is_negative() { wtr.write_str("-")?; @@ -310,7 +311,7 @@ impl SpanPrinter { wtr.write_int(&FMT_INT, fraction_second.get())?; if fraction_nano != 0 { wtr.write_str(".")?; - wtr.write_int(&FMT_FRACTION, fraction_nano.get())?; + wtr.write_fraction(&FMT_FRACTION, fraction_nano.get())?; } wtr.write_str("s")?; } diff --git a/src/fmt/util.rs b/src/fmt/util.rs index c54e146..62284d4 100644 --- a/src/fmt/util.rs +++ b/src/fmt/util.rs @@ -20,7 +20,6 @@ pub(crate) struct DecimalFormatter { force_sign: Option, minimum_digits: Option, padding_byte: u8, - minimum_precision: Option, } impl DecimalFormatter { @@ -30,12 +29,12 @@ impl DecimalFormatter { force_sign: None, minimum_digits: None, padding_byte: b'0', - minimum_precision: None, } } /// Format the given value using this configuration as a decimal ASCII /// number. + #[cfg(test)] pub(crate) const fn format(&self, value: i64) -> Decimal { Decimal::new(self, value) } @@ -72,27 +71,6 @@ impl DecimalFormatter { pub(crate) const fn padding_byte(self, byte: u8) -> DecimalFormatter { DecimalFormatter { padding_byte: byte, ..self } } - - /// Sets the maximum precision of this as a fractional number. - /// - /// This is useful for formatting the fractional digits to the right-hand - /// side of a decimal point. - /// - /// This implies `padding(max_precision)`, but also strips all - /// trailing zeros. - /// - /// The maximum precision is capped at the maximum number of digits for an - /// i64 value (which is 19). - pub(crate) const fn fractional( - self, - min_precision: u8, - max_precision: u8, - ) -> DecimalFormatter { - DecimalFormatter { - minimum_precision: Some(min_precision), - ..self.padding(max_precision) - } - } } impl Default for DecimalFormatter { @@ -159,14 +137,6 @@ impl Decimal { decimal.start -= 1; decimal.buf[decimal.start as usize] = ascii_sign; } - if let Some(min_precision) = formatter.minimum_precision { - while decimal.end > decimal.start - && decimal.len() > min_precision - && decimal.buf[decimal.end as usize - 1] == b'0' - { - decimal.end -= 1; - } - } decimal } @@ -210,7 +180,6 @@ impl FractionalFormatter { /// Format the given value using this configuration as a decimal ASCII /// fractional number. - #[cfg(test)] pub(crate) const fn format(&self, value: i64) -> Fractional { Fractional::new(self, value) } @@ -425,24 +394,6 @@ mod tests { let x = DecimalFormatter::new().force_sign(true).padding(4).format(789); assert_eq!(x.as_str(), "+0789"); - - let x = DecimalFormatter::new().fractional(0, 9).format(123_000_000); - assert_eq!(x.as_str(), "123"); - - let x = DecimalFormatter::new().fractional(0, 9).format(123_456_000); - assert_eq!(x.as_str(), "123456"); - - let x = DecimalFormatter::new().fractional(0, 9).format(123_456_789); - assert_eq!(x.as_str(), "123456789"); - - let x = DecimalFormatter::new().fractional(0, 9).format(456_789); - assert_eq!(x.as_str(), "000456789"); - - let x = DecimalFormatter::new().fractional(0, 9).format(789); - assert_eq!(x.as_str(), "000000789"); - - let x = DecimalFormatter::new().fractional(6, 9).format(123_000_000); - assert_eq!(x.as_str(), "123000"); } #[test]