Skip to content

Commit

Permalink
fmt: migrate other fractional printing to FractionalFormatter
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
BurntSushi committed Aug 3, 2024
1 parent 185c531 commit 38bc73a
Show file tree
Hide file tree
Showing 3 changed files with 11 additions and 60 deletions.
5 changes: 2 additions & 3 deletions src/fmt/offset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(())
Expand Down
15 changes: 8 additions & 7 deletions src/fmt/temporal/printer.rs
Original file line number Diff line number Diff line change
@@ -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},
Expand Down Expand Up @@ -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(":")?;
Expand All @@ -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(())
}
Expand Down Expand Up @@ -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("-")?;
Expand Down Expand Up @@ -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")?;
}
Expand Down
51 changes: 1 addition & 50 deletions src/fmt/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ pub(crate) struct DecimalFormatter {
force_sign: Option<bool>,
minimum_digits: Option<u8>,
padding_byte: u8,
minimum_precision: Option<u8>,
}

impl DecimalFormatter {
Expand All @@ -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)
}
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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
}

Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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]
Expand Down

0 comments on commit 38bc73a

Please sign in to comment.