Documentation
use std::io::{self, Read};

const DEFAULT_BUFFER_SIZE: usize = 1023;

// bit reader (MSB to LSB)
// TODO: make it abstract over BitStorage
pub struct Reader<R> {
    buffer: Box<[u8]>,
    position: usize,  // in bits
    size: usize, // also in bits
    reader: R
}

impl<R> Reader<R> where R: Read {
    pub fn new(reader: R) -> Self {
        Self::with_capacity(DEFAULT_BUFFER_SIZE, reader)
    }

    pub fn with_capacity(capacity: usize, reader: R) -> Self {
        Reader {
            buffer: vec![0; capacity + 1].into_boxed_slice(),
            position: 0,
            size: 0,
            reader
        }
    }

    pub fn read_bit(&mut self) -> io::Result<bool> {
        if self.size == self.position {
            self.fill_buffer()?;
        }

        let byte_index = self.position / 8;
        let bit_index = 7 - self.position % 8;
        let bit = self.buffer[byte_index] & (1 << bit_index) != 0;

        println!("Reading at {} -> {}", self.position, bit);

        self.position += 1;
        Ok(bit)
    }

    // TODO: abstract over |bits|
    pub fn read_bits(&mut self, bits: &mut u8, count: usize) -> io::Result<()> {
        for i in 0..count {
            let bit = self.read_bit()?;
            if bit {
                *bits |= 1 << (7 - i);
            }
        }

        Ok(())
    }

    fn fill_buffer(&mut self) -> io::Result<()> {
        
        let n = self.reader.read(&mut self.buffer)?;
        println!("Refill: {}", n);
        if n == 0 {
            return Err(io::Error::new(io::ErrorKind::UnexpectedEof, "Unexpected EOF"));
        }

        self.size = n * 8;
        self.position = 0;
        Ok(())
    }
}

#[cfg(test)]
mod tests {
    use std::io::Cursor;
    use super::*;

    #[test]
    fn within_byte() {
        let buffer = vec![0b10100101];
        let cursor = Cursor::new(buffer);
        let mut reader = Reader::new(cursor);
        let mut bits = 0u8;

        reader.read_bits(&mut bits, 4).unwrap();
        assert_eq!(bits, 0b10100000);

        bits = 0;
        reader.read_bits(&mut bits, 4).unwrap();
        assert_eq!(bits, 0b01010000);

        let e = reader.read_bit();
        assert!(e.is_err());
        assert_eq!(e.unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
    }

    #[test]
    fn overlapping() {
        let buffer = vec![0b10101010, 0b10100000];
        let cursor = Cursor::new(buffer);
        let mut reader = Reader::new(cursor);
        let mut bits = 0u8;

        reader.read_bits(&mut bits, 6).unwrap();
        assert_eq!(bits, 0b10101000);
        bits = 0;

        reader.read_bits(&mut bits, 6).unwrap();
        assert_eq!(bits, 0b10101000);
        bits = 0;

        reader.read_bits(&mut bits, 4).unwrap();        
        assert_eq!(bits, 0);

        let e = reader.read_bit();
        assert!(e.is_err());
        assert_eq!(e.unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
    }

    #[test]
    fn buffer_overflow() {
        let buffer = vec![0b10101010, 0b10100000];
        let cursor = Cursor::new(buffer);
        let mut reader = Reader::with_capacity(0, cursor);
        let mut bits = 0u8;

        reader.read_bits(&mut bits, 6).unwrap();
        assert_eq!(bits, 0b10101000);
        bits = 0;

        reader.read_bits(&mut bits, 6).unwrap();
        assert_eq!(bits, 0b10101000);
        bits = 0;

        reader.read_bits(&mut bits, 4).unwrap();        
        assert_eq!(bits, 0);

        let e = reader.read_bit();
        assert!(e.is_err());
        assert_eq!(e.unwrap_err().kind(), io::ErrorKind::UnexpectedEof);
    }
}