use std::convert::TryInto;
pub use self::error::DecoderError;
pub use self::reader::DecoderReader;
use crate::bitreader::BitReader;
use crate::block::Block;
use crate::header::Header;
mod error;
mod reader;
pub struct Decoder {
header_block: Option<(Header, Block)>,
skip_bits: usize,
in_buf: Vec<u8>,
eof: bool,
}
pub enum WriteState {
NeedsRead,
Written(usize),
}
pub enum ReadState {
NeedsWrite(usize),
Read(usize),
Eof,
}
impl Decoder {
pub fn new() -> Self {
Self {
header_block: None,
skip_bits: 0,
in_buf: Vec::new(),
eof: false,
}
}
fn space(&self) -> usize {
match &self.header_block {
Some((_, block)) if block.is_reading() => 0,
Some((header, _)) => {
let max_length = header.max_blocksize() as usize + (self.skip_bits / 8) + 1;
max_length - self.in_buf.len()
}
None => {
Header::from_raw_blocksize(1)
.expect("blocksize is valid")
.max_blocksize() as usize
+ 4
}
}
}
pub fn write(&mut self, buf: &[u8]) -> Result<WriteState, DecoderError> {
let space = self.space();
match &mut self.header_block {
Some((_, block)) if block.is_reading() => Ok(WriteState::NeedsRead),
Some((header, block)) => {
let written = space.min(buf.len());
self.in_buf.extend_from_slice(&buf[..written]);
let minimum = (self.skip_bits / 8) + header.max_blocksize() as usize;
if buf.is_empty() || self.in_buf.len() >= minimum {
block.set_ready_for_read();
}
Ok(WriteState::Written(written))
}
None => {
let written = space.min(buf.len());
self.in_buf.extend_from_slice(&buf[..written]);
if self.in_buf.len() < 4 {
return Ok(WriteState::Written(buf.len()));
}
let header = Header::parse(self.in_buf[..4].try_into().unwrap())?;
let block = Block::new(header.clone());
self.header_block = Some((header, block));
self.skip_bits = 4 * 8;
if written == buf.len() {
return Ok(WriteState::Written(written));
}
match self.write(&buf[written..])? {
WriteState::NeedsRead => unreachable!(),
WriteState::Written(n) => Ok(WriteState::Written(n + written)),
}
}
}
}
pub fn read(&mut self, buf: &mut [u8]) -> Result<ReadState, DecoderError> {
match &mut self.header_block {
Some(_) if self.eof => Ok(ReadState::Eof),
Some((_, block)) if block.is_not_ready() => Ok(ReadState::NeedsWrite(self.space())),
Some((_, block)) => {
let mut reader = BitReader::new(&self.in_buf);
reader.advance_by(self.skip_bits);
let ready_for_read = block.is_ready_for_read();
let read = block.read(&mut reader, buf)?;
if read == 0 {
if !buf.is_empty() {
self.eof = ready_for_read;
}
return Ok(ReadState::NeedsWrite(self.space()));
}
if read == 0 && !buf.is_empty() {
self.eof = true;
}
self.skip_bits = reader.position();
if block.is_not_ready() {
let bytes = self.skip_bits / 8;
self.in_buf.drain(..bytes);
self.skip_bits -= bytes * 8;
}
Ok(ReadState::Read(read))
}
None => Ok(ReadState::NeedsWrite(self.space())),
}
}
}
impl Default for Decoder {
fn default() -> Self {
Self::new()
}
}