use std::marker::PhantomData;
use super::{BitValue, Word};
pub struct IterImpl<V: BitValue, N> {
next_word: N,
word: Word,
bits_left: u32, next_index: usize, _p: PhantomData<V>,
}
impl<V: BitValue, N: Clone> Clone for IterImpl<V, N> {
fn clone(&self) -> Self {
Self {
next_word: self.next_word.clone(),
word: self.word,
bits_left: self.bits_left,
next_index: self.next_index,
_p: PhantomData,
}
}
}
impl<V: BitValue, N: Copy> Copy for IterImpl<V, N> {}
impl<V: BitValue, N> IterImpl<V, N> {
pub fn new(next_word: N) -> Self {
Self {
next_word,
word: 0,
bits_left: 0,
next_index: 0,
_p: PhantomData,
}
}
}
impl<V: BitValue, N: Iterator<Item = Word>> Iterator for IterImpl<V, N> {
type Item = V;
fn next(&mut self) -> Option<Self::Item> {
if self.word == 0 {
self.next_index += self.bits_left as usize;
self.bits_left = 0;
}
if self.bits_left == 0 {
loop {
self.word = self.next_word.next()?;
if self.word == 0 {
self.next_index += Word::BITS as usize;
} else {
break;
}
}
self.bits_left = Word::BITS;
}
let zeroes = self.word.trailing_zeros();
debug_assert_ne!(zeroes, Word::BITS);
let index = self.next_index + zeroes as usize;
self.word >>= zeroes as usize;
self.word >>= 1;
self.next_index += zeroes as usize + 1;
self.bits_left -= zeroes + 1;
Some(V::from_index(index))
}
}