diff --git a/core/functions/printf.rs b/core/functions/printf.rs index 7033dcf62..3b1cc59f8 100644 --- a/core/functions/printf.rs +++ b/core/functions/printf.rs @@ -34,7 +34,7 @@ fn get_exponential_formatted_str(number: &f64, uppercase: bool) -> crate::Result } } -// TODO: Support %!.3s %x, %X, %o, %c. flags: - + 0 ! , +// TODO: Support %!.3s %x, %X, %o. flags: - + 0 ! , #[inline(always)] pub fn exec_printf(values: &[Register]) -> crate::Result { if values.is_empty() { @@ -175,6 +175,17 @@ pub fn exec_printf(values: &[Register]) -> crate::Result { } args_index += 1; } + Some('c') => { + if args_index >= values.len() { + return Err(LimboError::InvalidArgument("not enough arguments".into())); + } + let value = &values[args_index].get_value(); + let value_str: String = format!("{value}"); + if !value_str.is_empty() { + result.push_str(&value_str[0..1]); + } + args_index += 1; + } None => { return Err(LimboError::InvalidArgument( "incomplete format specifier".into(), @@ -329,6 +340,35 @@ mod tests { } } + #[test] + fn test_printf_character_formatting() { + let test_cases = vec![ + // Simple character + (vec![text("character: %c"), text("a")], text("character: a")), + // Character with string + ( + vec![text("character: %c"), text("this is a test")], + text("character: t"), + ), + // Character with empty + (vec![text("character: %c"), text("")], text("character: ")), + // Character with integer + ( + vec![text("character: %c"), integer(123)], + text("character: 1"), + ), + // Character with float + ( + vec![text("character: %c"), float(42.5)], + text("character: 4"), + ), + ]; + + for (input, expected) in test_cases { + assert_eq!(exec_printf(&input).unwrap(), *expected.get_value()); + } + } + #[test] fn test_printf_exponential_formatting() { let test_cases = vec![