Add tests for leading zeros.
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 24 Mar 2025 01:16:22 +0000 (18:16 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 24 Mar 2025 01:16:22 +0000 (18:16 -0700)
rust/pspp/src/format/mod.rs

index 9a2375bd9384db39053c4ec8cc9705d0e1ab037f..c49d4a2226d4c6da73ee268b406ad7a2edad644e 100644 (file)
@@ -543,6 +543,10 @@ impl Format {
         self.d as usize
     }
 
+    pub fn new(type_: Type, w: Width, d: Decimals) -> Option<Self> {
+        UncheckedFormat { type_, w, d }.try_into().ok()
+    }
+
     pub fn default_for_width(var_width: VarWidth) -> Self {
         match var_width {
             VarWidth::Numeric => Format {
@@ -861,6 +865,12 @@ impl Settings {
         self.ccs[cc] = Some(Box::new(style));
         self
     }
+    pub fn with_leading_zero(self, leading_zero: bool) -> Self {
+        Self {
+            leading_zero,
+            ..self
+        }
+    }
     fn number_style(&self, type_: Type) -> &NumberStyle {
         static DEFAULT: LazyLock<NumberStyle> =
             LazyLock::new(|| NumberStyle::new("", "", Decimal::Dot, None, false));
@@ -1972,7 +1982,7 @@ mod test {
 
     use crate::{
         dictionary::Value,
-        format::{AbstractFormat, Format, Settings, UncheckedFormat, CC},
+        format::{AbstractFormat, Format, Settings, Type, UncheckedFormat, CC},
         lex::{
             scan::StringScanner,
             segment::Syntax,
@@ -2101,4 +2111,47 @@ mod test {
     fn cce() {
         test("cce.txt");
     }
+
+    #[test]
+    fn leading_zeros() {
+        struct Test {
+            with_leading_zero: Settings,
+            without_leading_zero: Settings,
+        }
+
+        impl Test {
+            fn new() -> Self {
+                Self {
+                    without_leading_zero: Settings::default(),
+                    with_leading_zero: Settings::default().with_leading_zero(true),
+                }
+            }
+
+            fn test_with_settings(value: f64, expected: [&str; 2], settings: &Settings) {
+                let value = Value::from(value);
+                for (expected, d) in expected.into_iter().zip([2, 1].into_iter()) {
+                    assert_eq!(
+                        &value
+                            .display(Format::new(Type::F, 5, d).unwrap(), UTF_8)
+                            .with_settings(settings)
+                            .to_string(),
+                        expected
+                    );
+                }
+            }
+            fn test(&self, value: f64, without: [&str; 2], with: [&str; 2]) {
+                Self::test_with_settings(value, without, &self.without_leading_zero);
+                Self::test_with_settings(value, with, &self.with_leading_zero);
+            }
+        }
+        let test = Test::new();
+        test.test(0.5, ["  .50", "   .5"], [" 0.50", "  0.5"]);
+        test.test(0.99, ["  .99", "  1.0"], [" 0.99", "  1.0"]);
+        test.test(0.01, ["  .01", "   .0"], [" 0.01", "  0.0"]);
+        test.test(0.0, ["  .00", "   .0"], [" 0.00", "  0.0"]);
+        test.test(-0.0, ["  .00", "   .0"], [" 0.00", "  0.0"]);
+        test.test(-0.5, [" -.50", "  -.5"], ["-0.50", " -0.5"]);
+        test.test(-0.99, [" -.99", " -1.0"], ["-0.99", " -1.0"]);
+        test.test(-0.01, [" -.01", "   .0"], ["-0.01", "  0.0"]);
+    }
 }