use core::{array, iter::Enumerate, mem::MaybeUninit, slice};
macro_rules! impl_iterator_outer {
($name:ident $into_iter:ident $iter:ident $iter_mut:ident $int:ty) => {
pub struct $into_iter<T> {
pub(crate) iter: Enumerate<array::IntoIter<MaybeUninit<T>, { <$int>::BITS as usize }>>,
pub(crate) mask: $int,
}
impl<T> Drop for $into_iter<T> {
fn drop(&mut self) {
for (i, item) in self.iter.by_ref() {
if self.mask & (1 << i) != 0 {
drop(unsafe { item.assume_init() });
}
}
}
}
impl<T> Iterator for $into_iter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
loop {
let (i, item) = self.iter.next()?;
if self.mask & (1 << i) != 0 {
return Some(unsafe { item.assume_init() });
}
}
}
}
pub struct $iter<'a, T> {
pub(crate) iter: Enumerate<slice::Iter<'a, MaybeUninit<T>>>,
pub(crate) mask: $int,
}
impl<'a, T> Iterator for $iter<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
loop {
let (i, item) = self.iter.next()?;
if self.mask & (1 << i) != 0 {
return Some(unsafe { item.assume_init_ref() });
}
}
}
}
pub struct $iter_mut<'a, T> {
pub(crate) iter: Enumerate<slice::IterMut<'a, MaybeUninit<T>>>,
pub(crate) mask: $int,
}
impl<'a, T> Iterator for $iter_mut<'a, T> {
type Item = &'a mut T;
fn next(&mut self) -> Option<Self::Item> {
loop {
let (i, item) = self.iter.next()?;
if self.mask & (1 << i) != 0 {
return Some(unsafe { item.assume_init_mut() });
}
}
}
}
};
}
impl_iterator_outer!(Block8 Block8IntoIter Block8Iter Block8IterMut u8);
impl_iterator_outer!(Block16 Block16IntoIter Block16Iter Block16IterMut u16);
impl_iterator_outer!(Block32 Block32IntoIter Block32Iter Block32IterMut u32);
impl_iterator_outer!(Block64 Block64IntoIter Block64Iter Block64IterMut u64);
impl_iterator_outer!(Block128 Block128IntoIter Block128Iter Block128IterMut u128);