From 2132f45fcb2ad6dc95a6c4721edde6787bc625fd Mon Sep 17 00:00:00 2001 From: Samuel Collins Date: Mon, 28 Apr 2025 15:04:55 +0100 Subject: [PATCH] add support for padding string and char arguments --- src/format.rs | 46 ++++++++++++++++++++++++++++++++++++++-- tests/compare_to_libc.rs | 6 ++++++ 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/format.rs b/src/format.rs index dec4b40..de5cbfe 100644 --- a/src/format.rs +++ b/src/format.rs @@ -472,7 +472,29 @@ impl Printf for f32 { impl Printf for &str { fn format(&self, spec: &ConversionSpecifier) -> Result { if spec.conversion_type == ConversionType::String { - Ok((*self).to_owned()) + let mut s = String::new(); + + let width: usize = match spec.width { + NumericParam::Literal(w) => w, + _ => { + return Err(PrintfError::Unknown); // should not happen at this point!! + } + } + .try_into() + .unwrap_or_default(); + + if spec.left_adj { + s.push_str(self); + while s.len() < width { + s.push(' '); + } + } else { + while s.len() + self.len() < width { + s.push(' '); + } + s.push_str(self); + } + Ok(s) } else { Err(PrintfError::WrongType) } @@ -486,7 +508,27 @@ impl Printf for char { fn format(&self, spec: &ConversionSpecifier) -> Result { if spec.conversion_type == ConversionType::Char { let mut s = String::new(); - s.push(*self); + + let width: usize = match spec.width { + NumericParam::Literal(w) => w, + _ => { + return Err(PrintfError::Unknown); // should not happen at this point!! + } + } + .try_into() + .unwrap_or_default(); + + if spec.left_adj { + s.push(*self); + while s.len() < width { + s.push(' '); + } + } else { + while s.len() + self.len_utf8() < width { + s.push(' '); + } + s.push(*self); + } Ok(s) } else { Err(PrintfError::WrongType) diff --git a/tests/compare_to_libc.rs b/tests/compare_to_libc.rs index 74f0a9d..a76c8fd 100644 --- a/tests/compare_to_libc.rs +++ b/tests/compare_to_libc.rs @@ -116,6 +116,10 @@ fn test_str() { let c_string = CString::new("test").unwrap(); check_fmt("%s", c_string.as_c_str()); check_fmt("%s", c_string); + check_fmt_s("%4s", "A"); + check_fmt_s("%4s", "ð’€€"); // multi-byte character test (4 bytes) + check_fmt_s("%-4sX", "A"); + check_fmt_s("%-4sX", "ð’€€"); // multi-byte character test (4 bytes) } #[test] @@ -125,6 +129,8 @@ fn test_char() { check_fmt("%c", b'x' as c_char); check_fmt("%c", u16::try_from('x').unwrap()); check_fmt("%c", u32::try_from('x').unwrap()); + check_fmt("%4c", 'A'); + check_fmt("%-4cX", 'A'); } #[test]