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