bitflags/iter.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
/*!
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<B: 'static> {
inner: IterNames<B>,
done: bool,
}
impl<B: Flags> Iter<B> {
pub(crate) fn new(flags: &B) -> Self {
Iter {
inner: IterNames::new(flags),
done: false,
}
}
}
impl<B: 'static> Iter<B> {
// Used by the `bitflags` macro
#[doc(hidden)]
pub const fn __private_const_new(flags: &'static [Flag<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;
// 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<B: 'static> {
flags: &'static [Flag<B>],
idx: usize,
source: B,
remaining: B,
}
impl<B: Flags> IterNames<B> {
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<B: 'static> IterNames<B> {
// Used by the bitflags macro
#[doc(hidden)]
pub const fn __private_const_new(flags: &'static [Flag<B>], 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<B: Flags> Iterator for IterNames<B> {
type Item = (&'static str, B);
fn next(&mut self) -> Option<Self::Item> {
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
}
}