bitflags/
traits.rs

1use core::{
2    fmt,
3    ops::{BitAnd, BitOr, BitXor, Not},
4};
5
6use crate::{
7    iter,
8    parser::{ParseError, ParseHex, WriteHex},
9};
10
11/**
12A defined flags value that may be named or unnamed.
13*/
14pub struct Flag<B> {
15    name: &'static str,
16    value: B,
17}
18
19impl<B> Flag<B> {
20    /**
21    Define a flag.
22
23    If `name` is non-empty then the flag is named, otherwise it's unnamed.
24    */
25    pub const fn new(name: &'static str, value: B) -> Self {
26        Flag { name, value }
27    }
28
29    /**
30    Get the name of this flag.
31
32    If the flag is unnamed then the returned string will be empty.
33    */
34    pub const fn name(&self) -> &'static str {
35        self.name
36    }
37
38    /**
39    Get the flags value of this flag.
40    */
41    pub const fn value(&self) -> &B {
42        &self.value
43    }
44
45    /**
46    Whether the flag is named.
47
48    If [`Flag::name`] returns a non-empty string then this method will return `true`.
49    */
50    pub const fn is_named(&self) -> bool {
51        !self.name.is_empty()
52    }
53
54    /**
55    Whether the flag is unnamed.
56
57    If [`Flag::name`] returns a non-empty string then this method will return `false`.
58    */
59    pub const fn is_unnamed(&self) -> bool {
60        self.name.is_empty()
61    }
62}
63
64/**
65A set of defined flags using a bits type as storage.
66
67## Implementing `Flags`
68
69This trait is implemented by the [`bitflags`](macro.bitflags.html) macro:
70
71```
72use bitflags::bitflags;
73
74bitflags! {
75    struct MyFlags: u8 {
76        const A = 1;
77        const B = 1 << 1;
78    }
79}
80```
81
82It can also be implemented manually:
83
84```
85use bitflags::{Flag, Flags};
86
87struct MyFlags(u8);
88
89impl Flags for MyFlags {
90    const FLAGS: &'static [Flag<Self>] = &[
91        Flag::new("A", MyFlags(1)),
92        Flag::new("B", MyFlags(1 << 1)),
93    ];
94
95    type Bits = u8;
96
97    fn from_bits_retain(bits: Self::Bits) -> Self {
98        MyFlags(bits)
99    }
100
101    fn bits(&self) -> Self::Bits {
102        self.0
103    }
104}
105```
106
107## Using `Flags`
108
109The `Flags` trait can be used generically to work with any flags types. In this example,
110we can count the number of defined named flags:
111
112```
113# use bitflags::{bitflags, Flags};
114fn defined_flags<F: Flags>() -> usize {
115    F::FLAGS.iter().filter(|f| f.is_named()).count()
116}
117
118bitflags! {
119    struct MyFlags: u8 {
120        const A = 1;
121        const B = 1 << 1;
122        const C = 1 << 2;
123
124        const _ = !0;
125    }
126}
127
128assert_eq!(3, defined_flags::<MyFlags>());
129```
130*/
131pub trait Flags: Sized + 'static {
132    /// The set of defined flags.
133    const FLAGS: &'static [Flag<Self>];
134
135    /// The underlying bits type.
136    type Bits: Bits;
137
138    /// Get a flags value with all bits unset.
139    fn empty() -> Self {
140        Self::from_bits_retain(Self::Bits::EMPTY)
141    }
142
143    /// Get a flags value with all known bits set.
144    fn all() -> Self {
145        let mut truncated = Self::Bits::EMPTY;
146
147        for flag in Self::FLAGS.iter() {
148            truncated = truncated | flag.value().bits();
149        }
150
151        Self::from_bits_retain(truncated)
152    }
153
154    /// Get the underlying bits value.
155    ///
156    /// The returned value is exactly the bits set in this flags value.
157    fn bits(&self) -> Self::Bits;
158
159    /// Convert from a bits value.
160    ///
161    /// This method will return `None` if any unknown bits are set.
162    fn from_bits(bits: Self::Bits) -> Option<Self> {
163        let truncated = Self::from_bits_truncate(bits);
164
165        if truncated.bits() == bits {
166            Some(truncated)
167        } else {
168            None
169        }
170    }
171
172    /// Convert from a bits value, unsetting any unknown bits.
173    fn from_bits_truncate(bits: Self::Bits) -> Self {
174        Self::from_bits_retain(bits & Self::all().bits())
175    }
176
177    /// Convert from a bits value exactly.
178    fn from_bits_retain(bits: Self::Bits) -> Self;
179
180    /// Get a flags value with the bits of a flag with the given name set.
181    ///
182    /// This method will return `None` if `name` is empty or doesn't
183    /// correspond to any named flag.
184    fn from_name(name: &str) -> Option<Self> {
185        // Don't parse empty names as empty flags
186        if name.is_empty() {
187            return None;
188        }
189
190        for flag in Self::FLAGS {
191            if flag.name() == name {
192                return Some(Self::from_bits_retain(flag.value().bits()));
193            }
194        }
195
196        None
197    }
198
199    /// Yield a set of contained flags values.
200    ///
201    /// Each yielded flags value will correspond to a defined named flag. Any unknown bits
202    /// will be yielded together as a final flags value.
203    fn iter(&self) -> iter::Iter<Self> {
204        iter::Iter::new(self)
205    }
206
207    /// Yield a set of contained named flags values.
208    ///
209    /// This method is like [`Flags::iter`], except only yields bits in contained named flags.
210    /// Any unknown bits, or bits not corresponding to a contained flag will not be yielded.
211    fn iter_names(&self) -> iter::IterNames<Self> {
212        iter::IterNames::new(self)
213    }
214
215    /// Whether all bits in this flags value are unset.
216    fn is_empty(&self) -> bool {
217        self.bits() == Self::Bits::EMPTY
218    }
219
220    /// Whether all known bits in this flags value are set.
221    fn is_all(&self) -> bool {
222        // NOTE: We check against `Self::all` here, not `Self::Bits::ALL`
223        // because the set of all flags may not use all bits
224        Self::all().bits() | self.bits() == self.bits()
225    }
226
227    /// Whether any set bits in a source flags value are also set in a target flags value.
228    fn intersects(&self, other: Self) -> bool
229    where
230        Self: Sized,
231    {
232        self.bits() & other.bits() != Self::Bits::EMPTY
233    }
234
235    /// Whether all set bits in a source flags value are also set in a target flags value.
236    fn contains(&self, other: Self) -> bool
237    where
238        Self: Sized,
239    {
240        self.bits() & other.bits() == other.bits()
241    }
242
243    /// The bitwise or (`|`) of the bits in two flags values.
244    fn insert(&mut self, other: Self)
245    where
246        Self: Sized,
247    {
248        *self = Self::from_bits_retain(self.bits()).union(other);
249    }
250
251    /// The intersection of a source flags value with the complement of a target flags value (`&!`).
252    ///
253    /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
254    /// `remove` won't truncate `other`, but the `!` operator will.
255    fn remove(&mut self, other: Self)
256    where
257        Self: Sized,
258    {
259        *self = Self::from_bits_retain(self.bits()).difference(other);
260    }
261
262    /// The bitwise exclusive-or (`^`) of the bits in two flags values.
263    fn toggle(&mut self, other: Self)
264    where
265        Self: Sized,
266    {
267        *self = Self::from_bits_retain(self.bits()).symmetric_difference(other);
268    }
269
270    /// Call [`Flags::insert`] when `value` is `true` or [`Flags::remove`] when `value` is `false`.
271    fn set(&mut self, other: Self, value: bool)
272    where
273        Self: Sized,
274    {
275        if value {
276            self.insert(other);
277        } else {
278            self.remove(other);
279        }
280    }
281
282    /// The bitwise and (`&`) of the bits in two flags values.
283    #[must_use]
284    fn intersection(self, other: Self) -> Self {
285        Self::from_bits_retain(self.bits() & other.bits())
286    }
287
288    /// The bitwise or (`|`) of the bits in two flags values.
289    #[must_use]
290    fn union(self, other: Self) -> Self {
291        Self::from_bits_retain(self.bits() | other.bits())
292    }
293
294    /// The intersection of a source flags value with the complement of a target flags value (`&!`).
295    ///
296    /// This method is not equivalent to `self & !other` when `other` has unknown bits set.
297    /// `difference` won't truncate `other`, but the `!` operator will.
298    #[must_use]
299    fn difference(self, other: Self) -> Self {
300        Self::from_bits_retain(self.bits() & !other.bits())
301    }
302
303    /// The bitwise exclusive-or (`^`) of the bits in two flags values.
304    #[must_use]
305    fn symmetric_difference(self, other: Self) -> Self {
306        Self::from_bits_retain(self.bits() ^ other.bits())
307    }
308
309    /// The bitwise negation (`!`) of the bits in a flags value, truncating the result.
310    #[must_use]
311    fn complement(self) -> Self {
312        Self::from_bits_truncate(!self.bits())
313    }
314}
315
316/**
317A bits type that can be used as storage for a flags type.
318*/
319pub trait Bits:
320    Clone
321    + Copy
322    + PartialEq
323    + BitAnd<Output = Self>
324    + BitOr<Output = Self>
325    + BitXor<Output = Self>
326    + Not<Output = Self>
327    + Sized
328    + 'static
329{
330    /// A value with all bits unset.
331    const EMPTY: Self;
332
333    /// A value with all bits set.
334    const ALL: Self;
335}
336
337// Not re-exported: prevent custom `Bits` impls being used in the `bitflags!` macro,
338// or they may fail to compile based on crate features
339pub trait Primitive {}
340
341macro_rules! impl_bits {
342    ($($u:ty, $i:ty,)*) => {
343        $(
344            impl Bits for $u {
345                const EMPTY: $u = 0;
346                const ALL: $u = <$u>::MAX;
347            }
348
349            impl Bits for $i {
350                const EMPTY: $i = 0;
351                const ALL: $i = <$u>::MAX as $i;
352            }
353
354            impl ParseHex for $u {
355                fn parse_hex(input: &str) -> Result<Self, ParseError> {
356                    <$u>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input))
357                }
358            }
359
360            impl ParseHex for $i {
361                fn parse_hex(input: &str) -> Result<Self, ParseError> {
362                    <$i>::from_str_radix(input, 16).map_err(|_| ParseError::invalid_hex_flag(input))
363                }
364            }
365
366            impl WriteHex for $u {
367                fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result {
368                    write!(writer, "{:x}", self)
369                }
370            }
371
372            impl WriteHex for $i {
373                fn write_hex<W: fmt::Write>(&self, mut writer: W) -> fmt::Result {
374                    write!(writer, "{:x}", self)
375                }
376            }
377
378            impl Primitive for $i {}
379            impl Primitive for $u {}
380        )*
381    }
382}
383
384impl_bits! {
385    u8, i8,
386    u16, i16,
387    u32, i32,
388    u64, i64,
389    u128, i128,
390    usize, isize,
391}
392
393/// A trait for referencing the `bitflags`-owned internal type
394/// without exposing it publicly.
395pub trait PublicFlags {
396    /// The type of the underlying storage.
397    type Primitive: Primitive;
398
399    /// The type of the internal field on the generated flags type.
400    type Internal;
401}
402
403#[doc(hidden)]
404#[deprecated(note = "use the `Flags` trait instead")]
405pub trait BitFlags: ImplementedByBitFlagsMacro + Flags {
406    /// An iterator over enabled flags in an instance of the type.
407    type Iter: Iterator<Item = Self>;
408
409    /// An iterator over the raw names and bits for enabled flags in an instance of the type.
410    type IterNames: Iterator<Item = (&'static str, Self)>;
411}
412
413#[allow(deprecated)]
414impl<B: Flags> BitFlags for B {
415    type Iter = iter::Iter<Self>;
416    type IterNames = iter::IterNames<Self>;
417}
418
419impl<B: Flags> ImplementedByBitFlagsMacro for B {}
420
421/// A marker trait that signals that an implementation of `BitFlags` came from the `bitflags!` macro.
422///
423/// There's nothing stopping an end-user from implementing this trait, but we don't guarantee their
424/// manual implementations won't break between non-breaking releases.
425#[doc(hidden)]
426pub trait ImplementedByBitFlagsMacro {}
427
428pub(crate) mod __private {
429    pub use super::{ImplementedByBitFlagsMacro, PublicFlags};
430}