1/*!
2Yield the bits of a source flags value in a set of contained flags values.
3*/
4
5use crate::{Flag, Flags};
6
7/**
8An iterator over flags values.
9
10This iterator will yield flags values for contained, defined flags first, with any remaining bits yielded
11as a final flags value.
12*/
13pub struct Iter<B: 'static> {
14 inner: IterNames<B>,
15 done: bool,
16}
17
18impl<B: Flags> Iter<B> {
19 pub(crate) fn new(flags: &B) -> Self {
20 Iter {
21 inner: IterNames::new(flags),
22 done: false,
23 }
24 }
25}
26
27impl<B: 'static> Iter<B> {
28 // Used by the `bitflags` macro
29 #[doc(hidden)]
30 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
38impl<B: Flags> Iterator for Iter<B> {
39 type Item = B;
40
41 fn next(&mut self) -> Option<Self::Item> {
42 match self.inner.next() {
43 Some((_, flag: B)) => 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/**
62An iterator over flags values.
63
64This iterator only yields flags values for contained, defined, named flags. Any remaining bits
65won't be yielded, but can be found with the [`IterNames::remaining`] method.
66*/
67pub struct IterNames<B: 'static> {
68 flags: &'static [Flag<B>],
69 idx: usize,
70 source: B,
71 remaining: B,
72}
73
74impl<B: Flags> IterNames<B> {
75 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
85impl<B: 'static> IterNames<B> {
86 // Used by the bitflags macro
87 #[doc(hidden)]
88 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.
102 pub fn remaining(&self) -> &B {
103 &self.remaining
104 }
105}
106
107impl<B: Flags> Iterator for IterNames<B> {
108 type Item = (&'static str, B);
109
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