use core::{
convert::{TryFrom, TryInto},
iter::{Enumerate, FilterMap},
marker::PhantomData,
};
use super::Bit;
use crate::{Bits, BitsOps, IntoBits};
pub struct BitsIter<V: IntoBits> {
pub(crate) value: V,
pub(crate) low: u32,
pub(crate) upper: u32,
}
impl<V: IntoBits> Iterator for BitsIter<V> {
type Item = Bit<V>;
fn next(&mut self) -> Option<Self::Item> {
let ret = if self.low <= self.upper {
Some(Bit {
value: self.value.bits(self.low).read(),
})
} else {
None
};
self.low += 1;
ret
}
}
pub struct BitMap<T, Pos>
where
Bits<T>: BitsOps<T>,
Pos: Into<u32> + TryFrom<u32>,
T: Sized + IntoBits<Output = Bits<T>>,
{
raw: T,
_phantom: PhantomData<Pos>,
}
impl<T, Pos> BitMap<T, Pos>
where
Bits<T>: BitsOps<T>,
Pos: Into<u32> + TryFrom<u32>,
T: Sized + IntoBits<Output = Bits<T>>,
{
pub fn new(raw_bitmap: T) -> Self {
Self {
raw: raw_bitmap,
_phantom: PhantomData,
}
}
pub fn is_setted(&self, pos: Pos) -> bool {
let pos: u32 = pos.into();
self.raw.bits(pos).is_set()
}
pub fn set(&mut self, pos: Pos) {
self.raw = self.raw.bits(pos.into()).set()
}
pub fn raw(&self) -> T {
self.raw
}
#[inline(always)]
pub fn any_undefined(&self) -> bool {
for (pos, bit) in self.raw.bits(..).into_iter().enumerate() {
if Pos::try_from(pos as u32).is_err() && bit.is_set() {
return false;
}
}
true
}
}
pub struct BitMapIter<T, Pos>
where
Bits<T>: BitsOps<T>,
Pos: Into<u32> + TryFrom<u32>,
T: Sized + IntoBits<Output = Bits<T>>,
{
raw_iter: FilterMap<Enumerate<BitsIter<T>>, fn((usize, Bit<T>)) -> Option<Pos>>,
}
impl<T, Pos> Iterator for BitMapIter<T, Pos>
where
Bits<T>: BitsOps<T>,
Pos: Into<u32> + TryFrom<u32>,
T: Sized + IntoBits<Output = Bits<T>>,
{
type Item = Pos;
fn next(&mut self) -> Option<Self::Item> {
self.raw_iter.next()
}
}
impl<T, Pos> IntoIterator for BitMap<T, Pos>
where
Bits<T>: BitsOps<T>,
Pos: Into<u32> + TryFrom<u32>,
T: Sized + IntoBits<Output = Bits<T>>,
{
type Item = Pos;
type IntoIter = BitMapIter<T, Pos>;
fn into_iter(self) -> Self::IntoIter {
BitMapIter {
raw_iter: self
.raw
.bits(..)
.into_iter()
.enumerate()
.filter_map(|(pos, bit)| {
if bit.is_clr() {
return None;
}
if let Ok(output) = (pos as u32).try_into() {
Some(output)
} else {
None
}
}),
}
}
}