From 31373819f2ab2c009a28e1a4d6dd7ba1b4dedf9b Mon Sep 17 00:00:00 2001 From: NetterSilver <133535268+Silvertree2010@users.noreply.github.com> Date: Sat, 17 Oct 2026 11:42:35 +0200 Subject: [PATCH] Zero-pad required integer digits in FormCalc Format() Found while testing crates/js/src/formcalc.rs:2240-2276 ("format" builtin, number branch) Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 Co-Authored-By: Claude Haiku 5.5 Co-Authored-By: Claude Sonnet 5.5 --- crates/js/src/formcalc.rs | 5 ++++- crates/js/src/tests.rs | 9 +++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/js/src/formcalc.rs b/crates/js/src/formcalc.rs index cf82eff46..0b12347bd 100644 --- a/crates/js/src/formcalc.rs +++ b/crates/js/src/formcalc.rs @@ -2261,8 +2261,11 @@ impl Interp<'_> { } let num = self.to_num(&v); let decimals = pic.split_once('.').map_or(0, |(_, f)| f.chars().filter(|c| matches!(c, '9' | 'z' | 'Z')).count()).min(20); + // `9` in the integer part forces a digit; `z` does not. + let min_int = pic.split('.').next().map_or(0, |i| i.chars().filter(|c| *c == '9').count()).min(20); + let width = min_int + if decimals > 0 { decimals + 1 } else { 0 }; let grouped = pic.contains(','); - let mut text = fixed(num.abs(), decimals); + let mut text = format!("{:0>width$}", fixed(num.abs(), decimals)); if grouped { let (int, frac) = text.split_once('.').map_or((text.as_str(), ""), |(a, b)| (a, b)); let mut g = String::new(); diff --git a/crates/js/src/tests.rs b/crates/js/src/tests.rs index 4fe5fd290..3f4647d16 100644 --- a/crates/js/src/tests.rs +++ b/crates/js/src/tests.rs @@ -705,6 +705,15 @@ mod formcalc { assert!(go("Nope(1)", "form1[0].page1[0].total[0]", "calculate").error.unwrap().contains("unknown function")); } + #[test] + fn format_nine_pads_the_integer_part() { + assert_eq!(calc(r#"Format("99999", 42)"#), "00042"); + assert_eq!(calc(r#"Format("9999", 5)"#), "0005"); + assert_eq!(calc(r#"Format("999.99", 4.5)"#), "004.50"); + assert_eq!(calc(r#"Format("zzz9", 42)"#), "42"); + assert_eq!(calc(r#"Format("99", 12345)"#), "12345"); + } + #[test] fn date2num_rejects_days_past_the_end_of_the_month() { assert_eq!(calc(r#"Date2Num("2023-02-30")"#), "0");