work on reading binary legacy member
authorBen Pfaff <blp@cs.stanford.edu>
Sat, 18 Oct 2025 15:17:23 +0000 (08:17 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Sat, 18 Oct 2025 15:17:23 +0000 (08:17 -0700)
rust/pspp/src/output/spv.rs
rust/pspp/src/output/spv/legacy_bin.rs [new file with mode: 0644]

index 1e9d6d377c97cac9ac6b55e19d06228a4d539c20..cff19a88a293289c96b6c358bc254000c33982a5 100644 (file)
@@ -40,6 +40,7 @@ use crate::output::{
 mod css;
 pub mod html;
 mod legacy_xml;
+mod legacy_bin;
 mod light;
 
 #[derive(Debug, Display, thiserror::Error)]
diff --git a/rust/pspp/src/output/spv/legacy_bin.rs b/rust/pspp/src/output/spv/legacy_bin.rs
new file mode 100644 (file)
index 0000000..bcaabdd
--- /dev/null
@@ -0,0 +1,76 @@
+use std::io::{Read, Seek, SeekFrom};
+
+use binrw::{BinRead, binread};
+
+#[binread]
+#[br(little)]
+#[derive(Debug)]
+pub struct LegacyBin {
+    #[br(magic(0u8))]
+    version: Version,
+    #[br(temp)]
+    n_sources: u16,
+    member_size: u32,
+    #[br(count(n_sources), args { inner: (version,) })]
+    metadata: Vec<Metadata>,
+    #[br(count(n_sources), args { inner: metadata.as_slice() })]
+    data: Vec<Data>,
+}
+
+#[binread]
+#[br(little)]
+#[derive(Copy, Clone, Debug, PartialEq, Eq)]
+enum Version {
+    #[br(magic = 0xafu8)]
+    Vaf,
+    #[br(magic = 0xb0u8)]
+    Vb0,
+}
+
+#[binread]
+#[br(little, import(version: Version))]
+#[derive(Debug)]
+struct Metadata {
+    n_values: u32,
+    n_variables: u32,
+    data_offset: u32,
+    #[br(count(if version == Version::Vaf { 28 } else { 64 }))]
+    source_name: Vec<u8>,
+    #[br(if(version == Version::Vb0), temp)]
+    _x: u32,
+}
+
+#[derive(Debug)]
+struct Data {
+    variables: Vec<Variable>,
+}
+
+impl BinRead for Data {
+    type Args<'a> = &'a [Metadata];
+
+    fn read_options<R: Read + Seek>(
+        reader: &mut R,
+        endian: binrw::Endian,
+        metadata: Self::Args<'_>,
+    ) -> binrw::BinResult<Self> {
+        let mut variables = Vec::with_capacity(metadata.len());
+        for metadata in metadata {
+            reader.seek(SeekFrom::Start(metadata.data_offset as u64))?;
+            variables.push(Variable::read_options(
+                reader,
+                endian,
+                (metadata.n_values,),
+            )?);
+        }
+        Ok(Self { variables })
+    }
+}
+
+#[binread]
+#[br(little, import(n_values: u32))]
+#[derive(Debug)]
+struct Variable {
+    variable_name: [u8; 288],
+    #[br(count(n_values))]
+    values: Vec<f64>,
+}