use core::fmt::Debug;
use core::ops::{Add, BitAndAssign, Sub};
pub trait Uint:
Copy + Eq + Add<Output = Self> + Sub<Output = Self> + Sized + BitAndAssign + TryInto<usize>
{
const BITS: usize;
const ZERO: Self;
const ONE: Self;
fn trailing_zeros(self) -> Self;
}
macro_rules! impl_uint_trait {
($primitive_ty:ty) => {
impl Uint for $primitive_ty {
const BITS: usize = <$primitive_ty>::BITS as usize;
const ZERO: Self = 0;
const ONE: Self = 1;
fn trailing_zeros(self) -> Self {
<$primitive_ty>::trailing_zeros(self) as Self
}
}
};
}
impl_uint_trait!(u8);
impl_uint_trait!(u16);
impl_uint_trait!(u32);
impl_uint_trait!(u64);
impl_uint_trait!(u128);
impl_uint_trait!(usize);
#[derive(Debug)]
pub struct BitsIter<U> {
value: U,
}
impl<U: Uint> BitsIter<U>
where
<U as TryInto<usize>>::Error: Debug,
{
pub const fn new(value: U) -> Self {
Self { value }
}
}
impl<U: Uint> Iterator for BitsIter<U>
where
<U as TryInto<usize>>::Error: Debug,
{
type Item = U;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
if self.value == U::ZERO {
return None;
}
let tz = self.value.trailing_zeros();
self.value &= self.value - U::ONE; Some(tz)
}
}
#[derive(Debug)]
pub struct BitmapIter<U, I> {
bitmap_iter: I,
consumed_count: usize,
current_element_it: BitsIter<U>,
}
impl<U: Uint, I: Iterator<Item = U>> BitmapIter<U, I>
where
<U as TryInto<usize>>::Error: Debug,
{
pub fn new<In: IntoIterator<IntoIter = I>>(bitmap_iter: In) -> Self {
let mut bitmap_iter = bitmap_iter.into_iter();
let current_element_it = BitsIter::new(bitmap_iter.next().unwrap_or(U::ZERO));
Self {
bitmap_iter,
consumed_count: 0,
current_element_it,
}
}
}
impl<U: Uint, I: Iterator<Item = U>> Iterator for BitmapIter<U, I>
where
<U as TryInto<usize>>::Error: Debug,
{
type Item = usize;
#[inline]
fn next(&mut self) -> Option<Self::Item> {
loop {
if let Some(bit) = self.current_element_it.next() {
let bit: usize = bit.try_into().unwrap();
return Some(bit + self.consumed_count);
}
let next_byte = self.bitmap_iter.next()?;
self.consumed_count += U::BITS;
self.current_element_it = BitsIter::new(next_byte);
}
}
}
pub trait BitposIteratorExt<U: Uint>: Iterator<Item = U> + Sized
where
<U as TryInto<usize>>::Error: Debug,
{
fn bit_positions(self) -> BitmapIter<U, Self> {
BitmapIter::new(self)
}
}
impl<U: Uint, I: Iterator<Item = U> + Sized> BitposIteratorExt<U> for I where
<U as TryInto<usize>>::Error: Debug
{
}
#[cfg(test)]
mod tests {
use super::*;
use std::vec::Vec;
#[test]
fn test_bits_iter() {
let iter = BitsIter::<u8>::new(0);
assert_eq!(&iter.collect::<Vec<_>>(), &[]);
let iter = BitsIter::<u8>::new(1);
assert_eq!(&iter.collect::<Vec<_>>(), &[0]);
let iter = BitsIter::<u8>::new(0b1010_1010);
assert_eq!(&iter.collect::<Vec<_>>(), &[1, 3, 5, 7]);
let iter = BitsIter::<u8>::new(0b1111_1111);
assert_eq!(&iter.collect::<Vec<_>>(), &[0, 1, 2, 3, 4, 5, 6, 7]);
let iter = BitsIter::<u128>::new(0b1111_1111);
assert_eq!(&iter.collect::<Vec<_>>(), &[0, 1, 2, 3, 4, 5, 6, 7]);
}
#[test]
fn test_bitmap_iter() {
let iter = BitmapIter::<u8, _>::new([0_u8]);
assert_eq!(&iter.collect::<Vec<_>>(), &[]);
let iter = BitmapIter::<u8, _>::new([0b1111_0010, 0b1000, 1]);
assert_eq!(&iter.collect::<Vec<_>>(), &[1, 4, 5, 6, 7, 11, 16]);
let iter = BitmapIter::<u128, _>::new([0b10, 0b10, 0b11]);
assert_eq!(&iter.collect::<Vec<_>>(), &[1, 129, 256, 257]);
}
}