#![warn(missing_docs)]
#![forbid(unsafe_code)]
use std::fmt::Debug;
use std::io;
use std::marker::PhantomData;
use std::mem;
use std::ops::{BitOrAssign, BitXor, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub};
pub mod huffman;
pub mod read;
pub mod write;
pub use read::{BitReader, ByteReader};
pub use write::{BitWriter, ByteWriter};
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>
{
type Bytes: AsRef<[u8]> + AsMut<[u8]>;
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;
fn buffer() -> Self::Bytes;
fn to_be_bytes(self) -> Self::Bytes;
fn to_le_bytes(self) -> Self::Bytes;
fn from_be_bytes(bytes: Self::Bytes) -> Self;
fn from_le_bytes(bytes: Self::Bytes) -> Self;
}
macro_rules! define_numeric {
($t:ty) => {
impl Numeric for $t {
type Bytes = [u8; mem::size_of::<$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 {
mem::size_of::<$t>() as u32 * 8
}
#[inline(always)]
fn buffer() -> Self::Bytes {
[0; mem::size_of::<$t>()]
}
#[inline(always)]
fn to_be_bytes(self) -> Self::Bytes {
self.to_be_bytes()
}
#[inline(always)]
fn to_le_bytes(self) -> Self::Bytes {
self.to_le_bytes()
}
#[inline(always)]
fn from_be_bytes(bytes: Self::Bytes) -> Self {
<$t>::from_be_bytes(bytes)
}
#[inline(always)]
fn from_le_bytes(bytes: Self::Bytes) -> Self {
<$t>::from_le_bytes(bytes)
}
}
};
}
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);
define_numeric!(i8);
define_numeric!(u16);
define_numeric!(i16);
define_numeric!(u32);
define_numeric!(i32);
define_numeric!(u64);
define_numeric!(i64);
define_numeric!(u128);
define_numeric!(i128);
define_signed_numeric!(i8);
define_signed_numeric!(i16);
define_signed_numeric!(i32);
define_signed_numeric!(i64);
define_signed_numeric!(i128);
pub trait Endianness: Sized {
fn push<N>(queue: &mut BitQueue<Self, N>, bits: u32, value: N)
where
N: Numeric;
fn pop<N>(queue: &mut BitQueue<Self, N>, bits: u32) -> N
where
N: Numeric;
fn drop<N>(queue: &mut BitQueue<Self, N>, bits: u32)
where
N: Numeric;
fn next_zeros<N>(queue: &BitQueue<Self, N>) -> u32
where
N: Numeric;
fn next_ones<N>(queue: &BitQueue<Self, N>) -> u32
where
N: Numeric;
fn read_signed<R, S>(r: &mut BitReader<R, Self>, bits: u32) -> io::Result<S>
where
R: io::Read,
S: SignedNumeric;
fn write_signed<W, S>(w: &mut BitWriter<W, Self>, bits: u32, value: S) -> io::Result<()>
where
W: io::Write,
S: SignedNumeric;
fn read_numeric<R, N>(r: R) -> io::Result<N>
where
R: io::Read,
N: Numeric;
fn write_numeric<W, N>(w: W, value: N) -> io::Result<()>
where
W: io::Write,
N: Numeric;
}
#[derive(Copy, Clone)]
pub struct BigEndian;
pub type BE = BigEndian;
impl Endianness for BigEndian {
#[inline]
fn push<N>(queue: &mut BitQueue<Self, N>, bits: u32, value: N)
where
N: Numeric,
{
if !queue.value.is_zero() {
queue.value <<= bits;
}
queue.value |= value;
queue.bits += bits;
}
#[inline]
fn pop<N>(queue: &mut BitQueue<Self, N>, bits: u32) -> N
where
N: Numeric,
{
if bits < queue.bits {
let offset = queue.bits - bits;
let to_return = queue.value >> offset;
queue.value %= N::one() << offset;
queue.bits -= bits;
to_return
} else {
let to_return = queue.value;
queue.value = N::default();
queue.bits = 0;
to_return
}
}
#[inline]
fn drop<N>(queue: &mut BitQueue<Self, N>, bits: u32)
where
N: Numeric,
{
if bits < queue.bits {
queue.value %= N::one() << (queue.bits - bits);
queue.bits -= bits;
} else {
queue.value = N::default();
queue.bits = 0;
}
}
#[inline]
fn next_zeros<N>(queue: &BitQueue<Self, N>) -> u32
where
N: Numeric,
{
queue.value.leading_zeros() - (N::bits_size() - queue.bits)
}
#[inline]
fn next_ones<N>(queue: &BitQueue<Self, N>) -> u32
where
N: Numeric,
{
if queue.bits < N::bits_size() {
(queue.value ^ ((N::one() << queue.bits) - N::one())).leading_zeros()
- (N::bits_size() - queue.bits)
} else {
(!queue.value).leading_zeros()
}
}
fn read_signed<R, S>(r: &mut BitReader<R, Self>, bits: u32) -> io::Result<S>
where
R: io::Read,
S: SignedNumeric,
{
if bits <= S::bits_size() {
let is_negative = r.read_bit()?;
let unsigned = r.read::<S>(bits - 1)?;
Ok(if is_negative {
unsigned.as_negative(bits)
} else {
unsigned
})
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"excessive bits for type read",
))
}
}
fn write_signed<W, S>(w: &mut BitWriter<W, Self>, bits: u32, value: S) -> io::Result<()>
where
W: io::Write,
S: SignedNumeric,
{
if bits > S::bits_size() {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"excessive bits for type written",
))
} else if bits == S::bits_size() {
w.write_bytes(value.to_be_bytes().as_ref())
} else if value.is_negative() {
w.write_bit(true)
.and_then(|()| w.write(bits - 1, value.as_unsigned(bits)))
} else {
w.write_bit(false).and_then(|()| w.write(bits - 1, value))
}
}
fn read_numeric<R, N>(mut r: R) -> io::Result<N>
where
R: io::Read,
N: Numeric,
{
let mut buffer = N::buffer();
r.read_exact(buffer.as_mut())?;
Ok(N::from_be_bytes(buffer))
}
#[inline]
fn write_numeric<W, N>(mut w: W, value: N) -> io::Result<()>
where
W: io::Write,
N: Numeric,
{
w.write_all(value.to_be_bytes().as_ref())
}
}
#[derive(Copy, Clone)]
pub struct LittleEndian;
pub type LE = LittleEndian;
impl Endianness for LittleEndian {
#[inline]
fn push<N>(queue: &mut BitQueue<Self, N>, bits: u32, mut value: N)
where
N: Numeric,
{
if !value.is_zero() {
value <<= queue.bits;
queue.value |= value;
}
queue.bits += bits;
}
#[inline]
fn pop<N>(queue: &mut BitQueue<Self, N>, bits: u32) -> N
where
N: Numeric,
{
if bits < queue.bits {
let to_return = queue.value % (N::one() << bits);
queue.value >>= bits;
queue.bits -= bits;
to_return
} else {
let to_return = queue.value;
queue.value = N::default();
queue.bits = 0;
to_return
}
}
#[inline]
fn drop<N>(queue: &mut BitQueue<Self, N>, bits: u32)
where
N: Numeric,
{
if bits < queue.bits {
queue.value >>= bits;
queue.bits -= bits;
} else {
queue.value = N::default();
queue.bits = 0;
}
}
#[inline(always)]
fn next_zeros<N>(queue: &BitQueue<Self, N>) -> u32
where
N: Numeric,
{
queue.value.trailing_zeros()
}
#[inline]
fn next_ones<N>(queue: &BitQueue<Self, N>) -> u32
where
N: Numeric,
{
(queue.value ^ !N::default()).trailing_zeros()
}
fn read_signed<R, S>(r: &mut BitReader<R, Self>, bits: u32) -> io::Result<S>
where
R: io::Read,
S: SignedNumeric,
{
if bits <= S::bits_size() {
let unsigned = r.read::<S>(bits - 1)?;
let is_negative = r.read_bit()?;
Ok(if is_negative {
unsigned.as_negative(bits)
} else {
unsigned
})
} else {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"excessive bits for type read",
))
}
}
fn write_signed<W, S>(w: &mut BitWriter<W, Self>, bits: u32, value: S) -> io::Result<()>
where
W: io::Write,
S: SignedNumeric,
{
if bits > S::bits_size() {
Err(io::Error::new(
io::ErrorKind::InvalidInput,
"excessive bits for type written",
))
} else if bits == S::bits_size() {
w.write_bytes(value.to_le_bytes().as_ref())
} else if value.is_negative() {
w.write(bits - 1, value.as_unsigned(bits))
.and_then(|()| w.write_bit(true))
} else {
w.write(bits - 1, value).and_then(|()| w.write_bit(false))
}
}
fn read_numeric<R, N>(mut r: R) -> io::Result<N>
where
R: io::Read,
N: Numeric,
{
let mut buffer = N::buffer();
r.read_exact(buffer.as_mut())?;
Ok(N::from_le_bytes(buffer))
}
#[inline]
fn write_numeric<W, N>(mut w: W, value: N) -> io::Result<()>
where
W: io::Write,
N: Numeric,
{
w.write_all(value.to_le_bytes().as_ref())
}
}
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> {
assert!(if bits < N::bits_size() {
value < (N::one() << bits)
} else {
bits <= N::bits_size()
});
BitQueue {
phantom: PhantomData,
value,
bits,
}
}
#[inline]
pub fn set(&mut self, value: N, bits: u32) {
assert!(if bits < N::bits_size() {
value < (N::one() << bits)
} else {
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(self, bits, value)
}
#[inline(always)]
pub fn pop(&mut self, bits: u32) -> N {
assert!(bits <= self.len());
E::pop(self, bits)
}
#[inline]
pub fn pop_all(&mut self) -> N {
let to_return = self.value;
self.value = N::default();
self.bits = 0;
to_return
}
#[inline(always)]
pub fn drop(&mut self, bits: u32) {
assert!(bits <= self.len());
E::drop(self, bits)
}
#[inline]
pub fn pop_0(&mut self) -> u32 {
let zeros = E::next_zeros(self);
self.drop(zeros + 1);
zeros
}
#[inline]
pub fn pop_1(&mut self) -> u32 {
let ones = E::next_ones(self);
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)
}
}