Works for at least one test file now
[pspp] / rust / src / raw.rs
index a8c7c858e9e0a766243226066023acd6bc1aead4..ac8b3a057027cc6649a39c99d294014102da7cec 100644 (file)
@@ -55,6 +55,9 @@ pub enum Error {
     #[error("At offset {offset:#x}, number of value labels ({n}) is greater than the maximum number {max}.")]
     BadNumberOfValueLabels { offset: u64, n: u32, max: u32 },
 
+    #[error("At offset {offset:#x}, following value label record, found record type {rec_type} instead of expected type 4 for variable index record")]
+    ExpectedVarIndexRecord { offset: u64, rec_type: u32 },
+
     #[error("At offset {offset:#x}, number of variables indexes ({n}) is greater than the maximum number ({max}).")]
     BadNumberOfVarIndexes { offset: u64, n: u32, max: u32 },
 
@@ -130,7 +133,6 @@ pub enum Record {
     Header(HeaderRecord),
     Variable(VariableRecord),
     ValueLabel(ValueLabelRecord),
-    VarIndexes(VarIndexRecord),
     Document(DocumentRecord),
     IntegerInfo(IntegerInfoRecord),
     FloatInfo(FloatInfoRecord),
@@ -158,7 +160,6 @@ impl Record {
         match rec_type {
             2 => Ok(Record::Variable(VariableRecord::read(reader, endian)?)),
             3 => Ok(Record::ValueLabel(ValueLabelRecord::read(reader, endian)?)),
-            4 => Ok(Record::VarIndexes(VarIndexRecord::read(reader, endian)?)),
             6 => Ok(Record::Document(DocumentRecord::read(reader, endian)?)),
             7 => Ok(Extension::read(reader, endian)?),
             999 => Ok(Record::EndOfHeaders(endian.parse(read_bytes(reader)?))),
@@ -997,34 +998,50 @@ impl<const N: usize> Debug for UnencodedStr<N> {
 
 #[derive(Clone)]
 pub struct ValueLabelRecord {
-    /// Offset from the start of the file to the start of the record.
-    pub offset: u64,
+    /// Offset from the start of the file to the start of the value label
+    /// record.
+    pub label_offset: u64,
 
     /// The labels.
     pub labels: Vec<(UntypedValue, UnencodedString)>,
+
+    /// Offset from the start of the file to the start of the variable index
+    /// record.
+    pub index_offset: u64,
+
+    /// The 1-based indexes of the variable indexes.
+    pub dict_indexes: Vec<u32>,
 }
 
 impl Debug for ValueLabelRecord {
     fn fmt(&self, f: &mut Formatter) -> FmtResult {
+        writeln!(f, "labels: ")?;
         for (value, label) in self.labels.iter() {
             writeln!(f, "{value:?}: {label:?}")?;
         }
+        write!(f, "apply to variables")?;
+        for dict_index in self.dict_indexes.iter() {
+            write!(f, " #{dict_index}")?;
+        }
         Ok(())
     }
 }
 
 impl ValueLabelRecord {
     /// Maximum number of value labels in a record.
-    pub const MAX: u32 = u32::MAX / 8;
+    pub const MAX_LABELS: u32 = u32::MAX / 8;
+
+    /// Maximum number of variable indexes in a record.
+    pub const MAX_INDEXES: u32 = u32::MAX / 8;
 
     fn read<R: Read + Seek>(r: &mut R, endian: Endian) -> Result<ValueLabelRecord, Error> {
-        let offset = r.stream_position()?;
+        let label_offset = r.stream_position()?;
         let n: u32 = endian.parse(read_bytes(r)?);
-        if n > ValueLabelRecord::MAX {
+        if n > Self::MAX_LABELS {
             return Err(Error::BadNumberOfValueLabels {
-                offset,
+                offset: label_offset,
                 n,
-                max: ValueLabelRecord::MAX,
+                max: Self::MAX_LABELS,
             });
         }
 
@@ -1039,41 +1056,22 @@ impl ValueLabelRecord {
             label.truncate(label_len);
             labels.push((value, UnencodedString(label)));
         }
-        Ok(ValueLabelRecord { offset, labels })
-    }
-}
 
-#[derive(Clone)]
-pub struct VarIndexRecord {
-    /// Offset from the start of the file to the start of the record.
-    pub offset: u64,
-
-    /// The 1-based indexes of the variable indexes.
-    pub dict_indexes: Vec<u32>,
-}
-
-impl Debug for VarIndexRecord {
-    fn fmt(&self, f: &mut Formatter) -> FmtResult {
-        write!(f, "apply to variables")?;
-        for dict_index in self.dict_indexes.iter() {
-            write!(f, " #{dict_index}")?;
+        let index_offset = r.stream_position()?;
+        let rec_type: u32 = endian.parse(read_bytes(r)?);
+        if rec_type != 4 {
+            return Err(Error::ExpectedVarIndexRecord {
+                offset: index_offset,
+                rec_type,
+            });
         }
-        Ok(())
-    }
-}
 
-impl VarIndexRecord {
-    /// Maximum number of variable indexes in a record.
-    pub const MAX: u32 = u32::MAX / 8;
-
-    fn read<R: Read + Seek>(r: &mut R, endian: Endian) -> Result<VarIndexRecord, Error> {
-        let offset = r.stream_position()?;
         let n: u32 = endian.parse(read_bytes(r)?);
-        if n > VarIndexRecord::MAX {
+        if n > Self::MAX_INDEXES {
             return Err(Error::BadNumberOfVarIndexes {
-                offset,
+                offset: index_offset,
                 n,
-                max: VarIndexRecord::MAX,
+                max: Self::MAX_INDEXES,
             });
         }
         let mut dict_indexes = Vec::with_capacity(n as usize);
@@ -1081,8 +1079,10 @@ impl VarIndexRecord {
             dict_indexes.push(endian.parse(read_bytes(r)?));
         }
 
-        Ok(VarIndexRecord {
-            offset,
+        Ok(ValueLabelRecord {
+            label_offset,
+            labels,
+            index_offset,
             dict_indexes,
         })
     }