use core::{mem, ops};
use bit_vec::BitBlock;
use crate::local_prelude::*;
use crate::util::div_rem;
pub struct BitSlice<Block> {
pub(crate) slice: [Block],
}
impl<Block: BitBlock> BitSlice<Block> {
#[inline]
pub fn new(slice: &[Block]) -> &Self {
unsafe { mem::transmute(slice) }
}
#[inline]
pub fn new_mut(slice: &mut [Block]) -> &mut Self {
unsafe { mem::transmute(slice) }
}
#[inline]
pub fn iter_bits(&self, len: usize) -> impl Iterator<Item = bool> + '_ {
(0..len).map(|i| self[i])
}
pub fn iter_blocks(&self) -> impl Iterator<Item = &Block> {
self.slice.iter()
}
pub fn iter_blocks_mut(&mut self) -> impl Iterator<Item = &mut Block> {
self.slice.iter_mut()
}
#[inline]
pub fn get(&self, bit: usize) -> bool {
let (block, i) = div_rem(bit, Block::bits());
match self.slice.get(block) {
None => false,
Some(&b) => (b & (Block::one() << i)) != Block::zero(),
}
}
#[inline]
pub fn small_slice_aligned(&self, bit: usize, len: u8) -> Block {
let (block, i) = div_rem(bit, Block::bits());
match self.slice.get(block) {
None => Block::zero(),
Some(&b) => {
let len_mask = (Block::one() << len as usize) - Block::one();
(b >> i) & len_mask
}
}
}
}
impl<Block: BitBlock> ops::Index<usize> for BitSlice<Block> {
type Output = bool;
#[inline]
fn index(&self, bit: usize) -> &bool {
let (block, i) = div_rem(bit, Block::bits());
match self.slice.get(block) {
None => &FALSE,
Some(&b) => {
if (b & (Block::one() << i)) != Block::zero() {
&TRUE
} else {
&FALSE
}
}
}
}
}
impl<Block: BitBlock> ops::BitOrAssign for &mut BitSlice<Block> {
fn bitor_assign(&mut self, rhs: Self) {
debug_assert_eq!(self.slice.len(), rhs.slice.len());
for (dst, src) in self.iter_blocks_mut().zip(rhs.iter_blocks()) {
*dst |= *src;
}
}
}