| 1 | use crate::{BitFlag, BitFlags, BitFlagNum}; |
| 2 | use core::iter::{FromIterator, FusedIterator}; |
| 3 | |
| 4 | impl<T> BitFlags<T> |
| 5 | where |
| 6 | T: BitFlag, |
| 7 | { |
| 8 | /// Iterate over the `BitFlags`. |
| 9 | /// |
| 10 | /// ``` |
| 11 | /// # use enumflags2::{bitflags, make_bitflags}; |
| 12 | /// # #[bitflags] |
| 13 | /// # #[derive(Clone, Copy, PartialEq, Debug)] |
| 14 | /// # #[repr (u8)] |
| 15 | /// # enum MyFlag { |
| 16 | /// # A = 1 << 0, |
| 17 | /// # B = 1 << 1, |
| 18 | /// # C = 1 << 2, |
| 19 | /// # } |
| 20 | /// let flags = make_bitflags!(MyFlag::{A | C}); |
| 21 | /// |
| 22 | /// flags.iter() |
| 23 | /// .for_each(|flag| println!("{:?}" , flag)); |
| 24 | /// ``` |
| 25 | #[inline ] |
| 26 | pub fn iter(self) -> Iter<T> { |
| 27 | Iter { rest: self } |
| 28 | } |
| 29 | } |
| 30 | |
| 31 | impl<T: BitFlag> IntoIterator for BitFlags<T> { |
| 32 | type IntoIter = Iter<T>; |
| 33 | type Item = T; |
| 34 | |
| 35 | fn into_iter(self) -> Self::IntoIter { |
| 36 | self.iter() |
| 37 | } |
| 38 | } |
| 39 | |
| 40 | /// Iterator that yields each flag set in a `BitFlags`. |
| 41 | #[derive (Clone, Debug)] |
| 42 | pub struct Iter<T: BitFlag> { |
| 43 | rest: BitFlags<T>, |
| 44 | } |
| 45 | |
| 46 | impl<T> Iterator for Iter<T> |
| 47 | where |
| 48 | T: BitFlag, |
| 49 | { |
| 50 | type Item = T; |
| 51 | |
| 52 | fn next(&mut self) -> Option<Self::Item> { |
| 53 | if self.rest.is_empty() { |
| 54 | None |
| 55 | } else { |
| 56 | // SAFETY: `flag` will be a single bit, because |
| 57 | // x & -x = x & (~x + 1), and the increment causes only one 0 -> 1 transition. |
| 58 | // The invariant of `from_bits_unchecked` is satisfied, because bits & x |
| 59 | // is a subset of bits, which we know are the valid bits. |
| 60 | unsafe { |
| 61 | let bits = self.rest.bits(); |
| 62 | let flag: T::Numeric = bits & bits.wrapping_neg(); |
| 63 | let flag: T = core::mem::transmute_copy(&flag); |
| 64 | self.rest = BitFlags::from_bits_unchecked(bits & (bits - BitFlagNum::ONE)); |
| 65 | Some(flag) |
| 66 | } |
| 67 | } |
| 68 | } |
| 69 | |
| 70 | fn size_hint(&self) -> (usize, Option<usize>) { |
| 71 | let l = self.rest.len(); |
| 72 | (l, Some(l)) |
| 73 | } |
| 74 | } |
| 75 | |
| 76 | impl<T> ExactSizeIterator for Iter<T> |
| 77 | where |
| 78 | T: BitFlag, |
| 79 | { |
| 80 | fn len(&self) -> usize { |
| 81 | self.rest.len() |
| 82 | } |
| 83 | } |
| 84 | |
| 85 | impl<T: BitFlag> FusedIterator for Iter<T> {} |
| 86 | |
| 87 | impl<T, B> FromIterator<B> for BitFlags<T> |
| 88 | where |
| 89 | T: BitFlag, |
| 90 | B: Into<BitFlags<T>>, |
| 91 | { |
| 92 | #[inline ] |
| 93 | fn from_iter<I>(it: I) -> BitFlags<T> |
| 94 | where |
| 95 | I: IntoIterator<Item = B>, |
| 96 | { |
| 97 | it.into_iter() |
| 98 | .fold(init:BitFlags::empty(), |acc: BitFlags::Numeric>, flag: B| acc | flag) |
| 99 | } |
| 100 | } |
| 101 | |
| 102 | impl<T, B> Extend<B> for BitFlags<T> |
| 103 | where |
| 104 | T: BitFlag, |
| 105 | B: Into<BitFlags<T>>, |
| 106 | { |
| 107 | #[inline ] |
| 108 | fn extend<I>(&mut self, it: I) |
| 109 | where |
| 110 | I: IntoIterator<Item = B>, |
| 111 | { |
| 112 | *self = it.into_iter().fold(*self, |acc: BitFlags::Numeric>, flag: B| acc | flag) |
| 113 | } |
| 114 | } |
| 115 | |