#[derive(Clone)]
pub struct BitCursor<'a> {
buf: &'a [u8],
position: usize,
bit_position: u8,
}
impl<'a> BitCursor<'a> {
pub fn new(buf: &'a [u8]) -> BitCursor<'a> {
BitCursor {
buf: buf,
position: 0,
bit_position: 0,
}
}
#[inline]
pub fn read_bit(&mut self) -> Result<bool, ()> {
self.read_u8(1).map(|b| {
match b {
0 => false,
1 => true,
_ => unreachable!(),
}
})
}
#[inline]
pub fn read_u8(&mut self, len: usize) -> Result<u8, ()> {
assert!(len <= 8);
try!(self.check_avail(len));
let ret: u16 = ((self.buf[self.position] as u16) << 8) +
*self.buf.get(self.position + 1).unwrap_or(&0) as u16;
let ret = ret << self.bit_position;
let ret = ret >> (16 - len);
self.skip_unckecked(len);
Ok(ret as u8)
}
#[inline]
pub fn read_u16(&mut self, len: usize) -> Result<u16, ()> {
assert!(len <= 16);
try!(self.check_avail(len));
let ret: u32 = ((self.buf[self.position] as u32) << 16) +
((*self.buf.get(self.position + 1).unwrap_or(&0) as u32) << 8) +
*self.buf.get(self.position + 2).unwrap_or(&0) as u32;
let ret = ret << 8 + self.bit_position;
let ret = ret >> (32 - len);
self.skip_unckecked(len);
Ok(ret as u16)
}
#[inline]
pub fn peek_u32(&mut self, len: usize) -> Result<u32, ()> {
assert!(len <= 32);
try!(self.check_avail(len));
let ret: u64 = ((self.buf[self.position] as u64) << 32) +
((*self.buf.get(self.position + 1).unwrap_or(&0) as u64) << 24) +
((*self.buf.get(self.position + 2).unwrap_or(&0) as u64) << 16) +
((*self.buf.get(self.position + 3).unwrap_or(&0) as u64) << 8) +
(*self.buf.get(self.position + 4).unwrap_or(&0) as u64);
let ret = ret << 24 + self.bit_position;
let ret = ret >> (64 - len);
Ok(ret as u32)
}
#[inline]
pub fn read_u32(&mut self, len: usize) -> Result<u32, ()> {
let ret = try!(self.peek_u32(len));
self.skip_unckecked(len);
Ok(ret)
}
#[inline]
fn check_avail(&self, bit_len: usize) -> Result<(), ()> {
let bit_pos = self.bit_position as usize + bit_len;
let pos = self.position + bit_pos >> 3;
if pos < self.buf.len() {
Ok(())
} else {
Err(())
}
}
#[inline]
pub fn skip(&mut self, bit_len: usize) -> Result<(), ()> {
try!(self.check_avail(bit_len));
self.skip_unckecked(bit_len);
Ok(())
}
#[inline]
fn skip_unckecked(&mut self, bit_len: usize) {
let bit_pos = self.bit_position as usize + bit_len;
self.position += bit_pos >> 3;
self.bit_position = (bit_pos & 7) as u8;
}
#[inline]
pub fn skip_to_byte(&mut self) -> Result<(), ()> {
let skip = self.bit_position & 7;
self.skip(skip as usize)
}
}