#
bitflags/
iter.rs

    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)) => 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
    147/**
    148An iterator over all defined named flags.
    149
    150This iterator will yield flags values for all defined named flags, regardless of
    151whether they are contained in a particular flags value.
    152*/
    153pub struct IterDefinedNames<B: 'static> {
    154    flags: &'static [Flag<B>],
    155    idx: usize,
    156}
    157
    158impl<B: Flags> IterDefinedNames<B> {
    159    pub(crate) fn new() -> Self {
    160        IterDefinedNames {
    161            flags: B::FLAGS,
    162            idx: 0,
    163        }
    164    }
    165}
    166
    167impl<B: Flags> Iterator for IterDefinedNames<B> {
    168    type Item = (&'static str, B);
    169
    170    fn next(&mut self) -> Option<Self::Item> {
    171        while let Some(flag) = self.flags.get(self.idx) {
    172            self.idx += 1;
    173
    174            // Only yield named flags
    175            if flag.is_named() {
    176                return Some((flag.name(), B::from_bits_retain(flag.value().bits())));
    177            }
    178        }
    179
    180        None
    181    }
    182}