- fn _next(&mut self) -> Result<Option<Record>, Error> {
- match self.state {
- ReaderState::Start => {
- let header = read_header(&mut self.r)?;
- self.state = ReaderState::Headers(header.endianness, header.compression);
- Ok(Some(Record::Header(header)))
- }
- ReaderState::Headers(endian, compression) => {
- let rec_type: u32 = endian.parse(read_bytes(&mut self.r)?);
- let record = match rec_type {
- 2 => {
- let variable = read_variable_record(&mut self.r, endian)?;
- self.var_types.push(VarType::from_width(variable.width));
- Record::Variable(variable)
- }
- 3 => Record::ValueLabel(read_value_label_record(&mut self.r, endian)?),
- 4 => Record::VarIndexes(read_var_indexes_record(&mut self.r, endian)?),
- 6 => Record::Document(read_document_record(&mut self.r, endian)?),
- 7 => Record::Extension(read_extension_record(&mut self.r, endian)?),
- 999 => {
- let _: [u8; 4] = read_bytes(&mut self.r)?;
- self.state = match compression {
- None => ReaderState::Data(endian),
- Some(Compression::Simple) => {
- ReaderState::CompressedData(endian, VecDeque::new())
- }
- Some(Compression::ZLib) => ReaderState::ZHeader(endian),
- };
- return Ok(Some(Record::EndOfHeaders));
- }
- _ => {
- return Err(Error::BadRecordType {
- offset: self.r.stream_position()?,
- rec_type,
- })
- }
- };
- Ok(Some(record))
- }
- ReaderState::Data(endian) => {
- let case_start = self.r.stream_position()?;
- let mut values = Vec::with_capacity(self.var_types.len());
- for (i, &var_type) in self.var_types.iter().enumerate() {
- let Some(raw) = try_read_bytes(&mut self.r)? else {
- if i == 0 {
- return Ok(None);
- } else {
- let offset = self.r.stream_position()?;
- return Err(Error::EofInCase {
- offset,
- case_ofs: offset - case_start,
- case_len: self.var_types.len() * 8,
- });
- }
- };
- values.push(Value::from_raw(var_type, raw, endian));
- }
- Ok(Some(Record::Case(values)))
- }
- ReaderState::CompressedData(endian, ref mut codes) => {
- let case_start = self.r.stream_position()?;
- let mut values = Vec::with_capacity(self.var_types.len());
- let bias = 100.0; // XXX
- for (i, &var_type) in self.var_types.iter().enumerate() {
- let value = loop {
- let Some(code) = codes.pop_front() else {
- let Some(new_codes): Option<[u8; 8]> = try_read_bytes(&mut self.r)?
- else {
- if i == 0 {
- return Ok(None);
- } else {
- let offset = self.r.stream_position()?;
- return Err(Error::EofInCompressedCase {
- offset,
- case_ofs: offset - case_start,
- });
- }
- };
- codes.extend(new_codes.into_iter());
- continue;
- };
- match code {
- 0 => (),
- 1..=251 => match var_type {
- VarType::Number => break Value::Number(Some(code as f64 - bias)),
- VarType::String => {
- break Value::String(endian.to_bytes(code as f64 - bias))
- }
- },
- 252 => {
- if i == 0 {
- return Ok(None);
- } else {
- let offset = self.r.stream_position()?;
- return Err(Error::PartialCompressedCase {
- offset,
- case_ofs: offset - case_start,
- });
- }
- }
- 253 => {
- break Value::from_raw(var_type, read_bytes(&mut self.r)?, endian)
- }
- 254 => match var_type {
- VarType::String => break Value::String(*b" "), // XXX EBCDIC
- VarType::Number => {
- return Err(Error::CompressedStringExpected {
- offset: case_start,
- case_ofs: self.r.stream_position()? - case_start,
- })
- }
- },
- 255 => match var_type {
- VarType::Number => break Value::Number(None),
- VarType::String => {
- return Err(Error::CompressedNumberExpected {
- offset: case_start,
- case_ofs: self.r.stream_position()? - case_start,
- })
- }
- },
- }
- };
- values.push(value);
- }
- Ok(Some(Record::Case(values)))
- }
- ReaderState::ZHeader(endian) => {
- let zheader = read_zheader(&mut self.r, endian)?;
- self.state = ReaderState::ZTrailer {
- endian,
- ztrailer_ofs: zheader.ztrailer_offset,
- ztrailer_len: zheader.ztrailer_len,
- };
- Ok(Some(Record::ZHeader(zheader)))
- }
- ReaderState::ZTrailer {
- endian,
- ztrailer_ofs,
- ztrailer_len,
- } => {
- //self.state = ReaderState::ZData;
- match read_ztrailer(&mut self.r, endian, ztrailer_ofs, ztrailer_len)? {
- Some(ztrailer) => Ok(Some(Record::ZTrailer(ztrailer))),
- None => self._next(),
- }
- }
- /*
- ReaderState::ZData(zlib_decoder) => {
- let zlib_decoder = zlib_decoder.unwrap_or_else(
- },
- */
- ReaderState::End => Ok(None),
- }
- }