work
[pspp] / rust / src / cooked.rs
index 58e9c270512f108a0178ec5c12f11b05163f7f58..9f6f0101b0ce51535221779b362008edcd311a94 100644 (file)
@@ -129,6 +129,9 @@ pub enum Error {
     #[error("Invalid variable name in long string value label record.  {0}")]
     InvalidLongStringValueLabelName(IdError),
 
+    #[error("Invalid variable name in attribute record.  {0}")]
+    InvalidAttributeVariableName(IdError),
+
     #[error("Details TBD")]
     TBD,
 }
@@ -151,8 +154,8 @@ pub enum Record {
     LongNames(LongNameRecord),
     VeryLongStrings(VeryLongStringRecord),
     FileAttributes(FileAttributeRecord),
-    //VariableAttributes(UnencodedString),
-    //OtherExtension(Extension),
+    VariableAttributes(VariableAttributeRecord),
+    OtherExtension(Extension),
     //EndOfHeaders(u32),
     //ZHeader(ZHeader),
     //ZTrailer(ZTrailer),
@@ -160,6 +163,7 @@ pub enum Record {
 }
 
 pub use crate::raw::EncodingRecord;
+pub use crate::raw::Extension;
 pub use crate::raw::FloatInfoRecord;
 pub use crate::raw::IntegerInfoRecord;
 pub use crate::raw::NumberOfCasesRecord;
@@ -183,6 +187,26 @@ pub struct Decoder {
     n_generated_names: usize,
 }
 
+pub fn decode<T>(headers: Vec<raw::Record>) -> Vec<Record> {
+    let encoding = headers.iter().find_map(|rec| {
+        if let raw::Record::Encoding(ref e) = rec {
+            Some(e.0.as_str())
+        } else {
+            None
+        }
+    });
+    let character_code = headers.iter().find_map(|rec| {
+        if let raw::Record::IntegerInfo(ref r) = rec {
+            Some(r.character_code)
+        } else {
+            None
+        }
+    });
+    
+
+    Vec::new()
+}
+
 impl Decoder {
     fn generate_name(&mut self) -> Identifier {
         loop {
@@ -842,8 +866,9 @@ impl FileAttributeRecord {
     }
 }
 
+#[derive(Clone, Debug)]
 pub struct VarAttributeSet {
-    pub long_var_name: String,
+    pub long_var_name: Identifier,
     pub attributes: AttributeSet,
 }
 
@@ -852,21 +877,23 @@ impl VarAttributeSet {
         decoder: &Decoder,
         input: &'a str,
         warn: &impl Fn(Error),
-    ) -> Result<(VarAttributeSet, &'a str), Error> {
+    ) -> Result<(Option<VarAttributeSet>, &'a str), Error> {
         let Some((long_var_name, rest)) = input.split_once(':') else {
             return Err(Error::TBD);
         };
         let (attributes, rest) = AttributeSet::parse(decoder, rest, Some('/'), warn)?;
-        Ok((
-            VarAttributeSet {
-                long_var_name: long_var_name.into(),
+        let var_attribute = Identifier::new(long_var_name, decoder.encoding)
+            .map_err(|e| Error::InvalidAttributeVariableName(e))
+            .warn_on_error(warn)
+            .map(|name| VarAttributeSet {
+                long_var_name: name,
                 attributes,
-            },
-            rest,
-        ))
+            });
+        Ok((var_attribute, rest))
     }
 }
 
+#[derive(Clone, Debug)]
 pub struct VariableAttributeRecord(Vec<VarAttributeSet>);
 
 impl VariableAttributeRecord {
@@ -878,7 +905,9 @@ impl VariableAttributeRecord {
             else {
                 break;
             };
-            var_attribute_sets.push(var_attribute);
+            if let Some(var_attribute) = var_attribute {
+                var_attribute_sets.push(var_attribute);
+            }
             input = rest;
         }
         Ok(VariableAttributeRecord(var_attribute_sets))