From b8e97841b0dae3835a761d616af6096c9b18ea26 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 8 Jun 2025 12:48:37 -0700 Subject: [PATCH] variable display --- rust/pspp/src/sys/raw.rs | 24 +++++---- rust/pspp/src/sys/test.rs | 5 ++ .../variable_display_without_width.expected | 0 .../variable_display_without_width.sack | 53 +++++++++++++++++++ 4 files changed, 73 insertions(+), 9 deletions(-) create mode 100644 rust/pspp/src/sys/testdata/variable_display_without_width.expected create mode 100644 rust/pspp/src/sys/testdata/variable_display_without_width.sack diff --git a/rust/pspp/src/sys/raw.rs b/rust/pspp/src/sys/raw.rs index eb3e0f4a0d..34693eb0f4 100644 --- a/rust/pspp/src/sys/raw.rs +++ b/rust/pspp/src/sys/raw.rs @@ -334,7 +334,7 @@ impl Record { 2 => Ok(Some(VariableRecord::read(reader, endian, warn)?)), 3 => Ok(ValueLabelRecord::read(reader, endian, var_types, warn)?), 6 => Ok(Some(DocumentRecord::read(reader, endian)?)), - 7 => Extension::read(reader, endian, var_types.n_values(), warn), + 7 => Extension::read(reader, endian, var_types, warn), 999 => Ok(Some(Record::EndOfHeaders( endian.parse(read_bytes(reader)?), ))), @@ -2281,10 +2281,9 @@ pub enum Alignment { impl Alignment { fn try_decode(source: u32) -> Result, Warning> { match source { - 0 => Ok(None), - 1 => Ok(Some(Alignment::Left)), - 2 => Ok(Some(Alignment::Right)), - 3 => Ok(Some(Alignment::Center)), + 0 => Ok(Some(Alignment::Left)), + 1 => Ok(Some(Alignment::Right)), + 2 => Ok(Some(Alignment::Center)), _ => Err(Warning::InvalidAlignment(source)), } } @@ -2320,7 +2319,7 @@ impl VarDisplayRecord { fn parse( ext: &Extension, - n_vars: usize, + var_types: &VarTypes, endian: Endian, warn: &dyn Fn(Warning), ) -> Result { @@ -2333,6 +2332,7 @@ impl VarDisplayRecord { }); } + let n_vars = var_types.n_vars(); let has_width = if ext.count as usize == 3 * n_vars { true } else if ext.count as usize == 2 * n_vars { @@ -2341,7 +2341,7 @@ impl VarDisplayRecord { return Err(Warning::InvalidVariableDisplayCount { count: ext.count as usize, first: 2 * n_vars, - second: 2 * n_vars, + second: 3 * n_vars, }); }; @@ -2885,7 +2885,7 @@ impl Extension { fn read( r: &mut R, endian: Endian, - n_vars: usize, + var_types: &VarTypes, warn: &dyn Fn(Warning), ) -> Result, Error> { let subtype = endian.parse(read_bytes(r)?); @@ -2913,7 +2913,9 @@ impl Extension { let result = match subtype { IntegerInfoRecord::SUBTYPE => IntegerInfoRecord::parse(&extension, endian), FloatInfoRecord::SUBTYPE => FloatInfoRecord::parse(&extension, endian), - VarDisplayRecord::SUBTYPE => VarDisplayRecord::parse(&extension, n_vars, endian, warn), + VarDisplayRecord::SUBTYPE => { + VarDisplayRecord::parse(&extension, var_types, endian, warn) + } MultipleResponseRecord::SUBTYPE | 19 => { MultipleResponseRecord::parse(&extension, endian) } @@ -3231,4 +3233,8 @@ impl VarTypes { .iter() .map(|var_type| var_type.unwrap_or(VarType::String)) } + + pub fn n_vars(&self) -> usize { + self.types.iter().flatten().count() + } } diff --git a/rust/pspp/src/sys/test.rs b/rust/pspp/src/sys/test.rs index db94531a2f..3265db5c48 100644 --- a/rust/pspp/src/sys/test.rs +++ b/rust/pspp/src/sys/test.rs @@ -62,6 +62,11 @@ fn extra_product_info() { test_sysfile("extra_product_info"); } +#[test] +fn variable_display_without_width() { + test_sysfile("variable_display_without_width"); +} + fn test_sysfile(name: &str) { let input_filename = Path::new(env!("CARGO_MANIFEST_DIR")) .join("src/sys/testdata") diff --git a/rust/pspp/src/sys/testdata/variable_display_without_width.expected b/rust/pspp/src/sys/testdata/variable_display_without_width.expected new file mode 100644 index 0000000000..e69de29bb2 diff --git a/rust/pspp/src/sys/testdata/variable_display_without_width.sack b/rust/pspp/src/sys/testdata/variable_display_without_width.sack new file mode 100644 index 0000000000..0137bd0d53 --- /dev/null +++ b/rust/pspp/src/sys/testdata/variable_display_without_width.sack @@ -0,0 +1,53 @@ +# File header. +"$FL2"; s60 "$(#) SPSS DATA FILE PSPP synthetic test file"; +2; # Layout code +19; # Nominal case size +0; # Not compressed +0; # Not weighted +0; # No cases. +100.0; # Bias. +"01 Jan 11"; "20:53:52"; s64 "PSPP synthetic test file"; +i8 0 *3; + +# Numeric variables. +2; 0; 0; 0; 0x050800 *2; s8 "A"; +2; 0; 0; 0; 0x050800 *2; s8 "B"; +2; 0; 0; 0; 0x050800 *2; s8 "C"; +2; 0; 0; 0; 0x050800 *2; s8 "D"; + +# Short string variables. +2; 3; 0; 0; 0x010300 *2; s8 "H"; +2; 3; 0; 0; 0x010300 *2; s8 "I"; +2; 3; 0; 0; 0x010300 *2; s8 "J"; +2; 3; 0; 0; 0x010300 *2; s8 "K"; + +# Long string variables. +2; 9; 0; 0; 0x010900 *2; s8 "L"; +2; -1; 0; 0; 0; 0; s8 ""; +2; 10; 0; 0; 0x010a00 *2; s8 "M"; +2; -1; 0; 0; 0; 0; s8 ""; +2; 17; 0; 0; 0x011100 *2; s8 "N"; +( 2; -1; 0; 0; 0; 0; s8 "" ) * 2; +2; 25; 0; 0; 0x011900 *2; s8 "O"; +( 2; -1; 0; 0; 0; 0; s8 "" ) * 3; + +# Variable display parameters +7; 11; 4; 24; +1; 0; +2; 0; +3; 0; +1; 1; +2; 1; +3; 1; +1; 2; +2; 2; +3; 2; +0; 0; +0; 1; +0; 2; + +# Character encoding record. +7; 20; 1; 12; "windows-1252"; + +# Dictionary termination record. +999; 0; -- 2.30.2