From 8c86b83afb63c124a153f6f73c2fee87db37239b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teemu=20P=C3=A4tsi?= Date: Sat, 14 Jun 2025 22:23:17 +0300 Subject: [PATCH 1/2] uucore: format: Fix zero padding for hexadecimals --- .../src/lib/features/format/num_format.rs | 41 +++++++------------ 1 file changed, 15 insertions(+), 26 deletions(-) diff --git a/src/uucore/src/lib/features/format/num_format.rs b/src/uucore/src/lib/features/format/num_format.rs index 12e19a095..52065c8b1 100644 --- a/src/uucore/src/lib/features/format/num_format.rs +++ b/src/uucore/src/lib/features/format/num_format.rs @@ -134,16 +134,14 @@ pub struct UnsignedInt { } impl Formatter for UnsignedInt { - fn fmt(&self, mut writer: impl Write, x: u64) -> std::io::Result<()> { + fn fmt(&self, writer: impl Write, x: u64) -> std::io::Result<()> { let mut s = match self.variant { UnsignedIntVariant::Decimal => format!("{x}"), UnsignedIntVariant::Octal(_) => format!("{x:o}"), - UnsignedIntVariant::Hexadecimal(Case::Lowercase, _) => { - format!("{x:x}") - } - UnsignedIntVariant::Hexadecimal(Case::Uppercase, _) => { - format!("{x:X}") - } + UnsignedIntVariant::Hexadecimal(case, _) => match case { + Case::Lowercase => format!("{x:x}"), + Case::Uppercase => format!("{x:X}"), + }, }; // Zeroes do not get a prefix. An octal value does also not get a @@ -156,12 +154,7 @@ impl Formatter for UnsignedInt { }; s = format!("{prefix}{s:0>width$}", width = self.precision); - - match self.alignment { - NumberAlignment::Left => write!(writer, "{s: write!(writer, "{s:>width$}", width = self.width), - NumberAlignment::RightZero => write!(writer, "{s:0>width$}", width = self.width), - } + write_output(writer, "".to_string(), s, self.width, self.alignment) } fn try_from_spec(s: Spec) -> Result { @@ -700,7 +693,14 @@ fn write_output( } } NumberAlignment::RightZero => { - write!(writer, "{sign_indicator}{s:0>remaining_width$}") + // Add the padding after "0x" for hexadecimals + let (prefix, rest) = if s.len() >= 2 && s[..2].eq_ignore_ascii_case("0x") { + (&s[..2], &s[2..]) + } else { + ("", s.as_str()) + }; + let remaining_width = remaining_width.saturating_sub(prefix.len()); + write!(writer, "{sign_indicator}{prefix}{rest:0>remaining_width$}") } } } @@ -1271,18 +1271,7 @@ mod test { assert_eq!(f("%#09.e", &(-100.0).into()), "-001.e+02"); assert_eq!(f("%# 9.E", &100.0.into()), " 1.E+02"); assert_eq!(f("% 12.2A", &(-100.0).into()), " -0XC.80P+3"); - } - - #[test] - #[ignore = "Need issue #7510 to be fixed"] - fn format_float_others_broken() { - // TODO: Merge this back into format_float_others. - let f = |fmt_str: &str, n: &ExtendedBigDecimal| { - let format = Format::::parse(fmt_str).unwrap(); - fmt(&format, n) - }; - - // #7510 assert_eq!(f("%012.2a", &(-100.0).into()), "-0x00c.80p+3"); + assert_eq!(f("%012.2A", &(-100.0).into()), "-0X00C.80P+3"); } } From cf7255f0856afc80dd681658e393642459a1ad23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teemu=20P=C3=A4tsi?= Date: Sun, 15 Jun 2025 00:26:29 +0300 Subject: [PATCH 2/2] printf: Test formatting hex with padding --- tests/by-util/test_printf.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index c0e9c41b3..ef618d0c8 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -906,6 +906,10 @@ fn pad_unsigned_three() { ("%#.3x", "0x003"), ("%#.3X", "0X003"), ("%#.3o", "003"), + ("%#05x", "0x003"), + ("%#05X", "0X003"), + ("%3x", " 3"), + ("%3X", " 3"), ] { new_ucmd!() .args(&[format, "3"])