use crate::{
+ cooked::VarWidth,
endian::{Endian, Parse, ToBytes},
identifier::{Error as IdError, Identifier},
};
#[error("Invalid multiple response set variable name. {0}")]
InvalidMrSetVariableName(IdError),
+ #[error("Invalid variable name in long string missing values record. {0}")]
+ InvalidLongStringMissingValueVariableName(IdError),
+
#[error("Details TBD")]
TBD,
}
})
}
- fn decode<'a>(&'a self, decoder: &Decoder) -> HeaderRecord<Cow<'a, str>> {
+ pub fn decode<'a>(&'a self, decoder: &Decoder) -> HeaderRecord<Cow<'a, str>> {
let eye_catcher = decoder.decode(&self.eye_catcher);
let file_label = decoder.decode(&self.file_label);
let creation_date = decoder.decode(&self.creation_date);
}
}
-struct Decoder {
- encoding: &'static Encoding,
- warn: Box<dyn Fn(Error)>,
+pub struct Decoder {
+ pub encoding: &'static Encoding,
+ pub warn: Box<dyn Fn(Error)>,
}
impl Decoder {
}
impl VarType {
- fn from_width(width: i32) -> VarType {
+ pub fn from_width(width: VarWidth) -> VarType {
match width {
- 0 => VarType::Numeric,
- _ => VarType::String,
+ VarWidth::Numeric => Self::Numeric,
+ VarWidth::String(_) => Self::String,
}
}
- fn opposite(self) -> VarType {
+ pub fn opposite(self) -> VarType {
match self {
Self::Numeric => Self::String,
Self::String => Self::Numeric,
};
match record {
Record::Variable(VariableRecord { width, .. }) => {
- self.var_types.push(VarType::from_width(width));
+ self.var_types.push(if width == 0 {
+ VarType::Numeric
+ } else {
+ VarType::String
+ });
}
Record::EndOfHeaders(_) => {
self.state = if let Some(Compression::ZLib) = self.header.compression {
}
#[derive(Clone)]
-pub struct MissingValues<S>
+pub struct MissingValues<S = String>
where
S: Debug,
{
}
}
+impl<S> Default for MissingValues<S>
+where
+ S: Debug,
+{
+ fn default() -> Self {
+ Self {
+ values: Vec::new(),
+ range: None,
+ }
+ }
+}
+
impl MissingValues<RawStr<8>> {
fn read<R: Read + Seek>(
r: &mut R,
(_, _) => return Err(Error::BadStringMissingValueCode { offset, code }),
};
- let var_type = VarType::from_width(width);
+ let var_type = if width == 0 {
+ VarType::Numeric
+ } else {
+ VarType::String
+ };
let mut values = Vec::new();
for _ in 0..n_values {
}))
}
- fn decode<'a>(&'a self, decoder: &Decoder) -> VariableRecord<Cow<'a, str>, String> {
+ pub fn decode<'a>(&'a self, decoder: &Decoder) -> VariableRecord<Cow<'a, str>, String> {
VariableRecord {
offsets: self.offsets.clone(),
width: self.width,
}
}
- fn decode<'a>(&'a self, decoder: &Decoder) -> DocumentRecord<Cow<'a, str>> {
+ pub fn decode<'a>(&'a self, decoder: &Decoder) -> DocumentRecord<Cow<'a, str>> {
DocumentRecord {
offsets: self.offsets.clone(),
lines: self
}
impl Measure {
+ pub fn default_for_type(var_type: VarType) -> Option<Measure> {
+ match var_type {
+ VarType::Numeric => None,
+ VarType::String => Some(Self::Nominal),
+ }
+ }
+
fn try_decode(source: u32) -> Result<Option<Measure>, Error> {
match source {
0 => Ok(None),
_ => Err(Error::InvalidAlignment(source)),
}
}
+
+ pub fn default_for_type(var_type: VarType) -> Self {
+ match var_type {
+ VarType::Numeric => Self::Right,
+ VarType::String => Self::Left,
+ }
+ }
}
#[derive(Clone, Debug)]
}
impl LongStringMissingValues<RawString, RawStr<8>> {
- fn decode<'a>(&self, decoder: &Decoder) -> LongStringMissingValues<String, String> {
- LongStringMissingValues {
- var_name: decoder.decode(&self.var_name).to_string(),
+ fn decode<'a>(
+ &self,
+ decoder: &Decoder,
+ ) -> Result<LongStringMissingValues<Identifier, String>, IdError> {
+ Ok(LongStringMissingValues {
+ var_name: decoder.decode_identifier(&self.var_name)?,
missing_values: self.missing_values.decode(decoder),
- }
+ })
}
}
}
impl LongStringMissingValueRecord<RawString, RawStr<8>> {
- fn decode<'a>(&self, decoder: &Decoder) -> LongStringMissingValueRecord<String, String> {
- LongStringMissingValueRecord(self.0.iter().map(|mv| mv.decode(decoder)).collect())
+ pub fn decode<'a>(
+ &self,
+ decoder: &Decoder,
+ ) -> LongStringMissingValueRecord<Identifier, String> {
+ let mut mvs = Vec::with_capacity(self.0.len());
+ for mv in self.0.iter() {
+ if let Some(mv) = mv
+ .decode(decoder)
+ .map_err(|err| Error::InvalidLongStringMissingValueVariableName(err))
+ .warn_on_error(&decoder.warn)
+ {
+ mvs.push(mv);
+ }
+ }
+ LongStringMissingValueRecord(mvs)
}
}