use core::num::NonZeroUsize;
use core::slice::SliceIndex;
#[cfg(feature = "alloc")]
use alloc::fmt::Debug;
use crate::BitBlock;
mod iter;
pub use iter::Bits;
pub use iter::Ones;
pub use iter::Zeros;
#[cfg_attr(feature = "std", derive(Hash))]
#[repr(transparent)]
pub struct BitSlice<B: BitBlock>(pub [B]);
#[cfg(feature = "alloc")]
impl<B: BitBlock> Debug for BitSlice<B> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("[")?;
if f.alternate() {
f.write_str("\n")?;
} else {
f.write_str(" ")?;
}
for (i, bit) in self.bits().enumerate() {
if bit {
f.write_str("1")?;
} else {
f.write_str("0")?;
}
if i == self.len_bits() - 1 {
continue;
}
if i % B::BITS == (B::BITS - 1) {
if f.alternate() {
f.write_str(",\n")?;
} else {
f.write_str(", ")?;
}
} else if i % 8 == 7 {
f.write_str(" ")?;
}
}
if f.alternate() {
f.write_str("\n")?;
} else {
f.write_str(" ")?;
}
f.write_str("]")
}
}
impl<B: BitBlock> BitSlice<B> {
#[inline(always)]
pub fn len_blocks(&self) -> usize {
self.0.len()
}
#[inline(always)]
pub fn len_bits(&self) -> usize {
B::bit_index_from_block_index(self.len_blocks())
}
pub fn get_blocks<I: SliceIndex<[B]>>(&self, index: I) -> Option<&I::Output> {
self.0.get(index)
}
pub fn get_blocks_mut<I: SliceIndex<[B]>>(&mut self, index: I) -> Option<&mut I::Output> {
self.0.get_mut(index)
}
pub fn blocks(&self) -> core::slice::Iter<'_, B> {
self.0.iter()
}
pub fn blocks_mut(&mut self) -> core::slice::IterMut<'_, B> {
self.0.iter_mut()
}
pub fn bits(&self) -> Bits<'_, B> {
Bits::from_slice(self)
}
pub fn ones(&self) -> Ones<'_, B> {
Ones::from_slice(self)
}
pub fn zeros(&self) -> Zeros<'_, B> {
Zeros::from_slice(self)
}
#[inline(always)]
pub fn test(&self, idx: usize) -> Option<bool> {
if B::get_block_index(idx) < self.len_blocks() {
Some(unsafe { self.test_unchecked(idx) })
} else {
None
}
}
#[inline(always)]
pub fn set_checked(&mut self, idx: usize) -> bool {
if B::get_block_index(idx) < self.len_blocks() {
unsafe { self.set_unchecked(idx) };
true
} else {
false
}
}
#[inline(always)]
pub fn reset_checked(&mut self, idx: usize) -> bool {
if B::get_block_index(idx) < self.len_blocks() {
unsafe { self.reset_unchecked(idx) };
true
} else {
false
}
}
pub fn clear(&mut self) {
let blocks: &mut [B] = self.as_mut();
for block in blocks {
*block = B::ZERO;
}
}
pub fn bit_or_assign_iter<I: IntoIterator<Item = B>>(&mut self, other: I) {
for (block, other_block) in self.0.iter_mut().zip(other.into_iter()) {
*block |= other_block;
}
}
#[inline(always)]
pub fn bit_or_assign(&mut self, other: &Self) {
self.bit_or_assign_raw(&other.0)
}
pub fn fill_ones_checked(&mut self, start: usize, length: NonZeroUsize) -> bool {
let len_bits = self.len_bits();
if start + length.get() <= len_bits && start < len_bits {
unsafe {
self.fill_ones_unchecked(start, length);
}
true
} else {
false
}
}
pub fn fill_zeros_checked(&mut self, start: usize, length: NonZeroUsize) -> bool {
let len_bits = self.len_bits();
if start + length.get() <= len_bits && start < len_bits {
unsafe {
self.fill_zeros_unchecked(start, length);
}
true
} else {
false
}
}
}
impl<'a, B: BitBlock + 'a> BitSlice<B> {
#[inline(always)]
pub fn bit_or_assign_raw<I: IntoIterator<Item = &'a B>>(&mut self, other: I) {
self.bit_or_assign_iter(other.into_iter().copied())
}
}
impl<B: BitBlock> BitSlice<B> {
pub unsafe fn test_unchecked(&self, idx: usize) -> bool {
debug_assert!(B::get_block_index(idx) < self.len_blocks());
let block = self.0.get_unchecked(B::get_block_index(idx));
block.wrapping_test_bit(idx)
}
pub unsafe fn set_unchecked(&mut self, idx: usize) {
debug_assert!(B::get_block_index(idx) < self.len_blocks());
let block = self.0.get_unchecked_mut(B::get_block_index(idx));
*block = block.wrapping_with_bit(idx);
}
pub unsafe fn reset_unchecked(&mut self, idx: usize) {
debug_assert!(B::get_block_index(idx) < self.len_blocks());
let block = self.0.get_unchecked_mut(B::get_block_index(idx));
*block = block.wrapping_without_bit(idx);
}
pub unsafe fn fill_ones_unchecked(&mut self, start: usize, length: NonZeroUsize) {
let blocks = &mut self.0;
let block_index = B::get_block_index(start);
let start = start % B::BITS;
let mut remaining_len = length.get();
let mut pos = start;
let mut block_index = block_index;
while let Some(non_zero_remaining_length) = NonZeroUsize::new(remaining_len) {
let block: &mut B = blocks.get_unchecked_mut(block_index);
block_index += 1;
*block |= B::ones_mask(pos, non_zero_remaining_length);
remaining_len = remaining_len.saturating_sub(B::BITS - pos);
pos = 0;
}
}
pub unsafe fn fill_zeros_unchecked(&mut self, start: usize, length: NonZeroUsize) {
let blocks = &mut self.0;
let block_index = B::get_block_index(start);
let start = start % B::BITS;
let mut remaining_len = length.get();
let mut pos = start;
let mut block_index = block_index;
while let Some(non_zero_remaining_length) = NonZeroUsize::new(remaining_len) {
let block: &mut B = blocks.get_unchecked_mut(block_index);
block_index += 1;
*block &= !B::ones_mask(pos, non_zero_remaining_length);
remaining_len = remaining_len.saturating_sub(B::BITS - pos);
pos = 0;
}
}
}
impl<B: BitBlock> AsRef<[B]> for BitSlice<B> {
#[inline(always)]
fn as_ref(&self) -> &[B] {
&self.0
}
}
impl<B: BitBlock> AsMut<[B]> for BitSlice<B> {
#[inline(always)]
fn as_mut(&mut self) -> &mut [B] {
&mut self.0
}
}
impl<B: BitBlock> AsRef<BitSlice<B>> for [B] {
#[inline(always)]
fn as_ref(&self) -> &BitSlice<B> {
unsafe { &*(self as *const [B] as *const BitSlice<B>) }
}
}
impl<B: BitBlock> AsMut<BitSlice<B>> for [B] {
#[inline(always)]
fn as_mut(&mut self) -> &mut BitSlice<B> {
unsafe { &mut *(self as *mut [B] as *mut BitSlice<B>) }
}
}