From 3ea1bbce472b0870d17159a364f582d95368b864 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Sun, 6 Aug 2023 10:12:52 -0700 Subject: [PATCH] work --- rust/src/raw.rs | 147 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 134 insertions(+), 13 deletions(-) diff --git a/rust/src/raw.rs b/rust/src/raw.rs index fccc33b41b..f0e8c540c2 100644 --- a/rust/src/raw.rs +++ b/rust/src/raw.rs @@ -779,12 +779,12 @@ where } pub struct IntegerInfo { - version: (i32, i32, i32), - machine_code: i32, - floating_point_rep: i32, - compression_code: i32, - endianness: i32, - character_code: i32, + pub version: (i32, i32, i32), + pub machine_code: i32, + pub floating_point_rep: i32, + pub compression_code: i32, + pub endianness: i32, + pub character_code: i32, } impl ExtensionRecord for IntegerInfo { @@ -811,9 +811,9 @@ impl ExtensionRecord for IntegerInfo { } pub struct FloatInfo { - sysmis: f64, - highest: f64, - lowest: f64, + pub sysmis: f64, + pub highest: f64, + pub lowest: f64, } impl ExtensionRecord for FloatInfo { @@ -1055,8 +1055,8 @@ impl TextRecord for LongVariableNameRecord { } pub struct VeryLongString { - short_name: String, - length: usize, + pub short_name: String, + pub length: usize, } impl VeryLongString { @@ -1203,12 +1203,133 @@ impl ExtensionRecord for Encoding { } } +pub struct Attribute { + pub name: String, + pub values: Vec, +} + +impl Attribute { + fn parse<'a>(input: &'a str, warn: &impl Fn(Error)) -> Result<(Attribute, &'a str), Error> { + let Some((name, mut input)) = input.split_once('(') else { + return Err(Error::TBD); + }; + let mut values = Vec::new(); + loop { + let Some((value, rest)) = input.split_once('\n') else { + return Err(Error::TBD); + }; + if let Some(stripped) = value + .strip_prefix('\'') + .and_then(|value| value.strip_suffix('\'')) + { + values.push(stripped.into()); + } else { + warn(Error::TBD); + values.push(value.into()); + } + if let Some(rest) = rest.strip_prefix(')') { + return Ok(( + Attribute { + name: name.into(), + values, + }, + rest, + )); + } + input = rest; + } + } +} + +pub struct AttributeSet(pub Vec); + +impl AttributeSet { + fn parse<'a>( + mut input: &'a str, + sentinel: Option, + warn: &impl Fn(Error), + ) -> Result<(AttributeSet, &'a str), Error> { + let mut attributes = Vec::new(); + let rest = loop { + match input.chars().next() { + None => break input, + c if c == sentinel => break &input[1..], + _ => { + let (attribute, rest) = Attribute::parse(input, &warn)?; + attributes.push(attribute); + input = rest; + } + } + }; + Ok((AttributeSet(attributes), rest)) + } +} + +pub struct FileAttributeRecord(AttributeSet); + +impl TextRecord for FileAttributeRecord { + const NAME: &'static str = "data file attributes"; + fn parse(input: &str, warn: impl Fn(Error)) -> Result { + let (set, rest) = AttributeSet::parse(input, None, &warn)?; + if !rest.is_empty() { + warn(Error::TBD); + } + Ok(FileAttributeRecord(set)) + } +} + +pub struct VarAttributeSet { + pub long_var_name: String, + pub attributes: AttributeSet, +} + +impl VarAttributeSet { + fn parse<'a>( + input: &'a str, + warn: &impl Fn(Error), + ) -> Result<(VarAttributeSet, &'a str), Error> { + let Some((long_var_name, rest)) = input.split_once(':') else { + return Err(Error::TBD); + }; + let (attributes, rest) = AttributeSet::parse(rest, Some('/'), warn)?; + Ok(( + VarAttributeSet { + long_var_name: long_var_name.into(), + attributes, + }, + rest, + )) + } +} + +pub struct VariableAttributeRecord(Vec); + +impl TextRecord for VariableAttributeRecord { + const NAME: &'static str = "variable attributes"; + fn parse(mut input: &str, warn: impl Fn(Error)) -> Result { + let mut var_attribute_sets = Vec::new(); + while !input.is_empty() { + match VarAttributeSet::parse(input, &warn) { + Ok((var_attribute, rest)) => { + var_attribute_sets.push(var_attribute); + input = rest; + } + Err(error) => { + warn(error); + break; + } + } + } + Ok(VariableAttributeRecord(var_attribute_sets)) + } +} + pub struct NumberOfCasesRecord { /// Always observed as 1. - one: u64, + pub one: u64, /// Number of cases. - n_cases: u64, + pub n_cases: u64, } impl ExtensionRecord for NumberOfCasesRecord { -- 2.30.2