test writing attributes
authorBen Pfaff <blp@cs.stanford.edu>
Mon, 4 Aug 2025 20:10:31 +0000 (13:10 -0700)
committerBen Pfaff <blp@cs.stanford.edu>
Mon, 4 Aug 2025 20:10:31 +0000 (13:10 -0700)
rust/pspp/src/dictionary.rs
rust/pspp/src/sys/write.rs

index 5a1d8fa772b662f6c2291d56fd9e79202239563c..6f30e299725864d96637a984fee4def9422c54c5 100644 (file)
@@ -1268,6 +1268,11 @@ impl Attributes {
         self.0.insert(name, values);
     }
 
+    pub fn with(mut self, name: Identifier, values: Vec<String>) -> Self {
+        self.insert(name, values);
+        self
+    }
+
     pub fn append(&mut self, other: &mut Self) {
         self.0.append(&mut other.0)
     }
index 2297a828eb693ceecd29524fcb37ba46789703a1..02e3ff5e2ef2e4f1e64e4eb63a41591a0e7255d5 100644 (file)
@@ -671,7 +671,7 @@ where
     }
 
     fn write_data_file_attributes(&mut self) -> Result<(), BinError> {
-        if self.options.sysfile_version != SysfileVersion::V2 {
+        if self.options.sysfile_version != SysfileVersion::V3 {
             return Ok(());
         }
         let mut s = String::new();
@@ -680,7 +680,7 @@ where
     }
 
     fn write_variable_attributes(&mut self) -> Result<(), BinError> {
-        if self.options.sysfile_version != SysfileVersion::V2 {
+        if self.options.sysfile_version != SysfileVersion::V3 {
             return Ok(());
         }
         let mut s = String::new();
@@ -694,6 +694,7 @@ where
             if index > 0 {
                 s.push('/');
             }
+            write!(&mut s, "{}:", &variable.name).unwrap();
             put_attributes(&attributes, &mut s);
         }
         self.write_string_record(18, &s)
@@ -1213,8 +1214,9 @@ mod tests {
     use crate::{
         data::{ByteString, Datum, RawString},
         dictionary::{
-            Alignment, CategoryLabels, DictIndexMultipleResponseSet, DictIndexVariableSet,
-            Dictionary, Measure, MissingValueRange, MultipleResponseType, VarWidth, Variable,
+            Alignment, Attributes, CategoryLabels, DictIndexMultipleResponseSet,
+            DictIndexVariableSet, Dictionary, Measure, MissingValueRange, MultipleResponseType,
+            VarWidth, Variable,
         },
         identifier::{ByIdentifier, Identifier},
         sys::{
@@ -1877,4 +1879,55 @@ $e=E 11 6 choice 0  n o p
         }
         assert!(names(&expected).eq(names(&actual)));
     }
+
+    /// This tests the example from the documentation for the system file
+    /// format.
+    #[test]
+    fn attributes() {
+        let mut dictionary = Dictionary::new(UTF_8);
+        let attributes = Attributes::new()
+            .with(
+                Identifier::new("fred").unwrap(),
+                vec![String::from("23"), String::from("34")],
+            )
+            .with(Identifier::new("bert").unwrap(), vec![String::from("123")]);
+        dictionary.attributes = attributes.clone();
+        let mut variable =
+            Variable::new(Identifier::new("dummy").unwrap(), VarWidth::Numeric, UTF_8);
+        variable.attributes = attributes;
+        dictionary.add_var(variable).unwrap();
+
+        fn get_attributes(dictionary: &Dictionary, vars: bool) -> String {
+            let mut raw = Vec::new();
+            let options = WriteOptions::reproducible(None);
+            let mut cursor = Cursor::new(&mut raw);
+            let mut writer = DictionaryWriter::new(&options, &mut cursor, dictionary);
+            if vars {
+                writer.write_variable_attributes().unwrap();
+            } else {
+                writer.write_data_file_attributes().unwrap();
+            }
+            if raw.is_empty() {
+                String::new()
+            } else {
+                str::from_utf8(&raw[16..]).unwrap().into()
+            }
+        }
+
+        assert_eq!(
+            &get_attributes(&dictionary, false),
+            "bert('123'
+)fred('23'
+'34'
+)"
+        );
+        assert_eq!(
+            &get_attributes(&dictionary, true),
+            "dummy:$@Role('0'
+)bert('123'
+)fred('23'
+'34'
+)"
+        );
+    }
 }