1 /*!
2 Yield the bits of a source flags value in a set of contained flags values.
3 */
4 
5 use crate::{Flag, Flags};
6 
7 /**
8 An iterator over flags values.
9 
10 This iterator will yield flags values for contained, defined flags first, with any remaining bits yielded
11 as a final flags value.
12 */
13 pub struct Iter<B: 'static> {
14     inner: IterNames<B>,
15     done: bool,
16 }
17 
18 impl<B: Flags> Iter<B> {
new(flags: &B) -> Self19     pub(crate) fn new(flags: &B) -> Self {
20         Iter {
21             inner: IterNames::new(flags),
22             done: false,
23         }
24     }
25 }
26 
27 impl<B: 'static> Iter<B> {
28     // Used by the `bitflags` macro
29     #[doc(hidden)]
__private_const_new(flags: &'static [Flag<B>], source: B, remaining: B) -> Self30     pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, remaining: B) -> Self {
31         Iter {
32             inner: IterNames::__private_const_new(flags, source, remaining),
33             done: false,
34         }
35     }
36 }
37 
38 impl<B: Flags> Iterator for Iter<B> {
39     type Item = B;
40 
next(&mut self) -> Option<Self::Item>41     fn next(&mut self) -> Option<Self::Item> {
42         match self.inner.next() {
43             Some((_, flag)) => Some(flag),
44             None if !self.done => {
45                 self.done = true;
46 
47                 // After iterating through valid names, if there are any bits left over
48                 // then return one final value that includes them. This makes `into_iter`
49                 // and `from_iter` roundtrip
50                 if !self.inner.remaining().is_empty() {
51                     Some(B::from_bits_retain(self.inner.remaining.bits()))
52                 } else {
53                     None
54                 }
55             }
56             None => None,
57         }
58     }
59 }
60 
61 /**
62 An iterator over flags values.
63 
64 This iterator only yields flags values for contained, defined, named flags. Any remaining bits
65 won't be yielded, but can be found with the [`IterNames::remaining`] method.
66 */
67 pub struct IterNames<B: 'static> {
68     flags: &'static [Flag<B>],
69     idx: usize,
70     source: B,
71     remaining: B,
72 }
73 
74 impl<B: Flags> IterNames<B> {
new(flags: &B) -> Self75     pub(crate) fn new(flags: &B) -> Self {
76         IterNames {
77             flags: B::FLAGS,
78             idx: 0,
79             remaining: B::from_bits_retain(flags.bits()),
80             source: B::from_bits_retain(flags.bits()),
81         }
82     }
83 }
84 
85 impl<B: 'static> IterNames<B> {
86     // Used by the bitflags macro
87     #[doc(hidden)]
__private_const_new(flags: &'static [Flag<B>], source: B, remaining: B) -> Self88     pub const fn __private_const_new(flags: &'static [Flag<B>], source: B, remaining: B) -> Self {
89         IterNames {
90             flags,
91             idx: 0,
92             remaining,
93             source,
94         }
95     }
96 
97     /// Get a flags value of any remaining bits that haven't been yielded yet.
98     ///
99     /// Once the iterator has finished, this method can be used to
100     /// check whether or not there are any bits that didn't correspond
101     /// to a contained, defined, named flag remaining.
remaining(&self) -> &B102     pub fn remaining(&self) -> &B {
103         &self.remaining
104     }
105 }
106 
107 impl<B: Flags> Iterator for IterNames<B> {
108     type Item = (&'static str, B);
109 
next(&mut self) -> Option<Self::Item>110     fn next(&mut self) -> Option<Self::Item> {
111         while let Some(flag) = self.flags.get(self.idx) {
112             // Short-circuit if our state is empty
113             if self.remaining.is_empty() {
114                 return None;
115             }
116 
117             self.idx += 1;
118 
119             // Skip unnamed flags
120             if flag.name().is_empty() {
121                 continue;
122             }
123 
124             let bits = flag.value().bits();
125 
126             // If the flag is set in the original source _and_ it has bits that haven't
127             // been covered by a previous flag yet then yield it. These conditions cover
128             // two cases for multi-bit flags:
129             //
130             // 1. When flags partially overlap, such as `0b00000001` and `0b00000101`, we'll
131             // yield both flags.
132             // 2. When flags fully overlap, such as in convenience flags that are a shorthand for others,
133             // we won't yield both flags.
134             if self.source.contains(B::from_bits_retain(bits))
135                 && self.remaining.intersects(B::from_bits_retain(bits))
136             {
137                 self.remaining.remove(B::from_bits_retain(bits));
138 
139                 return Some((flag.name(), B::from_bits_retain(bits)));
140             }
141         }
142 
143         None
144     }
145 }
146