Skip to main content

bitflags_lite/
flags.rs

1use core::any::type_name;
2use core::borrow::Borrow;
3use core::cmp::Ordering;
4use core::fmt;
5use core::hash::{Hash, Hasher};
6use core::iter::{FromIterator, IntoIterator};
7use core::marker::PhantomData;
8use core::ops::{
9    BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Shl, Sub, SubAssign,
10};
11use core::str::FromStr;
12
13use crate::{BitFlag, BitFlagsIter, BitFlagsSpec, NameMatcher, util};
14
15/// A type-safe set of flags stored in an integer `T`.
16///
17/// The second type parameter `U` is a tag type that distinguishes flag sets
18/// that share the same storage type.
19/// When `U` implements `BitFlagsSpec`, it defines which bits are valid.
20///
21/// `BitFlags` is `#[repr(transparent)]` over `T`, so it has the same layout as
22/// `T`.
23///
24/// # Invalid bits
25///
26/// A `BitFlags` value is not guaranteed to contain only valid bits.
27/// [`BitFlags::from_bits_retain`] can create a value with any bit pattern of
28/// `T`, and raw-bit operations such as [`BitFlags::insert`],
29/// [`BitFlags::toggle`], [`BitFlags::union`], and bitwise operators preserve
30/// invalid bits. Use [`BitFlags::truncate`], [`BitFlags::try_from_bits`], or
31/// [`BitFlags::from_bits_truncate`] when a value must be restricted to
32/// [`BitFlagsSpec::VALID_BITS_MASK`].
33///
34/// [`BitFlags::bits`] returns the raw stored bits, including any invalid bits
35/// that are present.
36///
37/// # Examples
38///
39/// ```
40/// use bitflags_lite::{BitFlags, BitFlagsSpec, NameMatcher};
41///
42/// struct PermissionsTag;
43///
44/// impl BitFlagsSpec<u32> for PermissionsTag {
45///     const VALID_BITS_MASK: u32 = (1 << 3) - 1;
46///     const FLAG_NAMES: &[&[&str]] = &[&["read"], &["write"], &["exec", "execute"]];
47///     const DEFAULT_NAME_MATCHER: NameMatcher = NameMatcher::Exact;
48/// }
49///
50/// type Permissions = BitFlags<u32, PermissionsTag>;
51///
52/// const READ: Permissions = Permissions::try_from_bits(1 << 0).unwrap();
53/// const WRITE: Permissions = Permissions::try_from_bits(1 << 1).unwrap();
54/// const EXEC: Permissions = Permissions::try_from_bits(1 << 2).unwrap();
55///
56/// let rw = READ | WRITE;
57/// assert!(rw.contains(READ));
58/// assert!(rw.contains(WRITE));
59/// assert!(!rw.contains(EXEC));
60/// ```
61///
62/// # Method summary
63///
64/// - [`empty()`](Self::empty): Return a set with no bits set.
65/// - [`all_valid()`](Self::all_valid): Return a set with all valid bits set.
66/// - [`from_bits_retain()`](Self::from_bits_retain): Convert from raw bits
67///   without validation.
68/// - [`from_bits_truncate()`](Self::from_bits_truncate): Convert from raw bits,
69///   clearing invalid bits.
70/// - [`try_from_bits()`](Self::try_from_bits): Convert from raw bits, rejecting
71///   invalid bits.
72/// - [`from_bit_retain()`](Self::from_bit_retain): Return a set with only the
73///   bit at a given index, without validation.
74/// - [`from_bit_truncate()`](Self::from_bit_truncate): Return a set with only
75///   the bit at a given index, clearing it if invalid.
76/// - [`try_from_bit()`](Self::try_from_bit): Return a set with only the bit at
77///   a given index, rejecting it if invalid.
78/// - [`from_flag()`](Self::from_flag): Convert from a single [`BitFlag`].
79/// - [`try_from_str()`](Self::try_from_str): Parse from a separated string.
80/// - [`bits()`](Self::bits): Return the raw stored bits.
81/// - [`bits_mut()`](Self::bits_mut): Return a mutable reference to the raw
82///   bits.
83/// - [`into_bits()`](Self::into_bits): Consume the set and return the raw bits.
84/// - [`iter()`](Self::iter): Return an iterator over the set bits.
85/// - [`is_empty()`](Self::is_empty): Return `true` if no bits are set.
86/// - [`is_valid()`](Self::is_valid): Return `true` if all set bits are valid
87///   for the tag.
88/// - [`intersects()`](Self::intersects): Return `true` if any bits are shared.
89/// - [`contains()`](Self::contains): Return `true` if all bits of another set
90///   are present.
91/// - [`insert()`](Self::insert): Add all bits of another set.
92/// - [`remove()`](Self::remove): Remove all bits of another set.
93/// - [`toggle()`](Self::toggle): Flip all bits of another set.
94/// - [`set()`](Self::set): Insert or remove bits based on a boolean.
95/// - [`clear()`](Self::clear): Remove all bits, valid and invalid.
96/// - [`truncate()`](Self::truncate): Remove all invalid bits.
97/// - [`intersection()`](Self::intersection): Return the bits set in both sets.
98/// - [`union()`](Self::union): Return the bits set in either set.
99/// - [`difference()`](Self::difference): Return the bits set in `self` but not
100///   in `other`.
101/// - [`symmetric_difference()`](Self::symmetric_difference): Return the bits
102///   set in exactly one set.
103/// - [`complement()`](Self::complement): Return the valid bits not set in
104///   `self`.
105#[repr(transparent)]
106pub struct BitFlags<T, U>(
107    T,
108    // PhantomData<fn() -> *const U> is Send + Sync and covariant over `U`,
109    // and `U` is not required to be sized as pattern uses only its pointer.
110    // See: https://doc.rust-lang.org/nomicon/phantom-data.html#table-of-phantomdata-patterns
111    PhantomData<fn() -> *const U>,
112)
113where
114    U: ?Sized;
115
116/// Serde visitor for deserializing [`BitFlags`] from a string.
117///
118/// The accepted format is the same as [`BitFlags`]'s
119/// [`FromStr`](core::str::FromStr) implementation: an empty string, a
120/// `|`-separated list of named flags, and/or `0x`-prefixed hexadecimal flags.
121/// Named flags are matched according to
122/// [`BitFlagsSpec::DEFAULT_NAME_MATCHER`].
123///
124/// Deserialization does not validate the parsed bits against
125/// [`BitFlagsSpec::VALID_BITS_MASK`].
126/// The resulting value may contain invalid bits.
127#[cfg(feature = "serde")]
128struct BitFlagsVisitor<T, U>(PhantomData<T>, PhantomData<fn() -> *const U>)
129where
130    U: ?Sized;
131
132impl<T, U> BitFlags<T, U>
133where
134    U: ?Sized,
135{
136    /// Creates a flag set with no bits set (zero bits).
137    ///
138    /// This is equivalent to `from_bits_retain(0)`.
139    #[inline]
140    #[must_use]
141    pub const fn empty() -> Self
142    where
143        T: util::IntOpsExt,
144    {
145        Self(T::ZERO, PhantomData)
146    }
147
148    /// Creates a flag set containing all valid bits for this tag.
149    ///
150    /// This returns exactly [`BitFlagsSpec::VALID_BITS_MASK`]. Invalid bits
151    /// are never set.
152    ///
153    /// The method is named `all_valid` rather than `all` because a
154    /// `BitFlags` value can contain invalid bits after
155    /// [`BitFlags::from_bits_retain`].
156    /// In that case, "all" would be ambiguous: all bits of the storage
157    /// type, all bits currently set, or all valid bits?
158    ///
159    /// `all_valid` makes the meaning explicit.
160    #[doc(alias = "all")]
161    #[inline]
162    #[must_use]
163    pub const fn all_valid() -> Self
164    where
165        U: BitFlagsSpec<T>,
166    {
167        Self(U::VALID_BITS_MASK, PhantomData)
168    }
169
170    /// Creates a flag set from raw bits without validation.
171    ///
172    /// The resulting value may contain bits not present in
173    /// [`BitFlagsSpec::VALID_BITS_MASK`].
174    /// Such invalid bits are preserved by this constructor and by
175    /// raw-bit operations unless an operation clears them, such as
176    /// [`BitFlags::truncate`], [`BitFlags::complement`],
177    /// [`BitFlags::from_bits_truncate`], or [`Not`](core::ops::Not).
178    #[inline]
179    #[must_use]
180    pub const fn from_bits_retain(bits: T) -> Self {
181        Self(bits, PhantomData)
182    }
183
184    /// Returns the raw bits stored in this flag set.
185    ///
186    /// The returned value may contain invalid bits if this value was
187    /// created with [`BitFlags::from_bits_retain`] and has not since
188    /// been passed through an operation that clears invalid bits, such
189    /// as [`BitFlags::truncate`] or [`BitFlags::complement`].
190    #[inline]
191    #[must_use]
192    pub const fn bits(&self) -> T
193    where
194        T: Copy,
195    {
196        self.0
197    }
198
199    /// Returns a mutable reference to the raw bits stored in this flag set.
200    ///
201    /// Mutating the returned value can introduce invalid bits.
202    /// Use [`BitFlags::truncate`] afterwards if the value must contain only
203    /// valid bits.
204    #[inline]
205    #[must_use]
206    pub const fn bits_mut(&mut self) -> &mut T {
207        &mut self.0
208    }
209
210    /// Consumes this flag set and returns the raw bits.
211    ///
212    /// This is the consuming counterpart to [`BitFlags::bits`].
213    /// Like [`BitFlags::bits`], the returned value may contain bits not present
214    /// in [`BitFlagsSpec::VALID_BITS_MASK`].
215    ///
216    /// This method does not require `T: Copy`, so it is available for storage
217    /// types that are not `Copy`.
218    #[inline]
219    #[must_use]
220    pub fn into_bits(self) -> T {
221        self.0
222    }
223
224    /// Returns an iterator over the individual set bits in this flag set.
225    ///
226    /// The iterator yields [`BitFlag`] values from the least significant bit to
227    /// the most significant bit.
228    /// It includes invalid bits if they are present.
229    #[inline]
230    pub const fn iter(self) -> BitFlagsIter<T, U>
231    where
232        T: Copy + Not<Output = T> + BitAndAssign<T> + util::IntOpsExt,
233    {
234        BitFlagsIter::new(self)
235    }
236
237    /// Parses a flag set from a string.
238    ///
239    /// The input may be empty, which returns [`BitFlags::empty`].
240    /// Otherwise it is split on given `separator`, and each part is trimmed and
241    /// matched against the names in [`BitFlagsSpec::FLAG_NAMES`].
242    /// Match behavior is specified by `name_matcher`.
243    /// A part may also be a hexadecimal flag with a `0x` prefix.
244    ///
245    /// This method does not validate or truncate the parsed bits against
246    /// [`BitFlagsSpec::VALID_BITS_MASK`].
247    /// The returned value may contain invalid bits.
248    ///
249    /// Note that if `separator` is an empty string, the method would split into
250    /// individual characters, which is almost certainly not intended.
251    ///
252    /// # Errors
253    ///
254    /// Returns [`BitFlagsParseError`] if `input` is not a `separator`-separated
255    /// list of named flags or hexadecimal flags.
256    #[inline]
257    pub fn try_from_str(
258        input: &str,
259        separator: &'static str,
260        name_matcher: NameMatcher,
261    ) -> Result<Self, BitFlagsParseError>
262    where
263        T: BitOrAssign<T> + util::IntOpsExt,
264        U: BitFlagsSpec<T>,
265    {
266        if input.trim().is_empty() {
267            return Ok(Self::empty());
268        }
269
270        let mut this = Self::empty();
271        let input = input.split(separator);
272        for input in input {
273            let input = input.trim();
274
275            let flag = BitFlag::from_name_opt(input, name_matcher);
276            if let Some(flag) = flag {
277                this |= flag;
278                continue;
279            }
280
281            if let Some(maybe_hex_flag) = input.strip_prefix("0x") {
282                // `from_str_radix` allows optional `+` prefix.
283                // Parsing here should prohibit it.
284                if !maybe_hex_flag.starts_with('+') {
285                    let bits = T::from_str_radix(maybe_hex_flag, 16);
286                    if let Ok(bits) = bits {
287                        this |= Self::from_bits_retain(bits);
288                        continue;
289                    }
290                }
291            }
292
293            #[cfg(feature = "alloc")]
294            let given = alloc::string::ToString::to_string(input);
295            #[cfg(not(feature = "alloc"))]
296            let given = ();
297            let expected = U::FLAG_NAMES;
298            return Err(BitFlagsParseError {
299                given,
300                separator,
301                expected,
302            });
303        }
304
305        Ok(this)
306    }
307}
308
309// Const traits are not stable yet, so the const methods are implemented for
310// each integer type separately via a macro.
311// See: https://github.com/rust-lang/rust/issues/143874
312macro_rules! impl_bit_flags {
313    ($ty:ty) => {
314        impl<U> BitFlags<$ty, U>
315        where
316            U: ?Sized,
317        {
318            /// Creates a flag set from a single [`BitFlag`].
319            ///
320            /// The bit index is not validated against
321            /// [`BitFlagsSpec::VALID_BITS_MASK`].
322            /// The resulting value may contain an invalid bit.
323            ///
324            /// If the flag's index is outside the width of `T`, the result is
325            /// [`BitFlags::empty`].
326            #[inline]
327            #[must_use]
328            pub const fn from_flag(flag: BitFlag<$ty, U>) -> Self {
329                Self::from_bit_retain(flag.bit())
330            }
331
332            /// Creates a flag set with only the bit at index `bit` set.
333            ///
334            /// The bit index is not validated against
335            /// [`BitFlagsSpec::VALID_BITS_MASK`].
336            /// The resulting value may contain an invalid bit.
337            /// Use [`BitFlags::try_from_bit`] or
338            /// [`BitFlags::from_bits_truncate`] when validation or truncation
339            /// is required.
340            ///
341            /// If `bit` is outside the width of `T`, the result is
342            /// [`BitFlags::empty`].
343            #[inline]
344            #[must_use]
345            pub const fn from_bit_retain(bit: u8) -> Self {
346                #[expect(clippy::as_conversions, reason = "supported in const functions")]
347                let bit = bit as u32;
348                if bit < <$ty>::BITS {
349                    Self::from_bits_retain(1 << bit)
350                } else {
351                    Self::empty()
352                }
353            }
354
355            /// Creates a flag set with only the bit at index `bit` set,
356            /// clearing the bit if it is not valid for the tag.
357            ///
358            /// This is the bit-index counterpart to
359            /// [`BitFlags::from_bits_truncate`].
360            /// If `bit` is outside the width of `T`, or if the corresponding
361            /// bit is not present in [`BitFlagsSpec::VALID_BITS_MASK`], the
362            /// result is [`BitFlags::empty`].
363            ///
364            /// The result always contains either exactly one bit or no bits.
365            ///
366            /// Use [`BitFlags::try_from_bit`] when the caller needs to
367            /// distinguish a valid index from an invalid one.
368            #[inline]
369            #[must_use]
370            pub const fn from_bit_truncate(bit: u8) -> Self
371            where
372                U: BitFlagsSpec<$ty>,
373            {
374                #[expect(clippy::as_conversions, reason = "supported in const functions")]
375                let bit = bit as u32;
376                if bit < <$ty>::BITS {
377                    Self::from_bits_truncate(1 << bit)
378                } else {
379                    Self::empty()
380                }
381            }
382
383            /// Creates a flag set from bit index `bit` if that bit is valid.
384            ///
385            /// Returns `None` if `bit` is outside the width of `T` or if the
386            /// resulting bit is not present in
387            /// [`BitFlagsSpec::VALID_BITS_MASK`].
388            #[inline]
389            #[must_use]
390            pub const fn try_from_bit(bit: u8) -> Option<Self>
391            where
392                U: BitFlagsSpec<$ty>,
393            {
394                #[expect(clippy::as_conversions, reason = "supported in const functions")]
395                let bit = bit as u32;
396                if bit < <$ty>::BITS {
397                    Self::try_from_bits(1 << bit)
398                } else {
399                    None
400                }
401            }
402
403            /// Creates a flag set from raw bits if all set bits are valid.
404            ///
405            /// Returns `None` if `bits` contains any bit not present in
406            /// [`BitFlagsSpec::VALID_BITS_MASK`].
407            ///
408            /// Use [`BitFlags::from_bits_retain`] to keep invalid bits, or
409            /// [`BitFlags::from_bits_truncate`] to clear them.
410            #[doc(alias = "from_bits")]
411            #[inline]
412            #[must_use]
413            pub const fn try_from_bits(bits: $ty) -> Option<Self>
414            where
415                U: BitFlagsSpec<$ty>,
416            {
417                if bits & !U::VALID_BITS_MASK == 0 {
418                    Some(Self(bits, PhantomData))
419                } else {
420                    None
421                }
422            }
423
424            /// Creates a flag set from raw bits, clearing any bits not present in
425            /// [`BitFlagsSpec::VALID_BITS_MASK`].
426            ///
427            /// This always succeeds and never stores invalid bits.
428            #[inline]
429            #[must_use]
430            pub const fn from_bits_truncate(bits: $ty) -> Self
431            where
432                U: BitFlagsSpec<$ty>,
433            {
434                Self(bits & U::VALID_BITS_MASK, PhantomData)
435            }
436
437            /// Returns `true` if no bits are set.
438            ///
439            /// This checks the raw stored bits.
440            /// A value containing only invalid bits is not empty.
441            #[inline]
442            #[must_use]
443            pub const fn is_empty(&self) -> bool {
444                self.0 == 0
445            }
446
447            /// Returns `true` if all set bits in `self` are valid for this tag.
448            ///
449            /// A `BitFlags` value can contain bits not present in
450            /// [`BitFlagsSpec::VALID_BITS_MASK`] after construction with
451            /// [`BitFlags::from_bits_retain`] or after raw-bit operations such as
452            /// [`BitFlags::insert`], [`BitFlags::toggle`], and [`BitFlags::union`].
453            /// This method returns `false` for such values.
454            ///
455            /// Use [`BitFlags::truncate`] or [`BitFlags::from_bits_truncate`] to
456            /// restrict a value to its valid bits.
457            #[doc(alias = "is_all")]
458            #[inline]
459            #[must_use]
460            pub const fn is_valid(&self) -> bool
461            where
462                U: BitFlagsSpec<$ty>,
463            {
464                self.bits() & !U::VALID_BITS_MASK == 0
465            }
466
467            /// Returns `true` if `self` and `other` have at least one set bit in
468            /// common.
469            ///
470            /// This compares raw bits.
471            /// Invalid bits participate in the comparison if they are present.
472            #[inline]
473            #[must_use]
474            pub const fn intersects(&self, other: Self) -> bool {
475                (self.0 & other.0) != 0
476            }
477
478            /// Returns `true` if all bits set in `other` are also set in `self`.
479            ///
480            /// This compares raw bits.
481            /// Invalid bits participate in the comparison if they are present.
482            #[inline]
483            #[must_use]
484            pub const fn contains(&self, other: Self) -> bool {
485                (self.0 & other.0) == other.0
486            }
487
488            /// Inserts all bits from `other`.
489            ///
490            /// This is a raw-bit operation.
491            /// It does not validate or clear invalid bits.
492            /// Inserting `other` can introduce invalid bits into `self`.
493            #[inline]
494            pub const fn insert(&mut self, other: Self) {
495                self.0 |= other.0;
496            }
497
498            /// Removes all bits from `self`, including any invalid bits.
499            ///
500            /// This is equivalent to assigning [`BitFlags::empty`] to `self`.
501            #[inline]
502            pub const fn clear(&mut self) {
503                self.0 = 0;
504            }
505
506            /// Clears all bits not present in
507            /// [`BitFlagsSpec::VALID_BITS_MASK`].
508            ///
509            /// This leaves `self` unchanged if it already contains only valid
510            /// bits.
511            #[inline]
512            pub const fn truncate(&mut self)
513            where
514                U: BitFlagsSpec<$ty>,
515            {
516                self.0 &= U::VALID_BITS_MASK
517            }
518
519            /// Removes all bits from `other`.
520            ///
521            /// This is a raw-bit operation.
522            /// It cannot introduce new bits, but it does not clear any other
523            /// invalid bits that may already be present.
524            #[inline]
525            pub const fn remove(&mut self, other: Self) {
526                self.0 &= !other.0;
527            }
528
529            /// Toggles all bits from `other`.
530            ///
531            /// This is a raw-bit operation.
532            /// It does not validate or clear invalid bits.
533            /// Toggling `other` can introduce invalid bits into `self`.
534            #[inline]
535            pub const fn toggle(&mut self, other: Self) {
536                self.0 ^= other.0;
537            }
538
539            /// Inserts `other` if `value` is `true`, or removes `other` if
540            /// `value` is `false`.
541            ///
542            /// This is a raw-bit operation and follows the same invalid-bit
543            /// behavior as [`BitFlags::insert`] and [`BitFlags::remove`].
544            #[inline]
545            pub const fn set(&mut self, other: Self, value: bool) {
546                if value {
547                    self.insert(other)
548                } else {
549                    self.remove(other)
550                }
551            }
552
553            /// Returns the intersection of `self` and `other`.
554            ///
555            /// This is a raw-bit operation.
556            /// Invalid bits in either operand are preserved when they are set
557            /// in both operands.
558            #[inline]
559            #[must_use]
560            pub const fn intersection(self, other: Self) -> Self {
561                Self(self.0 & other.0, PhantomData)
562            }
563
564            /// Returns the union of `self` and `other`.
565            ///
566            /// This is a raw-bit operation.
567            /// Invalid bits in either operand are preserved.
568            #[inline]
569            #[must_use]
570            pub const fn union(self, other: Self) -> Self {
571                Self(self.0 | other.0, PhantomData)
572            }
573
574            /// Returns the difference of `self` and `other`.
575            ///
576            /// The result contains bits that are set in `self` but not in
577            /// `other`.
578            /// This is a raw-bit operation.
579            /// Invalid bits already present in `self` are preserved unless they
580            /// are also set in `other`.
581            #[inline]
582            #[must_use]
583            pub const fn difference(self, other: Self) -> Self {
584                Self(self.0 & !other.0, PhantomData)
585            }
586
587            /// Returns the symmetric difference of `self` and `other`.
588            ///
589            /// The result contains bits that are set in exactly one of `self`
590            /// or `other`.
591            /// This is a raw-bit operation.
592            /// Invalid bits participate and may be preserved.
593            #[inline]
594            #[must_use]
595            pub const fn symmetric_difference(self, other: Self) -> Self {
596                Self(self.0 ^ other.0, PhantomData)
597            }
598
599            /// Returns the complement of `self`.
600            ///
601            /// All valid bits not set in `self` become set, and all invalid
602            /// bits become unset.
603            /// The result always contains only valid bits.
604            #[inline]
605            #[must_use]
606            pub const fn complement(self) -> Self
607            where
608                U: BitFlagsSpec<$ty>,
609            {
610                Self(!self.0 & U::VALID_BITS_MASK, PhantomData)
611            }
612        }
613
614        impl<U> From<BitFlags<$ty, U>> for $ty
615        where
616            U: ?Sized,
617        {
618            #[inline]
619            fn from(flags: BitFlags<$ty, U>) -> Self {
620                flags.0
621            }
622        }
623    };
624}
625
626impl_bit_flags!(u8);
627impl_bit_flags!(u16);
628impl_bit_flags!(u32);
629impl_bit_flags!(u64);
630impl_bit_flags!(u128);
631impl_bit_flags!(usize);
632
633impl_bit_flags!(i8);
634impl_bit_flags!(i16);
635impl_bit_flags!(i32);
636impl_bit_flags!(i64);
637impl_bit_flags!(i128);
638impl_bit_flags!(isize);
639
640impl<T, U> Copy for BitFlags<T, U>
641where
642    T: Copy,
643    U: ?Sized,
644{
645}
646
647impl<T, U> Clone for BitFlags<T, U>
648where
649    T: Clone,
650    U: ?Sized,
651{
652    #[inline]
653    fn clone(&self) -> Self {
654        Self(self.0.clone(), PhantomData)
655    }
656}
657
658impl<T, U> Eq for BitFlags<T, U>
659where
660    T: Eq,
661    U: ?Sized,
662{
663}
664
665impl<T, U> PartialEq for BitFlags<T, U>
666where
667    T: PartialEq,
668    U: ?Sized,
669{
670    #[inline]
671    fn eq(&self, other: &Self) -> bool {
672        self.0 == other.0
673    }
674}
675
676impl<T, U> PartialEq<BitFlag<T, U>> for BitFlags<T, U>
677where
678    T: Copy + PartialEq + util::IntOpsExt,
679    U: ?Sized,
680{
681    #[inline]
682    fn eq(&self, other: &BitFlag<T, U>) -> bool {
683        self.eq(&Self::from(*other))
684    }
685}
686
687impl<T, U> PartialEq<BitFlags<T, U>> for BitFlag<T, U>
688where
689    T: Copy + PartialEq + util::IntOpsExt,
690    U: ?Sized,
691{
692    #[inline]
693    fn eq(&self, other: &BitFlags<T, U>) -> bool {
694        BitFlags::from(*self).eq(other)
695    }
696}
697
698impl<T, U> Ord for BitFlags<T, U>
699where
700    T: Ord,
701    U: ?Sized,
702{
703    #[inline]
704    fn cmp(&self, other: &Self) -> Ordering {
705        self.0.cmp(&other.0)
706    }
707}
708
709impl<T, U> PartialOrd for BitFlags<T, U>
710where
711    T: PartialOrd,
712    U: ?Sized,
713{
714    #[inline]
715    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
716        self.0.partial_cmp(&other.0)
717    }
718}
719
720impl<T, U> PartialOrd<BitFlag<T, U>> for BitFlags<T, U>
721where
722    T: Copy + PartialOrd + util::IntOpsExt,
723    U: ?Sized,
724{
725    #[inline]
726    fn partial_cmp(&self, other: &BitFlag<T, U>) -> Option<Ordering> {
727        self.partial_cmp(&Self::from(*other))
728    }
729}
730
731impl<T, U> PartialOrd<BitFlags<T, U>> for BitFlag<T, U>
732where
733    T: Copy + PartialOrd + util::IntOpsExt,
734    U: ?Sized,
735{
736    #[inline]
737    fn partial_cmp(&self, other: &BitFlags<T, U>) -> Option<Ordering> {
738        BitFlags::from(*self).partial_cmp(other)
739    }
740}
741
742impl<T, U> Hash for BitFlags<T, U>
743where
744    T: Hash,
745    U: ?Sized,
746{
747    #[inline]
748    fn hash<H: Hasher>(&self, state: &mut H) {
749        self.0.hash(state);
750    }
751}
752
753impl<T, U> Default for BitFlags<T, U>
754where
755    T: Default,
756    U: ?Sized,
757{
758    #[inline]
759    fn default() -> Self {
760        Self(T::default(), PhantomData)
761    }
762}
763
764impl<T, U> From<BitFlag<T, U>> for BitFlags<T, U>
765where
766    T: util::IntOpsExt,
767    U: ?Sized,
768{
769    #[inline]
770    fn from(flag: BitFlag<T, U>) -> Self {
771        let bit = flag.bit();
772        T::ONE
773            .checked_shl(u32::from(bit))
774            .map_or_else(Self::empty, Self::from_bits_retain)
775    }
776}
777
778impl<T, U> AsRef<T> for BitFlags<T, U>
779where
780    U: ?Sized,
781{
782    #[inline]
783    fn as_ref(&self) -> &T {
784        &self.0
785    }
786}
787
788impl<T, U> Borrow<T> for BitFlags<T, U>
789where
790    U: ?Sized,
791{
792    #[inline]
793    fn borrow(&self) -> &T {
794        &self.0
795    }
796}
797
798impl<T, U> BitAnd<Self> for BitFlags<T, U>
799where
800    T: BitAnd<T, Output = T>,
801    U: ?Sized,
802{
803    type Output = Self;
804
805    #[inline]
806    fn bitand(self, rhs: Self) -> Self::Output {
807        Self(self.0 & rhs.0, PhantomData)
808    }
809}
810
811impl<T, U> BitAnd<BitFlag<T, U>> for BitFlags<T, U>
812where
813    T: BitAnd<T, Output = T> + util::IntOpsExt,
814    U: ?Sized,
815{
816    type Output = Self;
817
818    #[inline]
819    fn bitand(self, rhs: BitFlag<T, U>) -> Self::Output {
820        self.bitand(Self::from(rhs))
821    }
822}
823
824impl<T, U> BitAnd<BitFlags<T, U>> for BitFlag<T, U>
825where
826    T: BitAnd<T, Output = T> + util::IntOpsExt,
827    U: ?Sized,
828{
829    type Output = BitFlags<T, U>;
830
831    #[inline]
832    fn bitand(self, rhs: BitFlags<T, U>) -> Self::Output {
833        BitFlags::from(self).bitand(rhs)
834    }
835}
836
837impl<T, U> BitAndAssign<Self> for BitFlags<T, U>
838where
839    T: BitAndAssign<T>,
840    U: ?Sized,
841{
842    #[inline]
843    fn bitand_assign(&mut self, rhs: Self) {
844        self.0 &= rhs.0;
845    }
846}
847
848impl<T, U> BitAndAssign<BitFlag<T, U>> for BitFlags<T, U>
849where
850    T: BitAndAssign<T> + util::IntOpsExt,
851    U: ?Sized,
852{
853    #[inline]
854    fn bitand_assign(&mut self, rhs: BitFlag<T, U>) {
855        self.bitand_assign(Self::from(rhs));
856    }
857}
858
859impl<T, U> BitOr<Self> for BitFlags<T, U>
860where
861    T: BitOr<T, Output = T>,
862    U: ?Sized,
863{
864    type Output = Self;
865
866    #[inline]
867    fn bitor(self, rhs: Self) -> Self::Output {
868        Self(self.0 | rhs.0, PhantomData)
869    }
870}
871
872impl<T, U> BitOr<BitFlag<T, U>> for BitFlags<T, U>
873where
874    T: BitOr<T, Output = T> + util::IntOpsExt,
875    U: ?Sized,
876{
877    type Output = Self;
878
879    #[inline]
880    fn bitor(self, rhs: BitFlag<T, U>) -> Self::Output {
881        self.bitor(Self::from(rhs))
882    }
883}
884
885impl<T, U> BitOr<BitFlags<T, U>> for BitFlag<T, U>
886where
887    T: BitOr<T, Output = T> + util::IntOpsExt,
888    U: ?Sized,
889{
890    type Output = BitFlags<T, U>;
891
892    #[inline]
893    fn bitor(self, rhs: BitFlags<T, U>) -> Self::Output {
894        BitFlags::from(self).bitor(rhs)
895    }
896}
897
898impl<T, U> BitOrAssign<Self> for BitFlags<T, U>
899where
900    T: BitOrAssign<T>,
901    U: ?Sized,
902{
903    #[inline]
904    fn bitor_assign(&mut self, rhs: Self) {
905        self.0 |= rhs.0;
906    }
907}
908
909impl<T, U> BitOrAssign<BitFlag<T, U>> for BitFlags<T, U>
910where
911    T: BitOrAssign<T> + util::IntOpsExt,
912    U: ?Sized,
913{
914    #[inline]
915    fn bitor_assign(&mut self, rhs: BitFlag<T, U>) {
916        self.bitor_assign(Self::from(rhs));
917    }
918}
919
920impl<T, U> BitXor<Self> for BitFlags<T, U>
921where
922    T: BitXor<T, Output = T>,
923    U: ?Sized,
924{
925    type Output = Self;
926
927    #[inline]
928    fn bitxor(self, rhs: Self) -> Self::Output {
929        Self(self.0 ^ rhs.0, PhantomData)
930    }
931}
932
933impl<T, U> BitXor<BitFlag<T, U>> for BitFlags<T, U>
934where
935    T: BitXor<T, Output = T> + util::IntOpsExt,
936    U: ?Sized,
937{
938    type Output = Self;
939
940    #[inline]
941    fn bitxor(self, rhs: BitFlag<T, U>) -> Self::Output {
942        self.bitxor(Self::from(rhs))
943    }
944}
945
946impl<T, U> BitXor<BitFlags<T, U>> for BitFlag<T, U>
947where
948    T: BitXor<T, Output = T> + util::IntOpsExt,
949    U: ?Sized,
950{
951    type Output = BitFlags<T, U>;
952
953    #[inline]
954    fn bitxor(self, rhs: BitFlags<T, U>) -> Self::Output {
955        BitFlags::from(self).bitxor(rhs)
956    }
957}
958
959impl<T, U> BitXorAssign<Self> for BitFlags<T, U>
960where
961    T: BitXorAssign<T>,
962    U: ?Sized,
963{
964    #[inline]
965    fn bitxor_assign(&mut self, rhs: Self) {
966        self.0 ^= rhs.0;
967    }
968}
969
970impl<T, U> BitXorAssign<BitFlag<T, U>> for BitFlags<T, U>
971where
972    T: BitXorAssign<T> + util::IntOpsExt,
973    U: ?Sized,
974{
975    #[inline]
976    fn bitxor_assign(&mut self, rhs: BitFlag<T, U>) {
977        self.bitxor_assign(Self::from(rhs));
978    }
979}
980
981impl<T, U> Sub<Self> for BitFlags<T, U>
982where
983    T: Not<Output = T> + BitAnd<T, Output = T>,
984    U: ?Sized,
985{
986    type Output = Self;
987
988    #[inline]
989    fn sub(self, rhs: Self) -> Self::Output {
990        Self(self.0 & !rhs.0, PhantomData)
991    }
992}
993
994impl<T, U> Sub<BitFlag<T, U>> for BitFlags<T, U>
995where
996    T: Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
997    U: ?Sized,
998{
999    type Output = Self;
1000
1001    #[inline]
1002    fn sub(self, rhs: BitFlag<T, U>) -> Self::Output {
1003        self.sub(Self::from(rhs))
1004    }
1005}
1006
1007impl<T, U> Sub<BitFlags<T, U>> for BitFlag<T, U>
1008where
1009    T: Not<Output = T> + BitAnd<T, Output = T> + util::IntOpsExt,
1010    U: ?Sized,
1011{
1012    type Output = BitFlags<T, U>;
1013
1014    #[inline]
1015    fn sub(self, rhs: BitFlags<T, U>) -> Self::Output {
1016        BitFlags::from(self).sub(rhs)
1017    }
1018}
1019
1020impl<T, U> SubAssign<Self> for BitFlags<T, U>
1021where
1022    T: Not<Output = T> + BitAndAssign<T>,
1023    U: ?Sized,
1024{
1025    #[inline]
1026    fn sub_assign(&mut self, rhs: Self) {
1027        self.0 &= !rhs.0;
1028    }
1029}
1030
1031impl<T, U> SubAssign<BitFlag<T, U>> for BitFlags<T, U>
1032where
1033    T: Not<Output = T> + BitAndAssign<T> + util::IntOpsExt,
1034    U: ?Sized,
1035{
1036    #[inline]
1037    fn sub_assign(&mut self, rhs: BitFlag<T, U>) {
1038        self.sub_assign(Self::from(rhs));
1039    }
1040}
1041
1042impl<T, U> Not for BitFlags<T, U>
1043where
1044    T: Not<Output = T> + BitAnd<T, Output = T>,
1045    U: ?Sized + BitFlagsSpec<T>,
1046{
1047    type Output = Self;
1048
1049    #[inline]
1050    fn not(self) -> Self::Output {
1051        Self(!self.0 & U::VALID_BITS_MASK, PhantomData)
1052    }
1053}
1054
1055impl<T, U> fmt::Display for BitFlags<T, U>
1056where
1057    T: Copy
1058        + PartialEq
1059        + Not<Output = T>
1060        + BitAnd<T, Output = T>
1061        + Shl<usize, Output = T>
1062        + fmt::LowerHex
1063        + util::IntOpsExt,
1064    U: ?Sized + BitFlagsSpec<T>,
1065{
1066    #[expect(clippy::missing_inline_in_public_items, reason = "bloats binary size")]
1067    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1068        let mut separator = "";
1069        let mut this = self.0;
1070        for (i, names) in U::FLAG_NAMES.iter().enumerate() {
1071            let Some(i) = u32::try_from(i).ok() else {
1072                break; // `FLAG_NAMES` with more than `u32::MAX` entries.
1073            };
1074            let Some(mask) = T::ONE.checked_shl(i) else {
1075                break;
1076            };
1077            if let Some(name) = names.first() {
1078                let new_this = this & !mask;
1079                if this != new_this {
1080                    write!(f, "{separator}{name}")?;
1081                    separator = " | ";
1082                }
1083                this = new_this;
1084            }
1085        }
1086        if this != T::ZERO {
1087            write!(f, "{separator}{this:#x}")?;
1088        }
1089        Ok(())
1090    }
1091}
1092
1093impl<T, U> fmt::Debug for BitFlags<T, U>
1094where
1095    T: fmt::LowerHex,
1096    U: ?Sized,
1097{
1098    #[expect(clippy::missing_inline_in_public_items, reason = "bloats binary size")]
1099    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1100        write!(
1101            f,
1102            "BitFlags({:#x}, PhantomData<{}>)",
1103            self.0,
1104            type_name::<U>()
1105        )
1106    }
1107}
1108
1109impl<T, U> fmt::Binary for BitFlags<T, U>
1110where
1111    T: fmt::Binary,
1112    U: ?Sized,
1113{
1114    #[inline]
1115    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1116        fmt::Binary::fmt(&self.0, f)
1117    }
1118}
1119
1120impl<T, U> fmt::Octal for BitFlags<T, U>
1121where
1122    T: fmt::Octal,
1123    U: ?Sized,
1124{
1125    #[inline]
1126    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1127        fmt::Octal::fmt(&self.0, f)
1128    }
1129}
1130
1131impl<T, U> fmt::LowerHex for BitFlags<T, U>
1132where
1133    T: fmt::LowerHex,
1134    U: ?Sized,
1135{
1136    #[inline]
1137    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1138        fmt::LowerHex::fmt(&self.0, f)
1139    }
1140}
1141
1142impl<T, U> fmt::UpperHex for BitFlags<T, U>
1143where
1144    T: fmt::UpperHex,
1145    U: ?Sized,
1146{
1147    #[inline]
1148    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1149        fmt::UpperHex::fmt(&self.0, f)
1150    }
1151}
1152
1153impl<T, U> FromStr for BitFlags<T, U>
1154where
1155    T: BitOrAssign<T> + util::IntOpsExt,
1156    U: ?Sized + BitFlagsSpec<T>,
1157{
1158    type Err = BitFlagsParseError;
1159
1160    #[inline]
1161    fn from_str(input: &str) -> Result<Self, Self::Err> {
1162        Self::try_from_str(input, "|", U::DEFAULT_NAME_MATCHER)
1163    }
1164}
1165
1166impl<T, U> IntoIterator for BitFlags<T, U>
1167where
1168    T: Copy + Not<Output = T> + BitAndAssign<T> + util::IntOpsExt,
1169    U: ?Sized,
1170{
1171    type IntoIter = BitFlagsIter<T, U>;
1172    type Item = BitFlag<T, U>;
1173
1174    #[inline]
1175    fn into_iter(self) -> Self::IntoIter {
1176        BitFlagsIter::new(self)
1177    }
1178}
1179
1180impl<T, U> IntoIterator for &BitFlags<T, U>
1181where
1182    T: Copy + Not<Output = T> + BitAndAssign<T> + util::IntOpsExt,
1183    U: ?Sized,
1184{
1185    type IntoIter = BitFlagsIter<T, U>;
1186    type Item = BitFlag<T, U>;
1187
1188    #[inline]
1189    fn into_iter(self) -> Self::IntoIter {
1190        BitFlagsIter::new(*self)
1191    }
1192}
1193
1194#[expect(
1195    clippy::into_iter_without_iter,
1196    reason = "`iter` and `iter_mut` are the same"
1197)]
1198impl<T, U> IntoIterator for &mut BitFlags<T, U>
1199where
1200    T: Copy + Not<Output = T> + BitAndAssign<T> + util::IntOpsExt,
1201    U: ?Sized,
1202{
1203    type IntoIter = BitFlagsIter<T, U>;
1204    type Item = BitFlag<T, U>;
1205
1206    #[inline]
1207    fn into_iter(self) -> Self::IntoIter {
1208        BitFlagsIter::new(*self)
1209    }
1210}
1211
1212impl<T, U> Extend<Self> for BitFlags<T, U>
1213where
1214    T: BitOrAssign<T>,
1215    U: ?Sized,
1216{
1217    #[inline]
1218    fn extend<I>(&mut self, iter: I)
1219    where
1220        I: IntoIterator<Item = Self>,
1221    {
1222        for other in iter {
1223            self.0 |= other.0;
1224        }
1225    }
1226}
1227
1228impl<T, U> Extend<BitFlag<T, U>> for BitFlags<T, U>
1229where
1230    T: BitOrAssign<T> + util::IntOpsExt,
1231    U: ?Sized,
1232{
1233    #[inline]
1234    fn extend<I>(&mut self, iter: I)
1235    where
1236        I: IntoIterator<Item = BitFlag<T, U>>,
1237    {
1238        for other in iter {
1239            *self |= Self::from(other);
1240        }
1241    }
1242}
1243
1244impl<T, U> FromIterator<Self> for BitFlags<T, U>
1245where
1246    T: BitOrAssign<T> + util::IntOpsExt,
1247    U: ?Sized,
1248{
1249    #[inline]
1250    fn from_iter<I>(iter: I) -> Self
1251    where
1252        I: IntoIterator<Item = Self>,
1253    {
1254        let mut this = Self(T::ZERO, PhantomData);
1255        for other in iter {
1256            this.0 |= other.0;
1257        }
1258        this
1259    }
1260}
1261
1262impl<T, U> FromIterator<BitFlag<T, U>> for BitFlags<T, U>
1263where
1264    T: BitOrAssign<T> + util::IntOpsExt,
1265    U: ?Sized,
1266{
1267    #[inline]
1268    fn from_iter<I>(iter: I) -> Self
1269    where
1270        I: IntoIterator<Item = BitFlag<T, U>>,
1271    {
1272        let mut this = Self(T::ZERO, PhantomData);
1273        for other in iter {
1274            this |= Self::from(other);
1275        }
1276        this
1277    }
1278}
1279
1280#[cfg(feature = "arbitrary")]
1281#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
1282impl<'a, T, U> arbitrary::Arbitrary<'a> for BitFlags<T, U>
1283where
1284    T: arbitrary::Arbitrary<'a>,
1285    U: ?Sized,
1286{
1287    #[inline]
1288    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
1289        T::arbitrary(u).map(|u| Self(u, PhantomData))
1290    }
1291
1292    #[inline]
1293    fn size_hint(depth: usize) -> (usize, Option<usize>) {
1294        T::size_hint(depth)
1295    }
1296}
1297
1298#[cfg(feature = "bytemuck")]
1299#[cfg_attr(docsrs, doc(cfg(feature = "bytemuck")))]
1300// SAFETY: All fields are valid when their memory is entirely zeroed out.
1301unsafe impl<T, U> bytemuck::Zeroable for BitFlags<T, U>
1302where
1303    T: bytemuck::Zeroable,
1304    U: ?Sized,
1305{
1306}
1307
1308#[cfg(feature = "bytemuck")]
1309#[cfg_attr(docsrs, doc(cfg(feature = "bytemuck")))]
1310// SAFETY: The type is Copy, Zeroable, has no padding bytes, and any
1311// bit pattern of the correct size is a valid instance of this type.
1312unsafe impl<T, U> bytemuck::Pod for BitFlags<T, U>
1313where
1314    T: bytemuck::Pod,
1315    U: 'static + ?Sized,
1316{
1317}
1318
1319#[cfg(feature = "serde")]
1320#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1321impl<T, U> serde::Serialize for BitFlags<T, U>
1322where
1323    T: Copy
1324        + PartialEq
1325        + Not<Output = T>
1326        + BitAnd<T, Output = T>
1327        + Shl<usize, Output = T>
1328        + fmt::LowerHex
1329        + util::IntOpsExt,
1330    U: ?Sized + BitFlagsSpec<T>,
1331{
1332    #[inline]
1333    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
1334    where
1335        S: serde::Serializer,
1336    {
1337        // Replicates the behavior of `bitflags`-based implementation.
1338        serializer.collect_str(&self)
1339    }
1340}
1341
1342#[cfg(feature = "serde")]
1343#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1344impl<'de, T, U> serde::Deserialize<'de> for BitFlags<T, U>
1345where
1346    T: BitOrAssign<T> + util::IntOpsExt,
1347    U: ?Sized + BitFlagsSpec<T>,
1348{
1349    #[inline]
1350    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
1351    where
1352        D: serde::Deserializer<'de>,
1353    {
1354        deserializer.deserialize_str(BitFlagsVisitor::<T, U>(PhantomData, PhantomData))
1355    }
1356}
1357
1358#[cfg(feature = "serde")]
1359#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
1360impl<T, U> serde::de::Visitor<'_> for BitFlagsVisitor<T, U>
1361where
1362    T: BitOrAssign<T> + util::IntOpsExt,
1363    U: ?Sized + BitFlagsSpec<T>,
1364{
1365    type Value = BitFlags<T, U>;
1366
1367    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1368        fmt_expected(f, "|", U::FLAG_NAMES)
1369    }
1370
1371    #[inline]
1372    fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
1373    where
1374        E: serde::de::Error,
1375    {
1376        Self::Value::from_str(value).map_err(E::custom)
1377    }
1378}
1379
1380/// An error encountered while parsing flags from text.
1381#[cfg_attr(
1382    not(feature = "alloc"),
1383    expect(
1384        missing_copy_implementations,
1385        reason = "the payload is feature-dependent"
1386    )
1387)]
1388#[derive(Clone, Debug)]
1389pub struct BitFlagsParseError {
1390    #[cfg(not(feature = "alloc"))]
1391    given: (),
1392    #[cfg(feature = "alloc")]
1393    given: alloc::string::String,
1394
1395    separator: &'static str,
1396    expected: &'static [&'static [&'static str]],
1397}
1398
1399impl fmt::Display for BitFlagsParseError {
1400    #[expect(clippy::missing_inline_in_public_items, reason = "bloats binary size")]
1401    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1402        let named_flags = self
1403            .expected
1404            .iter()
1405            .filter(|variants| !variants.is_empty())
1406            .count();
1407
1408        if named_flags == 0 {
1409            write!(f, "unrecognized hex flag, ")?;
1410        } else {
1411            write!(f, "unrecognized named flag or hex flag, ")?;
1412        }
1413        #[cfg(feature = "alloc")]
1414        write!(f, "given: \"{}\", expected ", self.given)?;
1415        #[cfg(not(feature = "alloc"))]
1416        write!(f, "expected ")?;
1417        fmt_expected(f, self.separator, self.expected)?;
1418
1419        #[cfg(not(feature = "alloc"))]
1420        let () = self.given;
1421
1422        Ok(())
1423    }
1424}
1425
1426impl core::error::Error for BitFlagsParseError {}
1427
1428/// Writes the expected flag format for [`BitFlagsParseError`] and serde
1429/// visitors.
1430#[inline]
1431fn fmt_expected(
1432    f: &mut fmt::Formatter<'_>,
1433    separator: &'static str,
1434    expected: &'static [&'static [&'static str]],
1435) -> fmt::Result {
1436    let named_flags = expected
1437        .iter()
1438        .filter(|variants| !variants.is_empty())
1439        .count();
1440
1441    if named_flags == 0 {
1442        write!(f, "a valid hex flag with \"0x\" prefix")?;
1443    } else {
1444        write!(f, "\"\", or a \"{separator}\"-separated set of")?;
1445
1446        let mut separator = " ";
1447        for names in expected {
1448            if let Some(name) = names.first() {
1449                write!(f, "{separator}\"{name}\"")?;
1450                separator = ", ";
1451            }
1452        }
1453        write!(f, ", or a valid hex flag with \"0x\" prefix")?;
1454    }
1455    Ok(())
1456}