From 8e11dab995a5377827eba6a815cef501c09a4015 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Wed, 5 Mar 2025 20:00:20 +0100 Subject: [PATCH] uucode: format: Change Formatter to take an &ExtendedBigDecimal Only changes the external interface, right now the number is casted back to f64 for printing. We'll update that in follow-up. --- src/uu/dd/src/progress.rs | 2 +- src/uu/seq/src/seq.rs | 16 +++------------- .../src/lib/features/format/num_format.rs | 17 ++++++++++++++--- src/uucore/src/lib/features/format/spec.rs | 7 ++++--- 4 files changed, 22 insertions(+), 20 deletions(-) diff --git a/src/uu/dd/src/progress.rs b/src/uu/dd/src/progress.rs index 268b3d5f4..7d7554420 100644 --- a/src/uu/dd/src/progress.rs +++ b/src/uu/dd/src/progress.rs @@ -157,7 +157,7 @@ impl ProgUpdate { variant: FloatVariant::Shortest, ..Default::default() } - .fmt(&mut duration_str, duration)?; + .fmt(&mut duration_str, &duration.into())?; // We assume that printf will output valid UTF-8 let duration_str = std::str::from_utf8(&duration_str).unwrap(); diff --git a/src/uu/seq/src/seq.rs b/src/uu/seq/src/seq.rs index caa5b0eb3..91dd091c4 100644 --- a/src/uu/seq/src/seq.rs +++ b/src/uu/seq/src/seq.rs @@ -149,7 +149,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { let format = options .format - .map(Format::::parse) + .map(Format::::parse) .transpose()?; let result = print_seq( @@ -258,7 +258,7 @@ fn print_seq( terminator: &str, pad: bool, padding: usize, - format: Option<&Format>, + format: Option<&Format>, ) -> std::io::Result<()> { let stdout = stdout().lock(); let mut stdout = BufWriter::new(stdout); @@ -293,17 +293,7 @@ fn print_seq( // shouldn't have to do so much converting back and forth via // strings. match &format { - Some(f) => { - let float = match &value { - ExtendedBigDecimal::BigDecimal(bd) => bd.to_f64().unwrap(), - ExtendedBigDecimal::Infinity => f64::INFINITY, - ExtendedBigDecimal::MinusInfinity => f64::NEG_INFINITY, - ExtendedBigDecimal::MinusZero => -0.0, - ExtendedBigDecimal::Nan => f64::NAN, - ExtendedBigDecimal::MinusNan => -f64::NAN, - }; - f.fmt(&mut stdout, float)?; - } + Some(f) => f.fmt(&mut stdout, &value)?, None => write_value_float(&mut stdout, &value, padding, precision)?, } // TODO Implement augmenting addition. diff --git a/src/uucore/src/lib/features/format/num_format.rs b/src/uucore/src/lib/features/format/num_format.rs index 3430ca674..62a1a16dc 100644 --- a/src/uucore/src/lib/features/format/num_format.rs +++ b/src/uucore/src/lib/features/format/num_format.rs @@ -5,12 +5,13 @@ //! Utilities for formatting numbers in various formats +use num_traits::ToPrimitive; use std::cmp::min; use std::io::Write; use super::{ spec::{CanAsterisk, Spec}, - FormatError, + ExtendedBigDecimal, FormatError, }; pub trait Formatter { @@ -231,9 +232,19 @@ impl Default for Float { } } -impl Formatter for Float { - fn fmt(&self, writer: impl Write, f: f64) -> std::io::Result<()> { +impl Formatter<&ExtendedBigDecimal> for Float { + fn fmt(&self, writer: impl Write, e: &ExtendedBigDecimal) -> std::io::Result<()> { + // TODO: For now we just convert ExtendedBigDecimal back to f64, fix this. + let f = match e { + ExtendedBigDecimal::BigDecimal(bd) => bd.to_f64().unwrap(), + ExtendedBigDecimal::Infinity => f64::INFINITY, + ExtendedBigDecimal::MinusInfinity => f64::NEG_INFINITY, + ExtendedBigDecimal::MinusZero => -0.0, + ExtendedBigDecimal::Nan => f64::NAN, + ExtendedBigDecimal::MinusNan => -f64::NAN, + }; let x = f.abs(); + let s = if x.is_finite() { match self.variant { FloatVariant::Decimal => { diff --git a/src/uucore/src/lib/features/format/spec.rs b/src/uucore/src/lib/features/format/spec.rs index 5d45d928a..190a4f2f0 100644 --- a/src/uucore/src/lib/features/format/spec.rs +++ b/src/uucore/src/lib/features/format/spec.rs @@ -12,7 +12,7 @@ use super::{ self, Case, FloatVariant, ForceDecimal, Formatter, NumberAlignment, PositiveSign, Prefix, UnsignedIntVariant, }, - parse_escape_only, ArgumentIter, FormatChar, FormatError, OctalParsing, + parse_escape_only, ArgumentIter, ExtendedBigDecimal, FormatChar, FormatError, OctalParsing, }; use std::{io::Write, ops::ControlFlow}; @@ -432,7 +432,8 @@ impl Spec { } => { let width = resolve_asterisk(*width, &mut args).unwrap_or(0); let precision = resolve_asterisk(*precision, &mut args).unwrap_or(6); - let f = args.get_f64(); + // TODO: We should implement some get_extendedBigDecimal function in args to avoid losing precision. + let f: ExtendedBigDecimal = args.get_f64().into(); if precision as u64 > i32::MAX as u64 { return Err(FormatError::InvalidPrecision(precision.to_string())); @@ -447,7 +448,7 @@ impl Spec { positive_sign: *positive_sign, alignment: *alignment, } - .fmt(writer, f) + .fmt(writer, &f) .map_err(FormatError::IoError) } }