Drop use of Cow
authorBen Pfaff <blp@cs.stanford.edu>
Wed, 31 Jan 2024 06:18:12 +0000 (22:18 -0800)
committerBen Pfaff <blp@cs.stanford.edu>
Wed, 31 Jan 2024 06:18:12 +0000 (22:18 -0800)
rust/src/cooked.rs
rust/src/raw.rs

index 1cb878f120d6768cff919e86c60c368a9c8347a5..78eaf138c2951fc831d72d5da98cbd8005542c73 100644 (file)
@@ -4,14 +4,14 @@ use std::{
 };
 
 use crate::{
-    dictionary::{self, Dictionary},
+    dictionary::{self, Dictionary, VarWidth},
     encoding::{default_encoding, get_encoding, Error as EncodingError},
     endian::Endian,
     format::{Error as FormatError, Spec, UncheckedSpec},
     identifier::{Error as IdError, Identifier},
     raw::{
         self, LongStringMissingValueRecord, MissingValues, ProductInfoRecord, RawDocumentLine,
-        RawStr, RawString, VarDisplayRecord, VarType,
+        RawStr, RawString, VarDisplayRecord, VarType, DecodedRecord,
     },
 };
 use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
@@ -285,24 +285,20 @@ impl<'a> Headers<'a> {
 
 
 pub fn decode(
-    headers: Vec<raw::Record>,
-    encoding: &'static Encoding,
-    warn: &impl Fn(Error),
+    headers: Vec<DecodedRecord>,
+    decoder: raw::Decoder,
 ) -> Result<(Vec<Record>, Metadata), Error> {
+    let dictionary = Dictionary::new(decoder.encoding);
     let mut decoder = Decoder {
-        raw: raw::Decoder {
-            encoding,
-            warn: Box::new(|error| println!("{error}")),
-        },
-        encoding,
+        raw: decoder,
         variables: HashMap::new(),
         var_names: HashMap::new(),
-        dictionary: Dictionary::new(encoding),
+        dictionary,
         n_dict_indexes: 0,
         n_generated_names: 0,
     };
 
-    let h = Headers::new(&headers, &decoder, warn);
+    let h = Headers::new(&headers, &decoder);
     let Some(header) = h.header else {
         return Err(Error::MissingHeaderRecord);
     };
index 1a760a0517dc26168b6084be90266fb7227f8007..0250520afc3b3ffdfee4fc5da9951d3f538952bb 100644 (file)
@@ -235,16 +235,16 @@ pub enum Record {
 }
 
 #[derive(Clone, Debug)]
-pub enum DecodedRecord<'a> {
-    Header(HeaderRecord<Cow<'a, str>>),
-    Variable(VariableRecord<Cow<'a, str>, String>),
-    ValueLabel(ValueLabelRecord<RawStr<8>, Cow<'a, str>>),
-    Document(DocumentRecord<Cow<'a, str>>),
+pub enum DecodedRecord {
+    Header(HeaderRecord<String>),
+    Variable(VariableRecord<String, String>),
+    ValueLabel(ValueLabelRecord<RawStr<8>, String>),
+    Document(DocumentRecord<String>),
     IntegerInfo(IntegerInfoRecord),
     FloatInfo(FloatInfoRecord),
     VarDisplay(VarDisplayRecord),
-    MultipleResponse(MultipleResponseRecord<Identifier, Cow<'a, str>>),
-    LongStringValueLabels(LongStringValueLabelRecord<Identifier, Cow<'a, str>>),
+    MultipleResponse(MultipleResponseRecord<Identifier, String>),
+    LongStringValueLabels(LongStringValueLabelRecord<Identifier, String>),
     LongStringMissingValues(LongStringMissingValueRecord<Identifier, String>),
     Encoding(EncodingRecord),
     NumberOfCases(NumberOfCasesRecord),
@@ -258,6 +258,7 @@ pub enum DecodedRecord<'a> {
     EndOfHeaders(u32),
     ZHeader(ZHeader),
     ZTrailer(ZTrailer),
+    Cases(Rc<RefCell<Cases>>),
 }
 
 impl Record {
@@ -286,7 +287,7 @@ impl Record {
         }
     }
 
-    pub fn decode<'a>(&'a self, decoder: &Decoder) -> Result<DecodedRecord<'a>, Error> {
+    pub fn decode(&self, decoder: &Decoder) -> Result<DecodedRecord, Error> {
         Ok(match self {
             Record::Header(record) => record.decode(decoder),
             Record::Variable(record) => record.decode(decoder),
@@ -309,7 +310,7 @@ impl Record {
             Record::EndOfHeaders(record) => DecodedRecord::EndOfHeaders(*record),
             Record::ZHeader(record) => DecodedRecord::ZHeader(record.clone()),
             Record::ZTrailer(record) => DecodedRecord::ZTrailer(record.clone()),
-            Record::Cases(_) => todo!(),
+            Record::Cases(record) => DecodedRecord::Cases(record.clone()),
         })
     }
 }
@@ -494,11 +495,11 @@ impl HeaderRecord<RawString> {
         })
     }
 
-    pub fn decode<'a>(&'a self, decoder: &Decoder) -> DecodedRecord<'a> {
-        let eye_catcher = decoder.decode(&self.eye_catcher);
-        let file_label = decoder.decode(&self.file_label);
-        let creation_date = decoder.decode(&self.creation_date);
-        let creation_time = decoder.decode(&self.creation_time);
+    pub fn decode(&self, decoder: &Decoder) -> DecodedRecord {
+        let eye_catcher = decoder.decode(&self.eye_catcher).to_string();
+        let file_label = decoder.decode(&self.file_label).to_string();
+        let creation_date = decoder.decode(&self.creation_date).to_string();
+        let creation_time = decoder.decode(&self.creation_time).to_string();
         DecodedRecord::Header(HeaderRecord {
             eye_catcher,
             weight_index: self.weight_index,
@@ -1345,11 +1346,14 @@ impl VariableRecord<RawString, RawStr<8>> {
         DecodedRecord::Variable(VariableRecord {
             offsets: self.offsets.clone(),
             width: self.width,
-            name: decoder.decode(&self.name),
+            name: decoder.decode(&self.name).to_string(),
             print_format: self.print_format,
             write_format: self.write_format,
             missing_values: self.missing_values.decode(decoder),
-            label: self.label.as_ref().map(|label| decoder.decode(label)),
+            label: self
+                .label
+                .as_ref()
+                .map(|label| decoder.decode(label).to_string()),
         })
     }
 }
@@ -1592,13 +1596,13 @@ impl ValueLabelRecord<RawStr<8>, RawString> {
         })))
     }
 
-    fn decode<'a>(&'a self, decoder: &Decoder) -> ValueLabelRecord<RawStr<8>, Cow<'a, str>> {
+    fn decode(&self, decoder: &Decoder) -> ValueLabelRecord<RawStr<8>, String> {
         let labels = self
             .labels
             .iter()
             .map(|ValueLabel { value, label }| ValueLabel {
                 value: *value,
-                label: decoder.decode(label),
+                label: decoder.decode(label).to_string(),
             })
             .collect();
         ValueLabelRecord {
@@ -1661,7 +1665,7 @@ impl DocumentRecord<RawDocumentLine> {
             lines: self
                 .lines
                 .iter()
-                .map(|s| decoder.decode_slice(&s.0))
+                .map(|s| decoder.decode_slice(&s.0).to_string())
                 .collect(),
         })
     }
@@ -1850,10 +1854,10 @@ impl MultipleResponseSet<RawString, RawString> {
         ))
     }
 
-    fn decode<'a>(
-        &'a self,
+    fn decode(
+        &self,
         decoder: &Decoder,
-    ) -> Result<MultipleResponseSet<Identifier, Cow<'a, str>>, Warning> {
+    ) -> Result<MultipleResponseSet<Identifier, String>, Warning> {
         let mut short_names = Vec::with_capacity(self.short_names.len());
         for short_name in self.short_names.iter() {
             if let Some(short_name) = decoder
@@ -1868,7 +1872,7 @@ impl MultipleResponseSet<RawString, RawString> {
             name: decoder
                 .decode_identifier(&self.name)
                 .map_err(Warning::InvalidMrSetVariableName)?,
-            label: decoder.decode(&self.label),
+            label: decoder.decode(&self.label).to_string(),
             mr_type: self.mr_type.clone(),
             short_names,
         })
@@ -2796,18 +2800,18 @@ where
 }
 
 impl LongStringValueLabels<RawString, RawString> {
-    fn decode<'a>(
-        &'a self,
+    fn decode(
+        &self,
         decoder: &Decoder,
-    ) -> Result<LongStringValueLabels<Identifier, Cow<'a, str>>, Warning> {
+    ) -> Result<LongStringValueLabels<Identifier, String>, Warning> {
         let var_name = decoder.decode(&self.var_name);
         let var_name = Identifier::new(var_name.trim_end(), decoder.encoding)
             .map_err(Warning::InvalidLongStringValueLabelName)?;
 
         let mut labels = Vec::with_capacity(self.labels.len());
         for (value, label) in self.labels.iter() {
-            let value = decoder.decode_exact_length(&value.0);
-            let label = decoder.decode(label);
+            let value = decoder.decode_exact_length(&value.0).to_string();
+            let label = decoder.decode(label).to_string();
             labels.push((value, label));
         }
 
@@ -2859,10 +2863,7 @@ impl ExtensionRecord for LongStringValueLabelRecord<RawString, RawString> {
 }
 
 impl LongStringValueLabelRecord<RawString, RawString> {
-    fn decode<'a>(
-        &'a self,
-        decoder: &Decoder,
-    ) -> LongStringValueLabelRecord<Identifier, Cow<'a, str>> {
+    fn decode(&self, decoder: &Decoder) -> LongStringValueLabelRecord<Identifier, String> {
         let mut labels = Vec::with_capacity(self.0.len());
         for label in &self.0 {
             match label.decode(decoder) {