From c123fa2ae0aa74118d8e791b70ae6026b2131b0a Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Wed, 7 Jan 2026 12:00:45 -0800 Subject: [PATCH] fix honor_small --- rust/pspp/src/spv/read/legacy_xml.rs | 2 +- rust/pspp/src/spv/read/light.rs | 47 +++++++++++++++------ rust/pspp/src/spv/testdata/light4.expected | 44 +++++++++++++++++++ rust/pspp/src/spv/testdata/light4.spv | Bin 0 -> 3419 bytes 4 files changed, 79 insertions(+), 14 deletions(-) create mode 100644 rust/pspp/src/spv/testdata/light4.expected create mode 100644 rust/pspp/src/spv/testdata/light4.spv diff --git a/rust/pspp/src/spv/read/legacy_xml.rs b/rust/pspp/src/spv/read/legacy_xml.rs index 7843d01aa6..47c2ca09de 100644 --- a/rust/pspp/src/spv/read/legacy_xml.rs +++ b/rust/pspp/src/spv/read/legacy_xml.rs @@ -54,7 +54,7 @@ pub fn datum_as_format(datum: &Datum) -> crate::format::Format { Datum::Number(None) => 0, Datum::String(s) => s.parse().unwrap_or_default(), }; - decode_format(f as u32, &mut |_| () /*XXX*/) + decode_format(f as u32, &mut |_| () /*XXX*/).0 } /// Returns this data value interpreted using `format`. diff --git a/rust/pspp/src/spv/read/light.rs b/rust/pspp/src/spv/read/light.rs index a3c685432c..1b1aca730c 100644 --- a/rust/pspp/src/spv/read/light.rs +++ b/rust/pspp/src/spv/read/light.rs @@ -1140,15 +1140,28 @@ struct ValueNumber { #[binread] #[br(little)] -#[derive(Debug)] struct Format(u32); impl Format { - pub fn decode(&self, warn: &mut dyn FnMut(LightWarning)) -> format::Format { + pub fn decode(&self, warn: &mut dyn FnMut(LightWarning)) -> (format::Format, bool) { decode_format(self.0, warn) } } +impl Debug for Format { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut warning = false; + let (format, _honor_small) = self.decode(&mut |_| { + warning = true; + }); + if warning { + write!(f, "InvalidFormat({:#x})", self.0) + } else { + write!(f, "{format}") + } + } +} + #[binread] #[br(little, import(context: &Context))] #[derive(Debug)] @@ -1274,24 +1287,27 @@ impl BinRead for Value { } } -pub(super) fn decode_format(raw: u32, warn: &mut dyn FnMut(LightWarning)) -> format::Format { +pub(super) fn decode_format( + raw: u32, + warn: &mut dyn FnMut(LightWarning), +) -> (format::Format, bool) { if raw == 0 || raw == 0x10000 || raw == 1 { - return F40_2; + return (F40_2, false); } let raw_type = (raw >> 16) as u16; - let type_ = if raw_type >= 40 { - Type::F + let (type_, honor_small) = if raw_type >= 40 { + (Type::F, true) } else if let Ok(type_) = Type::try_from(raw_type) { - type_ + (type_, false) } else { warn(LightWarning::InvalidFormat(raw_type)); - Type::F + (Type::F, false) }; let w = ((raw >> 8) & 0xff) as Width; let d = raw as Decimals; - UncheckedFormat::new(type_, w, d).fix() + (UncheckedFormat::new(type_, w, d).fix(), honor_small) } impl ValueNumber { @@ -1301,8 +1317,10 @@ impl ValueNumber { footnotes: &pivot::Footnotes, warn: &mut dyn FnMut(LightWarning), ) -> value::Value { + let (format, honor_small) = dbg!(self.format.decode(warn)); value::Value::new_number((self.x != -f64::MAX).then_some(self.x)) - .with_format(self.format.decode(warn)) + .with_format(format) + .with_honor_small(honor_small) .with_styling(ValueMods::decode_optional(&self.mods, encoding, footnotes)) } } @@ -1314,8 +1332,10 @@ impl ValueVarNumber { footnotes: &pivot::Footnotes, warn: &mut dyn FnMut(LightWarning), ) -> value::Value { + let (format, honor_small) = self.format.decode(warn); value::Value::new_number((self.x != -f64::MAX).then_some(self.x)) - .with_format(self.format.decode(warn)) + .with_format(format) + .with_honor_small(honor_small) .with_styling(ValueMods::decode_optional(&self.mods, encoding, footnotes)) .with_value_label(self.value_label.decode_optional(encoding)) .with_variable_name(Some(self.var_name.decode(encoding))) @@ -1342,11 +1362,12 @@ impl ValueString { footnotes: &pivot::Footnotes, warn: &mut dyn FnMut(LightWarning), ) -> value::Value { + let (format, honor_small) = self.format.decode(warn); value::Value::new(pivot::value::ValueInner::Datum(DatumValue { datum: Datum::new_utf8(self.s.decode(encoding)), - format: self.format.decode(warn), + format, + honor_small, show: self.show.decode(warn), - honor_small: false, variable: self.var_name.decode_optional(encoding), value_label: self.value_label.decode_optional(encoding), })) diff --git a/rust/pspp/src/spv/testdata/light4.expected b/rust/pspp/src/spv/testdata/light4.expected new file mode 100644 index 0000000000..21ddf26166 --- /dev/null +++ b/rust/pspp/src/spv/testdata/light4.expected @@ -0,0 +1,44 @@ + Correlation Matrix[a] + xxxx1│ xxx2│xxxx3│ x4 │ x5 │ x6 │ x7 │ x8 │ x9 │ x0 +───────────────────────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── +Correlation xxxx1 1.000│2.000│3.000│4.000│5.000│6.000│7.000│8.000│9.000│10.000 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + xxx2 -.962│1.000│ .969│ .252│ .738│ .038│ .242│-.103│-.091│ .194 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + xxxx3 -.984│ .969│1.000│ .291│ .836│-.047│ .324│ .010│-.103│ .190 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x4 -.187│ .252│ .291│1.000│ .545│ .128│ .344│ .575│-.283│ .178 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x5 -.754│ .738│ .836│ .545│1.000│ .043│ .513│ .333│ .018│ .215 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x6 -.001│ .038│-.047│ .128│ .043│1.000│-.412│-.536│ .018│ -.357 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x7 -.245│ .242│ .324│ .344│ .513│-.412│1.000│ .560│ .086│ .862 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x8 .117│-.103│ .010│ .575│ .333│-.536│ .560│1.000│-.227│ .241 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x9 .147│-.091│-.103│-.283│ .018│ .018│ .086│-.227│1.000│ .190 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x0 -.138│ .194│ .190│ .178│ .215│-.357│ .862│ .241│ .190│ 1.000 +───────────────────────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── +Sig. (1-tailed) xxxx1 │ .000│ .000│ .291│ .004│ .499│ .234│ .366│ .333│ .343 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + xxx2 .000│ │ .000│ .227│ .005│ .455│ .237│ .381│ .395│ .284 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + xxxx3 .000│ .000│ │ .193│ .001│ .445│ .166│ .488│ .381│ .288 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x4 .291│ .227│ .193│ │ .041│ .353│ .150│ .032│ .200│ .301 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x5 .004│ .005│ .001│ .041│ │ .450│ .053│ .159│ .479│ .263 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x6 .499│ .455│ .445│ .353│ .450│ │ .104│ .045│ .480│ .141 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x7 .234│ .237│ .166│ .150│ .053│ .104│ │ .037│ .401│ .000 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x8 .366│ .381│ .488│ .032│ .159│ .045│ .037│ │ .251│ .237 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x9 .333│ .395│ .381│ .200│ .479│ .480│ .401│ .251│ │ .288 + ╶───────────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼─────┼────── + x0 .343│ .284│ .288│ .301│ .263│ .141│ .000│ .237│ .288│ +───────────────────────────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴─────┴────── +a. Determinant = 1.479E-009 diff --git a/rust/pspp/src/spv/testdata/light4.spv b/rust/pspp/src/spv/testdata/light4.spv new file mode 100644 index 0000000000000000000000000000000000000000..717602a0a3e77465c38369f9b0038270a3dd0e0d GIT binary patch literal 3419 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