#![warn(missing_docs)]
use std::ops::{Shl, ShlAssign, Shr, ShrAssign, Rem, RemAssign, BitOrAssign,
BitXor, Not, Sub};
use std::marker::PhantomData;
use std::fmt::Debug;
pub mod read;
pub mod write;
pub mod huffman;
pub use read::BitReader;
pub use write::BitWriter;
pub trait Numeric: Sized + Copy + Default + Debug + PartialOrd +
Shl<u32,Output=Self> + ShlAssign<u32> +
Shr<u32,Output=Self> + ShrAssign<u32> +
Rem<Self,Output=Self> + RemAssign<Self> +
BitOrAssign<Self> + BitXor<Self,Output=Self> + Not<Output=Self> +
Sub<Self,Output=Self> {
fn one() -> Self;
fn is_zero(self) -> bool;
fn from_u8(u: u8) -> Self;
fn to_u8(self) -> u8;
fn count_ones(self) -> u32;
fn leading_zeros(self) -> u32;
fn trailing_zeros(self) -> u32;
fn bits_size() -> u32;
}
macro_rules! define_numeric {
($t:ty, $bits:expr) => {
impl Numeric for $t {
#[inline(always)]
fn one() -> Self {1}
#[inline(always)]
fn is_zero(self) -> bool {self == 0}
#[inline(always)]
fn from_u8(u: u8) -> Self {u as $t}
#[inline(always)]
fn to_u8(self) -> u8 {self as u8}
#[inline(always)]
fn count_ones(self) -> u32 {self.count_ones()}
#[inline(always)]
fn leading_zeros(self) -> u32 {self.leading_zeros()}
#[inline(always)]
fn trailing_zeros(self) -> u32 {self.trailing_zeros()}
#[inline(always)]
fn bits_size() -> u32 {$bits}
}
}
}
pub trait SignedNumeric: Numeric {
fn is_negative(self) -> bool;
fn as_negative(self, bits: u32) -> Self;
fn as_unsigned(self, bits: u32) -> Self;
}
macro_rules! define_signed_numeric {
($t:ty) => {
impl SignedNumeric for $t {
#[inline(always)]
fn is_negative(self) -> bool {self < 0}
#[inline(always)]
fn as_negative(self, bits: u32) -> Self {self + (-1 << (bits - 1))}
#[inline(always)]
fn as_unsigned(self, bits: u32) -> Self {self - (-1 << (bits - 1))}
}
}
}
define_numeric!(u8, 8);
define_numeric!(i8, 8);
define_numeric!(u16, 16);
define_numeric!(i16, 16);
define_numeric!(u32, 32);
define_numeric!(i32, 32);
define_numeric!(u64, 64);
define_numeric!(i64, 64);
define_numeric!(u128, 128);
define_numeric!(i128, 128);
define_signed_numeric!(i8);
define_signed_numeric!(i16);
define_signed_numeric!(i32);
define_signed_numeric!(i64);
define_signed_numeric!(i128);
pub trait Endianness {
fn push<N>(bits_acc: &mut u32,
value_acc: &mut N,
bits: u32,
value: N) where N: Numeric;
fn pop<N>(bits_acc: &mut u32,
value_acc: &mut N,
bits: u32) -> N where N: Numeric;
fn drop<N>(bits_acc: &mut u32,
value_acc: &mut N,
bits: u32) where N: Numeric;
fn next_zeros<N>(bits: u32, value: N) -> u32 where N: Numeric;
fn next_ones<N>(bits: u32, value: N) -> u32 where N: Numeric;
}
pub struct BigEndian {}
pub type BE = BigEndian;
impl Endianness for BigEndian {
#[inline]
fn push<N>(bits_acc: &mut u32,
value_acc: &mut N,
bits: u32,
value: N) where N: Numeric {
if !value_acc.is_zero() {
*value_acc <<= bits;
}
*value_acc |= value;
*bits_acc += bits;
}
#[inline]
fn pop<N>(bits_acc: &mut u32,
value_acc: &mut N,
bits: u32) -> N where N: Numeric {
if bits < *bits_acc {
let offset = *bits_acc - bits;
let to_return = *value_acc >> offset;
*value_acc %= N::one() << offset;
*bits_acc -= bits;
to_return
} else {
let to_return = *value_acc;
*value_acc = N::default();
*bits_acc = 0;
to_return
}
}
#[inline]
fn drop<N>(bits_acc: &mut u32,
value_acc: &mut N,
bits: u32) where N: Numeric {
if bits < *bits_acc {
*value_acc %= N::one() << (*bits_acc - bits);
*bits_acc -= bits;
} else {
*value_acc = N::default();
*bits_acc = 0;
}
}
#[inline]
fn next_zeros<N>(bits: u32, value: N) -> u32 where N: Numeric {
value.leading_zeros() - (N::bits_size() - bits)
}
#[inline]
fn next_ones<N>(bits: u32, value: N) -> u32 where N: Numeric {
if bits < N::bits_size() {
(value ^ ((N::one() << bits) - N::one())).leading_zeros() -
(N::bits_size() - bits)
} else {
(!value).leading_zeros()
}
}
}
pub struct LittleEndian {}
pub type LE = LittleEndian;
impl Endianness for LittleEndian {
#[inline]
fn push<N>(bits_acc: &mut u32,
value_acc: &mut N,
bits: u32,
mut value: N) where N: Numeric {
if !value.is_zero() {
value <<= *bits_acc;
}
*value_acc |= value;
*bits_acc += bits;
}
#[inline]
fn pop<N>(bits_acc: &mut u32,
value_acc: &mut N,
bits: u32) -> N where N: Numeric {
if bits < *bits_acc {
let to_return = *value_acc % (N::one() << bits);
*value_acc >>= bits;
*bits_acc -= bits;
to_return
} else {
let to_return = *value_acc;
*value_acc = N::default();
*bits_acc = 0;
to_return
}
}
#[inline]
fn drop<N>(bits_acc: &mut u32,
value_acc: &mut N,
bits: u32) where N: Numeric {
if bits < *bits_acc {
*value_acc >>= bits;
*bits_acc -= bits;
} else {
*value_acc = N::default();
*bits_acc = 0;
}
}
#[inline(always)]
fn next_zeros<N>(_: u32, value: N) -> u32 where N: Numeric {
value.trailing_zeros()
}
#[inline]
fn next_ones<N>(_: u32, value: N) -> u32 where N: Numeric {
(value ^ !N::default()).trailing_zeros()
}
}
pub struct BitQueue<E: Endianness, N: Numeric> {
phantom: PhantomData<E>,
value: N,
bits: u32,
}
impl<E: Endianness, N: Numeric> BitQueue<E, N> {
#[inline]
pub fn new() -> BitQueue<E, N> {
BitQueue{phantom: PhantomData, value: N::default(), bits: 0}
}
#[inline]
pub fn from_value(value: N, bits: u32) -> BitQueue<E,N> {
if bits < N::bits_size() {
assert!(value < (N::one() << bits));
} else {
assert!(bits <= N::bits_size());
}
BitQueue{phantom: PhantomData, value: value, bits: bits}
}
#[inline]
pub fn set(&mut self, value: N, bits: u32) {
if bits < N::bits_size() {
assert!(value < (N::one() << bits));
} else {
assert!(bits <= N::bits_size());
}
self.value = value;
self.bits = bits;
}
#[inline(always)]
pub fn value(self) -> N {self.value}
#[inline(always)]
pub fn len(&self) -> u32 {self.bits}
#[inline(always)]
pub fn max_len(&self) -> u32 {N::bits_size()}
#[inline(always)]
pub fn remaining_len(&self) -> u32 {self.max_len() - self.len()}
#[inline(always)]
pub fn is_empty(&self) -> bool {self.bits == 0}
#[inline(always)]
pub fn is_full(&self) -> bool {self.bits == N::bits_size()}
#[inline(always)]
pub fn clear(&mut self) {self.set(N::default(), 0)}
#[inline(always)]
pub fn all_0(&self) -> bool {self.value.count_ones() == 0}
#[inline(always)]
pub fn all_1(&self) -> bool {self.value.count_ones() == self.bits}
#[inline(always)]
pub fn push(&mut self, bits: u32, value: N) {
assert!(bits <= self.remaining_len()); E::push(&mut self.bits, &mut self.value, bits, value)
}
#[inline(always)]
pub fn pop(&mut self, bits: u32) -> N {
assert!(bits <= self.len()); E::pop(&mut self.bits, &mut self.value, bits)
}
#[inline(always)]
pub fn drop(&mut self, bits: u32) {
assert!(bits <= self.len()); E::drop(&mut self.bits, &mut self.value, bits)
}
#[inline]
pub fn pop_0(&mut self) -> u32 {
let zeros = E::next_zeros(self.bits, self.value);
self.drop(zeros + 1);
zeros
}
#[inline]
pub fn pop_1(&mut self) -> u32 {
let ones = E::next_ones(self.bits, self.value);
self.drop(ones + 1);
ones
}
}
impl<E: Endianness> BitQueue<E, u8> {
#[inline(always)]
pub fn to_state(&self) -> usize {
(1 << self.bits) | (self.value as usize)
}
}