/*! Yield the bits of a source flags value in a set of contained flags values. */ use crate::{Flag, Flags}; /** An iterator over flags values. This iterator will yield flags values for contained, defined flags first, with any remaining bits yielded as a final flags value. */ pub struct Iter { inner: IterNames, done: bool, } impl Iter { pub(crate) fn new(flags: &B) -> Self { Iter { inner: IterNames::new(flags), done: false, } } } impl Iter { // Used by the `bitflags` macro #[doc(hidden)] pub const fn __private_const_new(flags: &'static [Flag], source: B, remaining: B) -> Self { Iter { inner: IterNames::__private_const_new(flags, source, remaining), done: false, } } } impl Iterator for Iter { type Item = B; fn next(&mut self) -> Option { match self.inner.next() { Some((_, flag)) => Some(flag), None if !self.done => { self.done = true; // After iterating through valid names, if there are any bits left over // then return one final value that includes them. This makes `into_iter` // and `from_iter` roundtrip if !self.inner.remaining().is_empty() { Some(B::from_bits_retain(self.inner.remaining.bits())) } else { None } } None => None, } } } /** An iterator over flags values. This iterator only yields flags values for contained, defined, named flags. Any remaining bits won't be yielded, but can be found with the [`IterNames::remaining`] method. */ pub struct IterNames { flags: &'static [Flag], idx: usize, source: B, remaining: B, } impl IterNames { pub(crate) fn new(flags: &B) -> Self { IterNames { flags: B::FLAGS, idx: 0, remaining: B::from_bits_retain(flags.bits()), source: B::from_bits_retain(flags.bits()), } } } impl IterNames { // Used by the bitflags macro #[doc(hidden)] pub const fn __private_const_new(flags: &'static [Flag], source: B, remaining: B) -> Self { IterNames { flags, idx: 0, remaining, source, } } /// Get a flags value of any remaining bits that haven't been yielded yet. /// /// Once the iterator has finished, this method can be used to /// check whether or not there are any bits that didn't correspond /// to a contained, defined, named flag remaining. pub fn remaining(&self) -> &B { &self.remaining } } impl Iterator for IterNames { type Item = (&'static str, B); fn next(&mut self) -> Option { while let Some(flag) = self.flags.get(self.idx) { // Short-circuit if our state is empty if self.remaining.is_empty() { return None; } self.idx += 1; // Skip unnamed flags if flag.name().is_empty() { continue; } let bits = flag.value().bits(); // If the flag is set in the original source _and_ it has bits that haven't // been covered by a previous flag yet then yield it. These conditions cover // two cases for multi-bit flags: // // 1. When flags partially overlap, such as `0b00000001` and `0b00000101`, we'll // yield both flags. // 2. When flags fully overlap, such as in convenience flags that are a shorthand for others, // we won't yield both flags. if self.source.contains(B::from_bits_retain(bits)) && self.remaining.intersects(B::from_bits_retain(bits)) { self.remaining.remove(B::from_bits_retain(bits)); return Some((flag.name(), B::from_bits_retain(bits))); } } None } }