-mod state {
- use super::{
- Compression, Error, HeaderRecord, Record, Value, VarType, VariableRecord, ZHeader,
- ZTrailer, ZlibDecodeMultiple,
- };
- use crate::endian::Endian;
- use std::{
- collections::VecDeque,
- io::{Read, Seek},
- };
-
- pub trait State {
- #[allow(clippy::type_complexity)]
- fn read(self: Box<Self>) -> Result<Option<(Record, Box<dyn State>)>, Error>;
- }
-
- struct Start<R: Read + Seek> {
- reader: R,
- warn: Box<dyn Fn(Error)>
- }
-
- pub fn new<R: Read + Seek + 'static, F: Fn(Error) + 'static >(reader: R, warn: F) -> Box<dyn State> {
- Box::new(Start { reader, warn: Box::new(warn) })
- }
-
- struct CommonState<R: Read + Seek> {
- reader: R,
- warn: Box<dyn Fn(Error)>,
- endian: Endian,
- bias: f64,
- compression: Option<Compression>,
- var_types: Vec<VarType>,
- }
-
- impl<R: Read + Seek + 'static> State for Start<R> {
- fn read(mut self: Box<Self>) -> Result<Option<(Record, Box<dyn State>)>, Error> {
- let header = HeaderRecord::read(&mut self.reader)?;
- let next_state = Headers(CommonState {
- reader: self.reader,
- warn: self.warn,
- endian: header.endian,
- bias: header.bias,
- compression: header.compression,
- var_types: Vec::new(),
- });
- Ok(Some((Record::Header(header), Box::new(next_state))))
- }
- }
-
- struct Headers<R: Read + Seek>(CommonState<R>);
-
- impl<R: Read + Seek + 'static> State for Headers<R> {
- fn read(mut self: Box<Self>) -> Result<Option<(Record, Box<dyn State>)>, Error> {
- let record = Record::read(&mut self.0.reader, self.0.endian, &self.0.warn)?;
- match record {
- Record::Variable(VariableRecord { width, .. }) => {
- self.0.var_types.push(VarType::from_width(width));
- }
- Record::EndOfHeaders(_) => {
- let next_state: Box<dyn State> = match self.0.compression {
- None => Box::new(Data(self.0)),
- Some(Compression::Simple) => Box::new(CompressedData::new(self.0)),
- Some(Compression::ZLib) => Box::new(ZlibHeader(self.0)),
- };
- return Ok(Some((record, next_state)));
- }
- _ => (),
- };
- Ok(Some((record, self)))
- }
- }
-
- struct ZlibHeader<R: Read + Seek>(CommonState<R>);
-
- impl<R: Read + Seek + 'static> State for ZlibHeader<R> {
- fn read(mut self: Box<Self>) -> Result<Option<(Record, Box<dyn State>)>, Error> {
- let zheader = ZHeader::read(&mut self.0.reader, self.0.endian)?;
- let next_state = Box::new(ZlibTrailer(self.0, zheader.clone()));
- Ok(Some((Record::ZHeader(zheader), next_state)))
- }
- }
-
- struct ZlibTrailer<R: Read + Seek>(CommonState<R>, ZHeader);
-
- impl<R: Read + Seek + 'static> State for ZlibTrailer<R> {
- fn read(mut self: Box<Self>) -> Result<Option<(Record, Box<dyn State>)>, Error> {
- let retval = ZTrailer::read(
- &mut self.0.reader,
- self.0.endian,
- self.1.ztrailer_offset,
- self.1.ztrailer_len,
- )?;
- let next_state = Box::new(CompressedData::new(CommonState {
- reader: ZlibDecodeMultiple::new(self.0.reader),
- warn: self.0.warn,
- endian: self.0.endian,
- bias: self.0.bias,
- compression: self.0.compression,
- var_types: self.0.var_types,
- }));
- match retval {
- None => next_state.read(),
- Some(ztrailer) => Ok(Some((Record::ZTrailer(ztrailer), next_state))),
- }
- }
- }
-
- struct Data<R: Read + Seek>(CommonState<R>);
-
- impl<R: Read + Seek + 'static> State for Data<R> {
- fn read(mut self: Box<Self>) -> Result<Option<(Record, Box<dyn State>)>, Error> {
- match Value::read_case(&mut self.0.reader, &self.0.var_types, self.0.endian)? {
- None => Ok(None),
- Some(values) => Ok(Some((Record::Case(values), self))),
- }
- }
- }
-
- struct CompressedData<R: Read + Seek> {
- common: CommonState<R>,
- codes: VecDeque<u8>,
- }
-
- impl<R: Read + Seek + 'static> CompressedData<R> {
- fn new(common: CommonState<R>) -> CompressedData<R> {
- CompressedData {
- common,
- codes: VecDeque::new(),
- }
- }
- }
-
- impl<R: Read + Seek + 'static> State for CompressedData<R> {
- fn read(mut self: Box<Self>) -> Result<Option<(Record, Box<dyn State>)>, Error> {
- match Value::read_compressed_case(
- &mut self.common.reader,
- &self.common.var_types,
- &mut self.codes,
- self.common.endian,
- self.common.bias,
- )? {
- None => Ok(None),
- Some(values) => Ok(Some((Record::Case(values), self))),
- }
- }
- }
-}
-