use core::iter::FusedIterator;
use super::Flags;
pub struct IterNames<B: 'static> {
flags: &'static [(&'static str, B)],
index: usize,
source: B,
remaining: B,
}
impl<B: Flags> IterNames<B> {
pub(crate) fn new(flags: &B) -> Self {
Self {
flags: B::KNOWN_FLAGS,
index: 0,
source: B::from_bits_retain(flags.bits()),
remaining: B::from_bits_retain(flags.bits()),
}
}
}
impl<B: 'static> IterNames<B> {
pub const fn remaining(&self) -> &B {
&self.remaining
}
#[doc(hidden)]
pub const fn __private_const_new(
flags: &'static [(&'static str, B)],
source: B,
remaining: B,
) -> Self {
IterNames {
flags,
index: 0,
remaining,
source,
}
}
}
impl<B: Flags> Iterator for IterNames<B> {
type Item = (&'static str, B);
fn next(&mut self) -> Option<Self::Item> {
while let Some((name, flag)) = self.flags.get(self.index) {
if self.remaining.is_empty() {
return None;
}
self.index += 1;
if self.source.contains(*flag) && self.remaining.intersects(*flag) {
self.remaining.unset(*flag);
return Some((name, B::from_bits_retain(flag.bits())));
}
}
None
}
}
impl<B: Flags> FusedIterator for IterNames<B> {}
pub struct Iter<B: 'static> {
inner: IterNames<B>,
done: bool,
}
impl<B: Flags> Iter<B> {
pub fn new(flags: &B) -> Self {
Self {
inner: IterNames::new(flags),
done: false,
}
}
}
impl<B: 'static> Iter<B> {
#[doc(hidden)]
pub const fn __private_const_new(
flags: &'static [(&'static str, B)],
source: B,
remaining: B,
) -> Self {
Iter {
inner: IterNames::__private_const_new(flags, source, remaining),
done: false,
}
}
}
impl<B: Flags> Iterator for Iter<B> {
type Item = B;
fn next(&mut self) -> Option<Self::Item> {
match self.inner.next() {
Some((_, flag)) => Some(flag),
None if !self.done => {
self.done = true;
if !self.inner.remaining().is_empty() {
Some(self.inner.remaining)
} else {
None
}
}
None => None,
}
}
}
impl<B: Flags> FusedIterator for Iter<B> {}