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};
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>,
}
// 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(
}
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>;
}
}
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));
}
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 {
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(
}
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
.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();
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));
name: mr_set_name,
min_width,
max_width,
- label,
+ label: input.label.to_string(),
mr_type,
dict_indexes,
})
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());
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());
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());
FloatInfo(FloatInfoRecord),
VariableSets(TextRecord),
VarDisplay(VarDisplayRecord),
- MultipleResponse(MultipleResponseRecord),
+ MultipleResponse(MultipleResponseRecord<RawString>),
LongStringValueLabels(LongStringValueLabelRecord),
LongStringMissingValues(LongStringMissingValueRecord),
Encoding(EncodingRecord),
}
#[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);
};
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;
}
}
+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);