From: Ben Pfaff Date: Sun, 20 Aug 2023 21:22:45 +0000 (-0700) Subject: work X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3aadbf4b5339a293cafa3b0e5f0529d8818ad81d;p=pspp work --- diff --git a/rust/src/cooked.rs b/rust/src/cooked.rs index fc7c44f0cd..16cead934a 100644 --- a/rust/src/cooked.rs +++ b/rust/src/cooked.rs @@ -178,7 +178,7 @@ pub struct Header { } impl Decode for Header { - type Input = crate::raw::Header; + type Input = crate::raw::HeaderRecord; fn decode(decoder: &Decoder, input: &Self::Input, warn: impl Fn(Error)) -> Result { let eye_catcher = decoder.decode_string(&input.eye_catcher.0, &warn); @@ -265,7 +265,7 @@ fn decode_format(raw: raw::Spec, width: VarWidth, warn: impl Fn(Spec, FormatErro impl VariableRecord { pub fn decode( decoder: &mut Decoder, - input: &crate::raw::Variable, + input: &crate::raw::VariableRecord, warn: impl Fn(Error), ) -> Result, Error> { let width = match input.width { @@ -351,7 +351,7 @@ impl VariableRecord { pub struct Document(Vec); impl Decode for Document { - type Input = crate::raw::Document; + type Input = crate::raw::DocumentRecord; fn decode(decoder: &Decoder, input: &Self::Input, warn: impl Fn(Error)) -> Result { Ok(Document( @@ -364,9 +364,6 @@ impl Decode for Document { } } -pub use crate::raw::FloatInfo; -pub use crate::raw::IntegerInfo; - trait TextRecord where Self: Sized, @@ -430,8 +427,8 @@ impl WarnOnError for Result { impl ValueLabelRecord { pub fn decode( decoder: &mut Decoder, - raw_value_label: &crate::raw::ValueLabel, - dict_indexes: &crate::raw::VarIndexes, + raw_value_label: &crate::raw::ValueLabelRecord, + dict_indexes: &crate::raw::VarIndexRecord, warn: impl Fn(Error), ) -> Result, Error> { let variables: Vec<&Variable> = dict_indexes diff --git a/rust/src/raw.rs b/rust/src/raw.rs index 8fa0f26bcf..ead9da8341 100644 --- a/rust/src/raw.rs +++ b/rust/src/raw.rs @@ -97,13 +97,27 @@ pub enum Error { }, #[error("At offset {offset:#x}, {record} has bad size {size} bytes instead of the expected {expected_size}.")] - BadRecordSize { offset: u64, record: String, size: u32, expected_size: u32 }, + BadRecordSize { + offset: u64, + record: String, + size: u32, + expected_size: u32, + }, #[error("At offset {offset:#x}, {record} has bad count {count} instead of the expected {expected_count}.")] - BadRecordCount { offset: u64, record: String, count: u32, expected_count: u32 }, + BadRecordCount { + offset: u64, + record: String, + count: u32, + expected_count: u32, + }, #[error("In long string missing values record starting at offset {record_offset:#x}, value length at offset {offset:#x} is {value_len} instead of the expected 8.")] - BadLongMissingValueLength { record_offset: u64, offset: u64, value_len: u32 }, + BadLongMissingValueLength { + record_offset: u64, + offset: u64, + value_len: u32, + }, #[error("The encoding record at offset {offset:#x} contains an encoding name that is not valid UTF-8.")] BadEncodingName { offset: u64 }, @@ -114,13 +128,13 @@ pub enum Error { #[derive(Clone, Debug)] pub enum Record { - Header(Header), - Variable(Variable), - ValueLabel(ValueLabel), - VarIndexes(VarIndexes), - Document(Document), - IntegerInfo(IntegerInfo), - FloatInfo(FloatInfo), + Header(HeaderRecord), + Variable(VariableRecord), + ValueLabel(ValueLabelRecord), + VarIndexes(VarIndexRecord), + Document(DocumentRecord), + IntegerInfo(IntegerInfoRecord), + FloatInfo(FloatInfoRecord), VariableSets(UnencodedString), VarDisplay(VarDisplayRecord), MultipleResponse(MultipleResponseRecord), @@ -132,7 +146,6 @@ pub enum Record { LongStrings(UnencodedString), FileAttributes(UnencodedString), VariableAttributes(UnencodedString), - TextExtension(TextExtension), OtherExtension(Extension), EndOfHeaders(u32), ZHeader(ZHeader), @@ -144,10 +157,10 @@ impl Record { fn read(reader: &mut R, endian: Endian) -> Result { let rec_type: u32 = endian.parse(read_bytes(reader)?); match rec_type { - 2 => Ok(Record::Variable(Variable::read(reader, endian)?)), - 3 => Ok(Record::ValueLabel(ValueLabel::read(reader, endian)?)), - 4 => Ok(Record::VarIndexes(VarIndexes::read(reader, endian)?)), - 6 => Ok(Record::Document(Document::read(reader, endian)?)), + 2 => Ok(Record::Variable(VariableRecord::read(reader, endian)?)), + 3 => Ok(Record::ValueLabel(ValueLabelRecord::read(reader, endian)?)), + 4 => Ok(Record::VarIndexes(VarIndexRecord::read(reader, endian)?)), + 6 => Ok(Record::Document(DocumentRecord::read(reader, endian)?)), 7 => Ok(Extension::read(reader, endian)?), 999 => Ok(Record::EndOfHeaders(endian.parse(read_bytes(reader)?))), _ => Err(Error::BadRecordType { @@ -165,7 +178,7 @@ fn default_decode<'a>(s: &'a [u8]) -> Cow<'a, str> { } #[derive(Clone)] -pub struct Header { +pub struct HeaderRecord { /// Magic number. pub magic: Magic, @@ -206,13 +219,13 @@ pub struct Header { pub endian: Endian, } -impl Header { +impl HeaderRecord { fn debug_field(&self, f: &mut Formatter, name: &str, value: T) -> FmtResult { writeln!(f, "{name:>17}: {:?}", value) } } -impl Debug for Header { +impl Debug for HeaderRecord { fn fmt(&self, f: &mut Formatter) -> FmtResult { writeln!(f, "File header record:")?; self.debug_field(f, "Magic", self.magic)?; @@ -230,8 +243,8 @@ impl Debug for Header { } } -impl Header { - fn read(r: &mut R) -> Result { +impl HeaderRecord { + fn read(r: &mut R) -> Result { let magic: [u8; 4] = read_bytes(r)?; let magic: Magic = magic.try_into().map_err(|_| Error::NotASystemFile)?; @@ -268,7 +281,7 @@ impl Header { let file_label = UnencodedStr::<64>(read_bytes(r)?); let _: [u8; 3] = read_bytes(r)?; - Ok(Header { + Ok(HeaderRecord { magic, layout_code, nominal_case_size, @@ -341,8 +354,8 @@ impl VarType { mod state { use super::{ - Compression, Error, Header, Record, Value, VarType, Variable, ZHeader, ZTrailer, - ZlibDecodeMultiple, + Compression, Error, HeaderRecord, Record, Value, VarType, VariableRecord, ZHeader, + ZTrailer, ZlibDecodeMultiple, }; use crate::endian::Endian; use std::{ @@ -373,7 +386,7 @@ mod state { impl State for Start { fn read(mut self: Box) -> Result)>, Error> { - let header = Header::read(&mut self.reader)?; + let header = HeaderRecord::read(&mut self.reader)?; let next_state = Headers(CommonState { reader: self.reader, endian: header.endian, @@ -391,7 +404,7 @@ mod state { fn read(mut self: Box) -> Result)>, Error> { let record = Record::read(&mut self.0.reader, self.0.endian)?; match record { - Record::Variable(Variable { width, .. }) => { + Record::Variable(VariableRecord { width, .. }) => { self.0.var_types.push(VarType::from_width(width)); } Record::EndOfHeaders(_) => { @@ -500,7 +513,11 @@ impl Debug for Value { impl Value { fn read(r: &mut R, var_type: VarType, endian: Endian) -> Result { - Ok(Self::from_raw(UntypedValue(read_bytes(r)?), var_type, endian)) + Ok(Self::from_raw( + UntypedValue(read_bytes(r)?), + var_type, + endian, + )) } pub fn from_raw(raw: UntypedValue, var_type: VarType, endian: Endian) -> Value { @@ -583,7 +600,9 @@ impl Value { }); } } - 253 => break Value::from_raw(UntypedValue(read_bytes(reader)?), var_type, endian), + 253 => { + break Value::from_raw(UntypedValue(read_bytes(reader)?), var_type, endian) + } 254 => match var_type { VarType::String => break Value::String(UnencodedStr(*b" ")), // XXX EBCDIC VarType::Numeric => { @@ -744,8 +763,9 @@ fn format_name(type_: u32) -> Cow<'static, str> { 39 => "SDATE", 40 => "MTIME", 41 => "YMDHMS", - _ => return format!("").into() - }.into() + _ => return format!("").into(), + } + .into() } #[derive(Clone)] @@ -819,7 +839,7 @@ impl MissingValues { } #[derive(Clone)] -pub struct Variable { +pub struct VariableRecord { /// Offset from the start of the file to the start of the record. pub offset: u64, @@ -842,7 +862,7 @@ pub struct Variable { pub label: Option, } -impl Debug for Variable { +impl Debug for VariableRecord { fn fmt(&self, f: &mut Formatter) -> FmtResult { writeln!( f, @@ -864,8 +884,8 @@ impl Debug for Variable { } } -impl Variable { - fn read(r: &mut R, endian: Endian) -> Result { +impl VariableRecord { + fn read(r: &mut R, endian: Endian) -> Result { let offset = r.stream_position()?; let width: i32 = endian.parse(read_bytes(r)?); let has_variable_label: u32 = endian.parse(read_bytes(r)?); @@ -896,7 +916,7 @@ impl Variable { let missing_values = MissingValues::read(r, offset, width, missing_value_code, endian)?; - Ok(Variable { + Ok(VariableRecord { offset, width, name, @@ -971,7 +991,7 @@ impl Debug for UnencodedStr { } #[derive(Clone)] -pub struct ValueLabel { +pub struct ValueLabelRecord { /// Offset from the start of the file to the start of the record. pub offset: u64, @@ -979,7 +999,7 @@ pub struct ValueLabel { pub labels: Vec<(UntypedValue, UnencodedString)>, } -impl Debug for ValueLabel { +impl Debug for ValueLabelRecord { fn fmt(&self, f: &mut Formatter) -> FmtResult { for (value, label) in self.labels.iter() { writeln!(f, "{value:?}: {label:?}")?; @@ -988,18 +1008,18 @@ impl Debug for ValueLabel { } } -impl ValueLabel { +impl ValueLabelRecord { /// Maximum number of value labels in a record. pub const MAX: u32 = u32::MAX / 8; - fn read(r: &mut R, endian: Endian) -> Result { + fn read(r: &mut R, endian: Endian) -> Result { let offset = r.stream_position()?; let n: u32 = endian.parse(read_bytes(r)?); - if n > ValueLabel::MAX { + if n > ValueLabelRecord::MAX { return Err(Error::BadNumberOfValueLabels { offset, n, - max: ValueLabel::MAX, + max: ValueLabelRecord::MAX, }); } @@ -1014,12 +1034,12 @@ impl ValueLabel { label.truncate(label_len); labels.push((value, UnencodedString(label))); } - Ok(ValueLabel { offset, labels }) + Ok(ValueLabelRecord { offset, labels }) } } #[derive(Clone)] -pub struct VarIndexes { +pub struct VarIndexRecord { /// Offset from the start of the file to the start of the record. pub offset: u64, @@ -1027,7 +1047,7 @@ pub struct VarIndexes { pub dict_indexes: Vec, } -impl Debug for VarIndexes { +impl Debug for VarIndexRecord { fn fmt(&self, f: &mut Formatter) -> FmtResult { write!(f, "apply to variables")?; for dict_index in self.dict_indexes.iter() { @@ -1037,18 +1057,18 @@ impl Debug for VarIndexes { } } -impl VarIndexes { +impl VarIndexRecord { /// Maximum number of variable indexes in a record. pub const MAX: u32 = u32::MAX / 8; - fn read(r: &mut R, endian: Endian) -> Result { + fn read(r: &mut R, endian: Endian) -> Result { let offset = r.stream_position()?; let n: u32 = endian.parse(read_bytes(r)?); - if n > VarIndexes::MAX { + if n > VarIndexRecord::MAX { return Err(Error::BadNumberOfVarIndexes { offset, n, - max: VarIndexes::MAX, + max: VarIndexRecord::MAX, }); } let mut dict_indexes = Vec::with_capacity(n as usize); @@ -1056,7 +1076,7 @@ impl VarIndexes { dict_indexes.push(endian.parse(read_bytes(r)?)); } - Ok(VarIndexes { + Ok(VarIndexRecord { offset, dict_indexes, }) @@ -1064,17 +1084,17 @@ impl VarIndexes { } #[derive(Clone, Debug)] -pub struct Document { +pub struct DocumentRecord { /// Offset from the start of the file to the start of the record. pub pos: u64, /// The document, as an array of 80-byte lines. - pub lines: Vec + pub lines: Vec, } -pub type DocumentLine = UnencodedStr<{Document::LINE_LEN}>; +pub type DocumentLine = UnencodedStr<{ DocumentRecord::LINE_LEN }>; -impl Document { +impl DocumentRecord { /// Length of a line in a document. Document lines are fixed-length and /// padded on the right with spaces. pub const LINE_LEN: usize = 80; @@ -1083,7 +1103,7 @@ impl Document { /// the maximum number that will fit in a 32-bit space. pub const MAX_LINES: usize = i32::MAX as usize / Self::LINE_LEN; - fn read(r: &mut R, endian: Endian) -> Result { + fn read(r: &mut R, endian: Endian) -> Result { let offset = r.stream_position()?; let n: u32 = endian.parse(read_bytes(r)?); let n = n as usize; @@ -1097,9 +1117,9 @@ impl Document { let pos = r.stream_position()?; let mut lines = Vec::with_capacity(n); for _ in 0..n { - lines.push(UnencodedStr::<{Document::LINE_LEN}>(read_bytes(r)?)); + lines.push(UnencodedStr::<{ DocumentRecord::LINE_LEN }>(read_bytes(r)?)); } - Ok(Document { pos, lines }) + Ok(DocumentRecord { pos, lines }) } } } @@ -1116,7 +1136,7 @@ where } #[derive(Clone, Debug)] -pub struct IntegerInfo { +pub struct IntegerInfoRecord { pub version: (i32, i32, i32), pub machine_code: i32, pub floating_point_rep: i32, @@ -1125,7 +1145,7 @@ pub struct IntegerInfo { pub character_code: i32, } -impl ExtensionRecord for IntegerInfo { +impl ExtensionRecord for IntegerInfoRecord { const SUBTYPE: u32 = 3; const SIZE: Option = Some(4); const COUNT: Option = Some(8); @@ -1138,7 +1158,7 @@ impl ExtensionRecord for IntegerInfo { let data: Vec = (0..8) .map(|_| endian.parse(read_bytes(&mut input).unwrap())) .collect(); - Ok(IntegerInfo { + Ok(IntegerInfoRecord { version: (data[0], data[1], data[2]), machine_code: data[3], floating_point_rep: data[4], @@ -1150,13 +1170,13 @@ impl ExtensionRecord for IntegerInfo { } #[derive(Clone, Debug)] -pub struct FloatInfo { +pub struct FloatInfoRecord { pub sysmis: f64, pub highest: f64, pub lowest: f64, } -impl ExtensionRecord for FloatInfo { +impl ExtensionRecord for FloatInfoRecord { const SUBTYPE: u32 = 4; const SIZE: Option = Some(8); const COUNT: Option = Some(3); @@ -1169,7 +1189,7 @@ impl ExtensionRecord for FloatInfo { let data: Vec = (0..3) .map(|_| endian.parse(read_bytes(&mut input).unwrap())) .collect(); - Ok(FloatInfo { + Ok(FloatInfoRecord { sysmis: data[0], highest: data[1], lowest: data[2], @@ -1409,7 +1429,6 @@ impl ExtensionRecord for EncodingRecord { } } - #[derive(Clone, Debug)] pub struct NumberOfCasesRecord { /// Always observed as 1. @@ -1436,22 +1455,6 @@ impl ExtensionRecord for NumberOfCasesRecord { } } -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum TextExtensionSubtype { - VariableSets = 5, - ProductInfo = 10, - LongNames = 13, - LongStrings = 14, - FileAttributes = 17, - VariableAttributes = 18, -} - -#[derive(Clone, Debug)] -pub struct TextExtension { - pub subtype: TextExtensionSubtype, - pub string: UnencodedString, -} - #[derive(Clone, Debug)] pub struct Extension { /// Offset from the start of the file to the start of the record. @@ -1518,12 +1521,12 @@ impl Extension { data, }; match subtype { - IntegerInfo::SUBTYPE => Ok(Record::IntegerInfo(IntegerInfo::parse( + IntegerInfoRecord::SUBTYPE => Ok(Record::IntegerInfo(IntegerInfoRecord::parse( &extension, endian, |_| (), )?)), - FloatInfo::SUBTYPE => Ok(Record::FloatInfo(FloatInfo::parse( + FloatInfoRecord::SUBTYPE => Ok(Record::FloatInfo(FloatInfoRecord::parse( &extension, endian, |_| (), @@ -1549,24 +1552,12 @@ impl Extension { endian, |_| (), )?)), - x if x == TextExtensionSubtype::VariableSets as u32 => { - Ok(Record::VariableSets(UnencodedString(extension.data))) - } - x if x == TextExtensionSubtype::ProductInfo as u32 => { - Ok(Record::ProductInfo(UnencodedString(extension.data))) - } - x if x == TextExtensionSubtype::LongNames as u32 => { - Ok(Record::LongNames(UnencodedString(extension.data))) - } - x if x == TextExtensionSubtype::LongStrings as u32 => { - Ok(Record::LongStrings(UnencodedString(extension.data))) - } - x if x == TextExtensionSubtype::FileAttributes as u32 => { - Ok(Record::FileAttributes(UnencodedString(extension.data))) - } - x if x == TextExtensionSubtype::VariableAttributes as u32 => { - Ok(Record::VariableAttributes(UnencodedString(extension.data))) - } + 5 => Ok(Record::VariableSets(UnencodedString(extension.data))), + 10 => Ok(Record::ProductInfo(UnencodedString(extension.data))), + 13 => Ok(Record::LongNames(UnencodedString(extension.data))), + 14 => Ok(Record::LongStrings(UnencodedString(extension.data))), + 17 => Ok(Record::FileAttributes(UnencodedString(extension.data))), + 18 => Ok(Record::VariableAttributes(UnencodedString(extension.data))), _ => Ok(Record::OtherExtension(extension)), } } @@ -1760,4 +1751,3 @@ impl ExtensionRecord for LongStringValueLabelRecord { Ok(LongStringValueLabelRecord(label_set)) } } -