pub mod error;
mod iter;
pub use iter::*;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Binvec<const L: usize, const N: usize> {
inner: [u8; N],
}
impl<const L: usize, const N: usize> Binvec<L, N> {
#[deprecated(note = "Use the `binvec!` macro instead.")]
#[doc(hidden)]
pub const fn new(initial_value: bool) -> Self {
let mut new: Binvec<L, N> = Self { inner: [0x00; N] };
new.fill(initial_value);
new
}
#[inline(always)]
pub const fn len(&self) -> usize {
L
}
pub const unsafe fn get_unchecked(&self, index: usize) -> bool {
let byte_index: usize = index >> 3; let bit_offset: usize = index & 0b111; let byte: u8 = self.inner[byte_index];
((byte >> bit_offset) & 1) != 0
}
#[inline]
pub fn get(&self, index: usize) -> Option<bool> {
if index < L {
Some(unsafe { self.get_unchecked(index) })
} else {
None
}
}
pub unsafe fn set_unchecked(&mut self, index: usize, value: bool) {
let byte_index: usize = index >> 3; let bit_offset: usize = index & 0b111; let mask: u8 = 1 << bit_offset;
let byte: &mut u8 = &mut self.inner[byte_index];
if value == true {
*byte |= mask;
} else {
*byte &= !mask;
}
}
#[inline]
pub fn set(&mut self, index: usize, value: bool) -> Result<(), error::IndexOutOfBounds> {
if index < L {
unsafe { self.set_unchecked(index, value); }
Ok(())
} else {
Err(error::IndexOutOfBounds)
}
}
pub const fn fill(&mut self, value: bool) {
let byte: u8 = if value == true { 0xFF } else { 0x00 };
let mut inner: [u8; N] = [byte; N];
if L > 0
&& L % 8 != 0 {
let last_bits: usize = L % 8;
let mask: u8 = (1u8 << last_bits) - 1;
inner[N - 1] &= mask;
}
self.inner = inner;
}
pub const fn count_ones(&self) -> usize {
let mut count: usize = 0;
let mut i: usize = 0;
while i < N {
count += self.inner[i].count_ones() as usize;
i += 1;
}
count }
pub const fn count_zeros(&self) -> usize {
let mut count: usize = 0;
let mut i: usize = 0;
while i < N {
count += self.inner[i].count_zeros() as usize;
i += 1;
}
count - ((N * 8) - L) }
#[inline(always)]
pub const fn is_all_one(&self) -> bool {
self.count_ones() == L
}
#[inline(always)]
pub const fn is_all_zero(&self) -> bool {
self.count_zeros() == L
}
#[inline(always)]
pub fn iter(&self) -> BinvecIter<'_, L, N> {
BinvecIter::new(self)
}
}
impl<'a, const L: usize, const N: usize> IntoIterator for &'a Binvec<L, N> {
type Item = bool;
type IntoIter = BinvecIter<'a, L, N>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
#[macro_export]
macro_rules! binvec {
($len:expr, $initial_value:expr) => {{
const L: usize = $len;
const N: usize = (L + 7) >> 3; #[allow(deprecated)]
Binvec::<L, N>::new($initial_value)
}};
}
impl<const L: usize, const N: usize> core::fmt::Display for Binvec<L, N> {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "[")?;
let mut iter: BinvecIter<'_, L, N> = self.iter();
if let Some(first) = iter.next() {
write!(f, "{}", if first { "1" } else { "0" })?;
for bit in iter {
write!(f, ", {}", if bit { "1" } else { "0" })?;
}
}
write!(f, "]")
}
}