use super::*;
use std::io;
use std::mem;
pub trait BitRead<T>: Sized {
fn read_value_from<R: io::Read>(&self, reader: &mut BitReader<R>) -> Result<T>;
}
pub trait BitWrite<T>: Sized {
fn write_value_to<W: io::Write>(&self, value: T, writer: &mut BitWriter<W>) -> Result<()>;
}
#[derive(Debug)]
pub struct BitMask {
bits: u8,
}
impl BitMask {
pub fn bits(bits: u8) -> BitMask {
BitMask {
bits,
}
}
pub fn bytes(bytes: u8) -> BitMask {
BitMask {
bits: bytes*8,
}
}
}
impl BitReadable for BitMask {
fn read_from<R: io::Read>(reader: &mut BitReader<R>) -> Result<BitMask> {
match reader.read_byte() {
Ok(bits) => Ok(BitMask { bits }),
Err(e) => Err(e),
}
}
}
impl BitWritable for BitMask {
fn write_to<W: io::Write>(self, writer: &mut BitWriter<W>) -> Result<()> {
writer.write_byte(self.bits)
}
}
impl<'a> BitWritable for &'a BitMask {
fn write_to<W: io::Write>(self, writer: &mut BitWriter<W>) -> Result<()> {
writer.write_byte(self.bits)
}
}
macro_rules! impl_bit_mask {
($( $u: ident $i: ident $b: expr ),+) => { $(
impl BitRead<$u> for BitMask {
fn read_value_from<R: io::Read>(&self, reader: &mut BitReader<R>) -> Result<$u> {
if self.bits > $b {
return Err(Error::ConversionFailed);
} else if self.bits == 0 {
return Ok(0);
}
let mut int = 0;
for index in 0..self.bits {
let read = reader.read_bit()?;
if read {
int |= 1 << (self.bits-index-1);
}
}
Ok($u::from_le(int))
}
}
impl BitRead<$i> for BitMask {
fn read_value_from<R: io::Read>(&self, reader: &mut BitReader<R>) -> Result<$i> {
unsafe { Ok(mem::transmute::<$u, $i>(self.read_value_from(reader)?)) }
}
}
impl BitWrite<$u> for BitMask {
fn write_value_to<W: io::Write>(&self, value: $u, writer: &mut BitWriter<W>) -> Result<()> {
if self.bits != 0 {
let int = u64::to_le(value as u64);
if self.bits < 64 && int >> self.bits != 0 {
return Err(Error::ConversionFailed);
}
for index in 0..self.bits {
writer.write_bit((int >> (self.bits - index - 1)) & 1 == 1)?;
}
}
Ok(())
}
}
impl BitWrite<$i> for BitMask {
fn write_value_to<W: io::Write>(&self, value: $i, writer: &mut BitWriter<W>) -> Result<()> {
unsafe { self.write_value_to(mem::transmute::<$i, $u>(value), writer) }
}
}
)+ }
}
impl_bit_mask!(u64 i64 64, u32 i32 32, u16 i16 16, u8 i8 8);