use std::{fmt, error, result};
#[derive(Debug)]
pub enum Error {
BufferEmpty,
BufferFull,
BufferClosed,
ConversionFailed,
BitOverflow {
bits: u8,
expected: u8,
},
OtherError {
message: Option<String>,
},
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
match *self {
Error::BufferEmpty => write!(f, "buffer empty"),
Error::BufferFull => write!(f, "buffer full"),
Error::BufferClosed => write!(f, "buffer closed"),
Error::ConversionFailed => write!(f, "conversion failed"),
Error::BitOverflow { bits, expected } => write!(f, "bit overflow ({} > {})", bits, expected),
Error::OtherError { ref message } => {
if let &Some(ref message) = message {
write!(f, "bit error ({})", message)
} else {
write!(f, "unknown error")
}
},
}
}
}
impl error::Error for Error {
fn description(&self) -> &'static str {
match *self {
Error::BufferEmpty => "buffer empty",
Error::BufferFull => "buffer full",
Error::BufferClosed => "buffer closed",
Error::ConversionFailed => "conversion failed",
Error::BitOverflow { .. } => "bit overflow",
Error::OtherError { .. } => "bit error",
}
}
}
#[derive(Debug)]
pub enum Precision {
Byte,
Bit,
}
pub type Result<T> = result::Result<T, Error>;
#[derive(Debug, Clone)]
pub struct BitBuffer {
buffer: u64,
bits: u8,
}
impl BitBuffer {
pub fn new() -> BitBuffer {
BitBuffer {
buffer: 0,
bits: 0,
}
}
pub fn push_right(&mut self, value: u8) -> Result<()> {
if self.bits > 56 {
return Err(Error::BufferFull);
}
self.buffer = self.buffer << 8 | value as u64;
self.bits += 8;
Ok(())
}
pub fn pop_right(&mut self) -> Result<u8> {
if self.bits < 8 {
return Err(Error::BufferEmpty);
}
let value = (self.buffer & 0xff) as u8;
self.buffer >>= 8;
self.bits -= 8;
Ok(value)
}
pub fn push_left(&mut self, value: u8) -> Result<()> {
if self.bits > 56 {
return Err(Error::BufferFull);
}
self.buffer |= (value as u64) << self.bits;
self.bits += 8;
Ok(())
}
pub fn pop_left(&mut self) -> Result<u8> {
if self.bits < 8 {
return Err(Error::BufferEmpty);
}
let value = (self.buffer >> self.bits-8 & 0xff) as u8;
self.buffer &= !((0xff as u64) << self.bits-8);
self.bits -= 8;
Ok(value)
}
pub fn push_bit_right(&mut self, value: bool) -> Result<()> {
if self.bits > 63 {
return Err(Error::BufferFull);
}
if value {
self.buffer = self.buffer << 1 | 1;
} else {
self.buffer <<= 1;
}
self.bits += 1;
Ok(())
}
pub fn pop_bit_right(&mut self) -> Result<bool> {
if self.bits < 1 {
return Err(Error::BufferEmpty);
}
let value = self.buffer & 1 == 1;
self.buffer >>= 1;
self.bits -= 1;
Ok(value)
}
pub fn push_bit_left(&mut self, value: bool) -> Result<()> {
if self.bits > 63 {
return Err(Error::BufferFull);
}
if value {
self.buffer |= 1 << self.bits;
}
self.bits += 1;
Ok(())
}
pub fn pop_bit_left(&mut self) -> Result<bool> {
if self.bits < 1 {
return Err(Error::BufferEmpty);
}
let value = self.buffer >> self.bits-1 & 1 == 1;
self.buffer &= !(1 << self.bits-1);
self.bits -= 1;
Ok(value)
}
pub fn bits(&self) -> u8 {
self.bits
}
pub fn bytes(&self) -> u8 {
self.bits/8
}
pub fn is_empty(&self) -> bool {
self.bits == 0
}
pub fn is_aligned(&self) -> bool {
self.bits%8 == 0
}
pub fn has_byte(&self) -> bool {
self.bits >= 8
}
pub fn has_bit(&self) -> bool {
self.bits >= 1
}
pub fn can_take_byte(&self) -> bool {
self.bits <= 56
}
pub fn can_take_bit(&self) -> bool {
self.bits <= 63
}
pub fn byte_space(&self) -> u8 {
(64-self.bits) / 8
}
pub fn bit_space(&self) -> u8 {
64-self.bits
}
}
impl fmt::Display for BitBuffer {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.bits == 0 {
write!(f, "[]")
} else {
let mut buf_str = format!("{:b}", self.buffer);
while (buf_str.len() as u8) < self.bits {
buf_str.insert(0, '0');
}
write!(f, "[{}]", buf_str)
}
}
}