use crate::traits::{Byteable, Reader};
pub struct BitReader<'a> {
pub bytes: &'a [u8],
pub bit_pos: usize,
pub byte_pos: usize,
}
impl<'a> BitReader<'a> {
pub fn new(bytes: &'a [u8]) -> Self {
BitReader {
bytes,
bit_pos: 0,
byte_pos: 0,
}
}
pub fn read_bit(&mut self) -> Option<bool> {
if self.byte_pos < self.bytes.len() {
let byte = self.bytes[self.byte_pos];
let bit = (byte >> (7 - self.bit_pos)) & 1;
self.bit_pos += 1;
if self.bit_pos == 8 {
self.bit_pos = 0;
self.byte_pos += 1;
}
Some(bit != 0)
} else {
None
}
}
}
impl<'a> Reader for BitReader<'a> {
fn read_u8(&mut self) -> Option<u8> {
if self.remaining() >= 8 {
let mut value = 0;
for i in 0..8 {
if let Some(bit) = self.read_bit() {
if bit {
value |= 1 << (7 - i);
}
} else {
return None;
}
}
Some(value)
} else {
None
}
}
fn read<T: Byteable>(&mut self) -> Option<T> {
T::from_bytes(self)
}
fn remaining(&self) -> usize {
let total_bits = self.bytes.len() * 8;
total_bits - (self.byte_pos * 8 + self.bit_pos)
}
fn reset(&mut self) {
self.bit_pos = 0;
self.byte_pos = 0;
}
fn skip(&mut self, len: usize) -> bool {
let bits_to_skip = len * 8;
if bits_to_skip <= self.remaining() {
self.byte_pos += bits_to_skip / 8;
self.bit_pos += bits_to_skip % 8;
if self.bit_pos >= 8 {
self.byte_pos += 1;
self.bit_pos -= 8;
}
true
} else {
false
}
}
}