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;
#[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),
VarIndexes(VarIndexes),
Extension(Extension),
EndOfHeaders,
+ Case(Vec<Value>),
}
pub struct Header {
}
}
-enum VarType {
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub enum VarType {
Number,
String,
}
End,
}
+#[derive(Copy, Clone)]
+pub enum Value {
+ Number(Option<f64>),
+ 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<R: Read + Seek> Reader<R> {
pub fn new(r: R) -> Result<Reader<R>, Error> {
Ok(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),
}
}