work
authorBen Pfaff <blp@cs.stanford.edu>
Sun, 24 Dec 2023 18:19:09 +0000 (10:19 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Sun, 24 Dec 2023 18:19:09 +0000 (10:19 -0800)
rust/src/cooked.rs
rust/src/raw.rs

index e17e9f3e7a87271bffcf5bc6b97d1b0956570bdf..c6eabecdbf17bf6942f67874b8f5ef99fb637103 100644 (file)
@@ -8,7 +8,7 @@ use crate::{
     endian::Endian,
     format::{Error as FormatError, Spec, UncheckedSpec},
     identifier::{Error as IdError, Identifier},
-    raw::{self, RawStr, RawString, VarType, RawDocumentLine, VarDisplayRecord},
+    raw::{self, RawDocumentLine, RawStr, RawString, VarDisplayRecord, VarType},
 };
 use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
 use encoding_rs::{DecoderResult, Encoding};
@@ -214,7 +214,7 @@ struct Headers<'a> {
     float_info: Option<&'a raw::FloatInfoRecord>,
     variable_sets: Vec<&'a raw::TextRecord>,
     var_display: Option<&'a raw::VarDisplayRecord>,
-    multiple_response: Vec<&'a raw::MultipleResponseRecord>,
+    multiple_response: Vec<&'a raw::MultipleResponseRecord<RawString>>,
     long_string_value_labels: Vec<&'a raw::LongStringValueLabelRecord>,
     long_string_missing_values: Vec<&'a raw::LongStringMissingValueRecord>,
     encoding: Option<&'a raw::EncodingRecord>,
@@ -370,11 +370,13 @@ pub fn decode(
     }
 
     // Decode records that use short names.
-    for &raw in &h.multiple_response {
-        if let Some(mrr) = MultipleResponseRecord::try_decode(&mut decoder, raw, warn)? {
-            output.push(Record::MultipleResponse(mrr))
+    /*
+        for &raw in &h.multiple_response {
+            if let Some(mrr) = MultipleResponseRecord::try_decode(&mut decoder, raw, warn)? {
+                output.push(Record::MultipleResponse(mrr))
+            }
         }
-    }
+    */
     for &raw in &h.very_long_strings {
         let s = decoder.decode_string_cow(&raw.text.0, warn);
         output.push(Record::VeryLongStrings(VeryLongStringRecord::parse(
@@ -499,10 +501,10 @@ impl Decoder {
 }
 
 pub trait TryDecode: Sized {
-    type Input;
+    type Input<'a>;
     fn try_decode(
         decoder: &mut Decoder,
-        input: &Self::Input,
+        input: &Self::Input<'_>,
         warn: impl Fn(Error),
     ) -> Result<Option<Self>, Error>;
 }
@@ -532,11 +534,11 @@ fn trim_end_spaces(mut s: String) -> String {
 }
 
 impl TryDecode for HeaderRecord {
-    type Input = crate::raw::HeaderRecord<RawString>;
+    type Input<'a> = crate::raw::HeaderRecord<RawString>;
 
     fn try_decode(
         decoder: &mut Decoder,
-        input: &Self::Input,
+        input: &Self::Input<'_>,
         warn: impl Fn(Error),
     ) -> Result<Option<Self>, Error> {
         let eye_catcher = trim_end_spaces(decoder.decode_string(&input.eye_catcher.0, &warn));
@@ -682,11 +684,11 @@ fn decode_format(raw: raw::Spec, width: VarWidth, warn: impl Fn(Spec, FormatErro
 }
 
 impl TryDecode for VariableRecord {
-    type Input = raw::VariableRecord<RawString, RawStr<8>>;
+    type Input<'a> = raw::VariableRecord<RawString, RawStr<8>>;
 
     fn try_decode(
         decoder: &mut Decoder,
-        input: &Self::Input,
+        input: &Self::Input<'_>,
         warn: impl Fn(Error),
     ) -> Result<Option<VariableRecord>, Error> {
         let width = match input.width {
@@ -772,11 +774,11 @@ impl TryDecode for VariableRecord {
 pub struct DocumentRecord(Vec<String>);
 
 impl TryDecode for DocumentRecord {
-    type Input = crate::raw::DocumentRecord<RawDocumentLine>;
+    type Input<'a> = crate::raw::DocumentRecord<RawDocumentLine>;
 
     fn try_decode(
         decoder: &mut Decoder,
-        input: &Self::Input,
+        input: &Self::Input<'_>,
         warn: impl Fn(Error),
     ) -> Result<Option<Self>, Error> {
         Ok(Some(DocumentRecord(
@@ -858,10 +860,10 @@ pub struct ValueLabelRecord {
 }
 
 impl TryDecode for ValueLabelRecord {
-    type Input = crate::raw::ValueLabelRecord<RawStr<8>, RawString>;
+    type Input<'a> = crate::raw::ValueLabelRecord<RawStr<8>, RawString>;
     fn try_decode(
         decoder: &mut Decoder,
-        input: &Self::Input,
+        input: &Self::Input<'_>,
         warn: impl Fn(Error),
     ) -> Result<Option<ValueLabelRecord>, Error> {
         let variables: Vec<&Variable> = input
@@ -906,10 +908,7 @@ impl TryDecode for ValueLabelRecord {
             .iter()
             .map(|raw::ValueLabel { value, label }| {
                 let label = decoder.decode_string(&label.0, &warn);
-                let value = Value::decode(
-                    value,
-                    decoder,
-                );
+                let value = Value::decode(value, decoder);
                 ValueLabel { value, label }
             })
             .collect();
@@ -1229,18 +1228,15 @@ pub struct MultipleResponseSet {
 impl MultipleResponseSet {
     fn decode(
         decoder: &Decoder,
-        input: &raw::MultipleResponseSet,
+        input: &raw::MultipleResponseSet<Cow<str>>,
         warn: &impl Fn(Error),
     ) -> Result<Self, Error> {
-        let mr_set_name = decoder
-            .decode_identifier(&input.name.0, warn)
-            .map_err(Error::InvalidMrSetName)?;
-
-        let label = decoder.decode_string(&input.label.0, warn);
+        let mr_set_name =
+            Identifier::new(&input.name, decoder.encoding).map_err(Error::InvalidMrSetName)?;
 
         let mut dict_indexes = Vec::with_capacity(input.short_names.len());
         for short_name in input.short_names.iter() {
-            let short_name = match decoder.decode_identifier(&short_name.0, warn) {
+            let short_name = match Identifier::new(&short_name, decoder.encoding) {
                 Ok(name) => name,
                 Err(error) => {
                     warn(Error::InvalidMrSetName(error));
@@ -1279,7 +1275,7 @@ impl MultipleResponseSet {
             name: mr_set_name,
             min_width,
             max_width,
-            label,
+            label: input.label.to_string(),
             mr_type,
             dict_indexes,
         })
@@ -1290,11 +1286,11 @@ impl MultipleResponseSet {
 pub struct MultipleResponseRecord(pub Vec<MultipleResponseSet>);
 
 impl TryDecode for MultipleResponseRecord {
-    type Input = raw::MultipleResponseRecord;
+    type Input<'a> = raw::MultipleResponseRecord<Cow<'a, str>>;
 
     fn try_decode(
         decoder: &mut Decoder,
-        input: &Self::Input,
+        input: &Self::Input<'_>,
         warn: impl Fn(Error),
     ) -> Result<Option<Self>, Error> {
         let mut sets = Vec::with_capacity(input.0.len());
@@ -1340,11 +1336,11 @@ impl LongStringMissingValues {
 pub struct LongStringMissingValuesRecord(Vec<LongStringMissingValues>);
 
 impl TryDecode for LongStringMissingValuesRecord {
-    type Input = raw::LongStringMissingValueRecord;
+    type Input<'a> = raw::LongStringMissingValueRecord;
 
     fn try_decode(
         decoder: &mut Decoder,
-        input: &Self::Input,
+        input: &Self::Input<'_>,
         warn: impl Fn(Error),
     ) -> Result<Option<Self>, Error> {
         let mut labels = Vec::with_capacity(input.0.len());
@@ -1406,11 +1402,11 @@ impl LongStringValueLabels {
 pub struct LongStringValueLabelRecord(pub Vec<LongStringValueLabels>);
 
 impl TryDecode for LongStringValueLabelRecord {
-    type Input = raw::LongStringValueLabelRecord;
+    type Input<'a> = raw::LongStringValueLabelRecord;
 
     fn try_decode(
         decoder: &mut Decoder,
-        input: &Self::Input,
+        input: &Self::Input<'_>,
         warn: impl Fn(Error),
     ) -> Result<Option<Self>, Error> {
         let mut labels = Vec::with_capacity(input.0.len());
index 18e71d3623f5e4d98de552cc8653100f5b631f23..85312ef4c9e1f2260817fdef5ec1e06e0a8d7f22 100644 (file)
@@ -172,7 +172,7 @@ pub enum Record {
     FloatInfo(FloatInfoRecord),
     VariableSets(TextRecord),
     VarDisplay(VarDisplayRecord),
-    MultipleResponse(MultipleResponseRecord),
+    MultipleResponse(MultipleResponseRecord<RawString>),
     LongStringValueLabels(LongStringValueLabelRecord),
     LongStringMissingValues(LongStringMissingValueRecord),
     Encoding(EncodingRecord),
@@ -1610,15 +1610,18 @@ impl MultipleResponseType {
 }
 
 #[derive(Clone, Debug)]
-pub struct MultipleResponseSet {
-    pub name: RawString,
-    pub label: RawString,
+pub struct MultipleResponseSet<S>
+where
+    S: Debug,
+{
+    pub name: S,
+    pub label: S,
     pub mr_type: MultipleResponseType,
-    pub short_names: Vec<RawString>,
+    pub short_names: Vec<S>,
 }
 
-impl MultipleResponseSet {
-    fn parse(input: &[u8]) -> Result<(MultipleResponseSet, &[u8]), Error> {
+impl MultipleResponseSet<RawString> {
+    fn parse(input: &[u8]) -> Result<(Self, &[u8]), Error> {
         let Some(equals) = input.iter().position(|&b| b == b'=') else {
             return Err(Error::TBD);
         };
@@ -1657,12 +1660,23 @@ impl MultipleResponseSet {
             input,
         ))
     }
+
+    fn decode<'a>(&'a self, decoder: &Decoder) -> MultipleResponseSet<Cow<'a, str>> {
+        MultipleResponseSet {
+            name: decoder.decode(&self.name),
+            label: decoder.decode(&self.label),
+            mr_type: self.mr_type.clone(),
+            short_names: self.short_names.iter().map(|s| decoder.decode(s)).collect(),
+        }
+    }
 }
 
 #[derive(Clone, Debug)]
-pub struct MultipleResponseRecord(pub Vec<MultipleResponseSet>);
+pub struct MultipleResponseRecord<S>(pub Vec<MultipleResponseSet<S>>)
+where
+    S: Debug;
 
-impl ExtensionRecord for MultipleResponseRecord {
+impl ExtensionRecord for MultipleResponseRecord<RawString> {
     const SUBTYPE: u32 = 7;
     const SIZE: Option<u32> = Some(1);
     const COUNT: Option<u32> = None;
@@ -1682,6 +1696,12 @@ impl ExtensionRecord for MultipleResponseRecord {
     }
 }
 
+impl MultipleResponseRecord<RawString> {
+    fn decode<'a>(&'a self, decoder: &Decoder) -> MultipleResponseRecord<Cow<'a, str>> {
+        MultipleResponseRecord(self.0.iter().map(|set| set.decode(decoder)).collect())
+    }
+}
+
 fn parse_counted_string(input: &[u8]) -> Result<(RawString, &[u8]), Error> {
     let Some(space) = input.iter().position(|&b| b == b' ') else {
         return Err(Error::TBD);