use core::marker::PhantomData;
use core::mem;
use endian::{Endian, Big};
pub struct Bits<End: Endian = Big>(PhantomData<End>, [u8]);
impl<End: Endian> Bits<End> {
#[inline]
pub fn iter(&self) -> Iter<End> { Iter { bits: self, pos: 0 } }
#[inline]
pub fn get(&self, k: usize) -> Option<bool> {
let (m, n) = (k & 7, k >> 3);
self.1.get(n).map(|&x| 0 != x & if End::is_lil { 0x80 >> m } else { 1 << m })
}
#[inline]
pub fn modify<F: FnOnce(bool) -> bool>(&mut self, k: usize, f: F) -> Option<bool> {
let (m, n) = (k & 7, k >> 3);
self.1.get_mut(n).map(|x| {
let mask = if End::is_lil { 0x80 >> m } else { 1 << m };
let b = f(0 != *x & mask);
*x = *x & !mask | if b { mask } else { 0 };
b
})
}
#[inline]
pub unsafe fn get_unchecked(&self, k: usize) -> bool {
let (m, n) = (k & 7, k >> 3);
let x = self.1.get_unchecked(n);
0 != x & if End::is_lil { 0x80 >> m } else { 1 << m }
}
#[inline]
pub unsafe fn modify_unchecked<F: FnOnce(bool) -> bool>(&mut self, k: usize, f: F) -> bool {
let (m, n) = (k & 7, k >> 3);
let x = self.1.get_unchecked_mut(n);
let mask = if End::is_lil { 0x80 >> m } else { 1 << m };
let b = f(0 != *x & mask);
*x = *x & !mask | if b { mask } else { 0 };
b
}
#[inline]
pub fn raw_bytes(&self) -> &[u8] { &self.1 }
#[inline]
pub fn raw_bytes_mut(&mut self) -> &mut [u8] { &mut self.1 }
}
impl<'a> From<&'a [u8]> for &'a Bits {
#[inline]
fn from(bs: &'a [u8]) -> Self { unsafe { mem::transmute(bs) } }
}
impl<'a> From<&'a mut [u8]> for &'a mut Bits {
#[inline]
fn from(bs: &'a mut [u8]) -> Self { unsafe { mem::transmute(bs) } }
}
pub struct Iter<'a, End: 'a + Endian> {
bits: &'a Bits<End>,
pos: usize,
}
impl<'a, End: Endian> Iterator for Iter<'a, End> {
type Item = bool;
#[inline]
fn next(&mut self) -> Option<bool> {
let pos = self.pos;
self.pos += 1;
self.bits.get(pos)
}
}