From 20aa2ce6ec383c360658a4a4a46f6d51af5dc096 Mon Sep 17 00:00:00 2001 From: Ben Pfaff Date: Tue, 25 Jul 2023 23:07:57 -0700 Subject: [PATCH] work --- rust/src/lib.rs | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) diff --git a/rust/src/lib.rs b/rust/src/lib.rs index 8e8ee6cab4..0b8c541e54 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -2,7 +2,7 @@ use endian::{Endian, Parse}; use num::Integer; use num_derive::FromPrimitive; -use std::io::{BufReader, Error as IoError, Read, Seek}; +use std::io::{BufReader, Error as IoError, ErrorKind, Read, Seek}; use thiserror::Error; pub mod endian; @@ -15,11 +15,11 @@ pub enum Error { #[error("Invalid magic number {0:?}")] BadMagic([u8; 4]), - #[error("I/O error ({source})")] - Io { + #[error("I/O error ({0})")] + Io( #[from] - source: IoError, - }, + IoError, + ), #[error("Invalid SAV compression code {0}")] InvalidSavCompression(u32), @@ -100,6 +100,7 @@ pub enum Record { VarIndexes(VarIndexes), Extension(Extension), EndOfHeaders, + Case(Vec), } pub struct Header { @@ -170,7 +171,8 @@ impl TryFrom<[u8; 4]> for Magic { } } -enum VarType { +#[derive(Copy, Clone, PartialEq, Eq, Hash)] +pub enum VarType { Number, String, } @@ -197,6 +199,24 @@ enum ReaderState { End, } +#[derive(Copy, Clone)] +pub enum Value { + Number(Option), + String([u8; 8]), +} + +impl Value { + pub fn from_raw(var_type: VarType, raw: [u8; 8], endian: Endian) -> Value { + match var_type { + VarType::String => Value::String(raw), + VarType::Number => { + let number: f64 = endian.parse(raw); + Value::Number((number != -f64::MAX).then_some(number)) + } + } + } +} + impl Reader { pub fn new(r: R) -> Result, Error> { Ok(Reader { @@ -241,6 +261,23 @@ impl Reader { }; Ok(Some((record, ReaderState::Headers(endian, compression)))) } + ReaderState::Data(endian) => { + let mut values = Vec::with_capacity(self.var_types.len()); + for (i, &var_type) in self.var_types.iter().enumerate() { + let raw = match read_bytes(&mut self.r) { + Ok(raw) => raw, + Err(err) => { + if i == 0 && err.kind() == ErrorKind::UnexpectedEof { + return Ok(None); + } else { + return Err(Error::Io(err)); + } + } + }; + values.push(Value::from_raw(var_type, raw, endian)); + } + Ok(Some((Record::Case(values), ReaderState::Data(endian)))) + } ReaderState::End => Ok(None), } } -- 2.30.2