diff --git a/src/uucore/src/lib/features/format/num_format.rs b/src/uucore/src/lib/features/format/num_format.rs index 339b52209..fab81c456 100644 --- a/src/uucore/src/lib/features/format/num_format.rs +++ b/src/uucore/src/lib/features/format/num_format.rs @@ -63,6 +63,7 @@ pub enum NumberAlignment { pub struct SignedInt { pub width: usize, + pub precision: usize, pub positive_sign: PositiveSign, pub alignment: NumberAlignment, } @@ -79,16 +80,19 @@ impl Formatter for SignedInt { }?; } + let s = format!("{:0width$}", x, width = self.precision); + match self.alignment { - NumberAlignment::Left => write!(writer, "{x: write!(writer, "{x:>width$}", width = self.width), - NumberAlignment::RightZero => write!(writer, "{x:0>width$}", width = self.width), + NumberAlignment::Left => write!(writer, "{s: write!(writer, "{s:>width$}", width = self.width), + NumberAlignment::RightZero => write!(writer, "{s:0>width$}", width = self.width), } } fn try_from_spec(s: Spec) -> Result { let Spec::SignedInt { width, + precision, positive_sign, alignment, } = s @@ -102,8 +106,15 @@ impl Formatter for SignedInt { Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError), }; + let precision = match precision { + Some(CanAsterisk::Fixed(x)) => x, + None => 0, + Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError), + }; + Ok(Self { width, + precision, positive_sign, alignment, }) @@ -113,6 +124,7 @@ impl Formatter for SignedInt { pub struct UnsignedInt { pub variant: UnsignedIntVariant, pub width: usize, + pub precision: usize, pub alignment: NumberAlignment, } @@ -120,7 +132,7 @@ impl Formatter for UnsignedInt { type Input = u64; fn fmt(&self, mut writer: impl Write, x: Self::Input) -> std::io::Result<()> { - let s = match self.variant { + let mut s = match self.variant { UnsignedIntVariant::Decimal => format!("{x}"), UnsignedIntVariant::Octal(Prefix::No) => format!("{x:o}"), UnsignedIntVariant::Octal(Prefix::Yes) => format!("{x:#o}"), @@ -138,6 +150,10 @@ impl Formatter for UnsignedInt { } }; + if self.precision > s.len() { + s = format!("{:0width$}", s, width = self.precision) + } + match self.alignment { NumberAlignment::Left => write!(writer, "{s: write!(writer, "{s:>width$}", width = self.width), @@ -149,6 +165,7 @@ impl Formatter for UnsignedInt { let Spec::UnsignedInt { variant, width, + precision, alignment, } = s else { @@ -161,8 +178,15 @@ impl Formatter for UnsignedInt { Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError), }; + let precision = match precision { + Some(CanAsterisk::Fixed(x)) => x, + None => 0, + Some(CanAsterisk::Asterisk) => return Err(FormatError::SpecError), + }; + Ok(Self { width, + precision, variant, alignment, }) diff --git a/src/uucore/src/lib/features/format/spec.rs b/src/uucore/src/lib/features/format/spec.rs index 0f48cdafe..06f0ca1d6 100644 --- a/src/uucore/src/lib/features/format/spec.rs +++ b/src/uucore/src/lib/features/format/spec.rs @@ -22,12 +22,14 @@ pub enum Spec { }, SignedInt { width: Option>, + precision: Option>, positive_sign: PositiveSign, alignment: NumberAlignment, }, UnsignedInt { variant: UnsignedIntVariant, width: Option>, + precision: Option>, alignment: NumberAlignment, }, Float { @@ -167,6 +169,7 @@ impl Spec { }, b'd' | b'i' => Spec::SignedInt { width, + precision, alignment: match (minus, zero) { (true, _) => NumberAlignment::Left, (false, true) => NumberAlignment::RightZero, @@ -197,6 +200,7 @@ impl Spec { }; Spec::UnsignedInt { variant, + precision, width, alignment, } @@ -282,10 +286,12 @@ impl Spec { } &Spec::SignedInt { width, + precision, positive_sign, alignment, } => { let width = resolve_asterisk(width, &mut args)?.unwrap_or(0); + let precision = resolve_asterisk(precision, &mut args)?.unwrap_or(0); let arg = next_arg(&mut args)?; let Some(i) = arg.get_i64() else { @@ -294,6 +300,7 @@ impl Spec { num_format::SignedInt { width, + precision, positive_sign, alignment, } @@ -303,9 +310,11 @@ impl Spec { &Spec::UnsignedInt { variant, width, + precision, alignment, } => { let width = resolve_asterisk(width, &mut args)?.unwrap_or(0); + let precision = resolve_asterisk(precision, &mut args)?.unwrap_or(0); let arg = next_arg(args)?; let Some(i) = arg.get_u64() else { @@ -314,6 +323,7 @@ impl Spec { num_format::UnsignedInt { variant, + precision, width, alignment, }