simple-arithmetic-coding 0.2.2

Arithmetic coding, directly derived from the well-known CACM87 C-language implementation.
Documentation
use std::io::{BufRead, Write};

use crate::bitvec::BitVec;

pub struct Input <I>
where I: BufRead
{
    input_handle: I,
    input_bits: BitVec,
    idx: usize
}

impl<I> Input<I>
where I: BufRead
{
    pub fn new (mut input_handle: I) -> Result<Input<I>, std::io::Error> {
        let b = input_handle.fill_buf()?;
        let input_bits = BitVec::from_bytes(b);
        let len = b.len();
        input_handle.consume(len);
        Ok(Input {
            input_handle,
            input_bits,
            idx: 0
        })
    }
}

pub trait Next {
    fn next_bit (&mut self) -> Result<Option<bool>, std::io::Error>;
    fn next_byte (&mut self) -> Result<Option<u8>, std::io::Error>;
}

impl<I> Next for Input<I>
where I: BufRead
{
    fn next_bit (&mut self) -> Result<Option<bool>, std::io::Error> {
        if self.idx >= self.input_bits.len() {
            let b = self.input_handle.fill_buf()?;
            self.input_bits = BitVec::from_bytes(b);
            let len = b.len();
            self.input_handle.consume(len);
            self.idx = 0;
        }
        if let Some(o) = self.input_bits.get(self.idx) {
            self.idx += 1;
            Ok(Some(o))
        } else {
            Ok(None)
        }
    }

    fn next_byte (&mut self) -> Result<Option<u8>, std::io::Error>
    {
        let mut byte: u8 = 0;
        for shft in (0..8).rev() {
            if let Some(b) = self.next_bit()? {
                byte |= (b as u8) << shft;
            } else {
                return Ok(None);
            }
        }
        Ok(Some(byte))
    }
}


pub struct Output<'a, O>
where O: Write
{
    output_handle: &'a mut O,
    output_bits: BitVec
}

impl <'a, O> Output <'a, O>
where O: Write
{
    pub fn new(output_handle: &'a mut O, buffer_capacity: usize) -> Self {
        debug_assert!(buffer_capacity % 8 == 0);
        Output {
            output_handle,
            output_bits: BitVec::with_capacity(buffer_capacity)
        }
    }
}

pub trait Push {
    fn push_bit(&mut self, bit: bool) -> Result<(), std::io::Error>;
    fn push_byte(&mut self, byte: u8) -> Result<(), std::io::Error>;
    fn flush (&mut self) -> Result<(), std::io::Error>;
}

impl<'a, O> Push for Output<'a, O>
where O: Write
{
    fn push_bit(&mut self, bit: bool) -> Result<(), std::io::Error>
    {
        if self.output_bits.len() == self.output_bits.capacity() {
            self.flush()?;
        }
        self.output_bits.push(bit);
        Ok(())
    }

    fn push_byte(&mut self, byte: u8) -> Result<(), std::io::Error>
    {
        for shft in (0..8).rev() {
            self.push_bit(((byte >> shft) & 1) != 0)?;
        }
        Ok(())
    }
    fn flush (&mut self) -> Result<(), std::io::Error>
    {
        if !self.output_bits.is_empty() {
            self.output_handle.write_all(&self.output_bits.get_bytes())?;
            self.output_bits.clear();
        }
        Ok(())
    }
}