enumset/
set.rs

1use crate::repr::EnumSetTypeRepr;
2use crate::traits::EnumSetType;
3use crate::EnumSetTypeWithRepr;
4use core::cmp::Ordering;
5use core::fmt::{Debug, Display, Formatter};
6use core::hash::{Hash, Hasher};
7use core::iter::Sum;
8use core::ops::{
9    BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Sub, SubAssign,
10};
11
12#[cfg(feature = "serde")]
13use {
14    serde2 as serde,
15    serde2::{Deserialize, Serialize},
16};
17
18/// An efficient set type for enums.
19///
20/// It is implemented using a bitset stored using the smallest integer that can fit all bits
21/// in the underlying enum. In general, an enum variant with a discriminator of `n` is stored in
22/// the nth least significant bit (corresponding with a mask of, e.g. `1 << enum as u32`).
23///
24/// # Numeric representation
25///
26/// `EnumSet` is internally implemented using integer types, and as such can be easily converted
27/// from and to numbers.
28///
29/// Each bit of the underlying integer corresponds to at most one particular enum variant. If the
30/// corresponding bit for a variant is set, it present in the set. Bits that do not correspond to
31/// any variant are always unset.
32///
33/// By default, each enum variant is stored in a bit corresponding to its discriminator. An enum
34/// variant with a discriminator of `n` is stored in the `n + 1`th least significant bit
35/// (corresponding to a mask of e.g. `1 << enum as u32`).
36///
37/// # Array representation
38///
39/// Sets with more than 128 variants are instead stored with an underlying array of `u64`s. This
40/// is treated as if it was a single large integer. The `n`th least significant bit of this integer
41/// is stored in the `n % 64`th least significant bit of the `n / 64`th element in the array.
42///
43/// # Serialization
44///
45/// When the `serde` feature is enabled, `EnumSet`s can be serialized and deserialized using
46/// the `serde` crate. The exact serialization format can be controlled with additional attributes
47/// on the enum type. These attributes are valid regardless of whether the `serde` feature
48/// is enabled.
49///
50/// By default, `EnumSet` is serialized by directly writing out a single integer containing the
51/// numeric representation of the bitset. The integer type used is the smallest one that can fit
52/// the largest variant in the enum. If no integer type is large enough, instead the `EnumSet` is
53/// serialized as an array of `u64`s containing the array representation.
54///
55/// The `#[enumset(serialize_repr = "…")]` attribute can be used to override the representation
56/// used. Valid values are as follows:
57///
58/// * `u8`, `u16`, `u32`, `u64`, and `u128` serialize the type as the corresponding integer type.
59/// * `array` serializes the set as an list of `u64`s corresponding to the array representation.
60/// * `list` serializes the set as a list of enum variants. This requires your enum type implement
61///   [`Serialize`] and [`Deserialize`].
62/// * `map` serializes the set as a map of enum variants to booleans. The set contains a value if
63///   the boolean is `true`. This requires your enum type implement `Serialize` and `Deserialize`.
64///
65/// The representation used is determined statically at compile time, and there is currently no
66/// support for reading different formats with the same deserializer.
67///
68/// By default, unknown bits are ignored and silently removed from the bitset. To override this
69/// behavior, you can add a `#[enumset(serialize_deny_unknown)]` attribute. This will cause
70/// deserialization to fail if an invalid bit is set.
71///
72/// # FFI, Safety and `repr`
73///
74/// If an enum type `T` is annotated with
75/// [`#[enumset(repr = "…")]`](derive@crate::EnumSetType#options) where `…` is a primitive integer
76/// type, then several things happen:
77///
78/// * `T` will implement
79///   <code>[EnumSetTypeWithRepr](crate::traits::EnumSetTypeWithRepr)&lt;Repr = R&gt;</code> in
80///   addition to [`EnumSetType`].
81/// * The `EnumSet` methods with `repr` in their name, such as [`as_repr`][EnumSet::as_repr] and
82///   [`from_repr`][EnumSet::from_repr], will be available for `EnumSet<T>`.
83/// * The in-memory representation of `EnumSet<T>` is guaranteed to be `R`.
84///
85/// That last guarantee makes it sound to send `EnumSet<T>` across an FFI boundary. For example:
86///
87/// ```
88/// # use enumset::*;
89/// #
90/// # mod ffi_impl {
91/// #     // This example “foreign” function is actually written in Rust, but for the sake
92/// #     // of example, we'll pretend it's written in C.
93/// #     #[no_mangle]
94/// #     extern "C" fn some_foreign_function(set: u32) -> u32 {
95/// #         set & 0b100
96/// #     }
97/// # }
98/// #
99/// extern "C" {
100///     // This function is written in C like:
101///     // uint32_t some_foreign_function(uint32_t set) { … }
102///     fn some_foreign_function(set: EnumSet<MyEnum>) -> EnumSet<MyEnum>;
103/// }
104///
105/// #[derive(Debug, EnumSetType)]
106/// #[enumset(repr = "u32")]
107/// enum MyEnum { A, B, C }
108///
109/// let set: EnumSet<MyEnum> = enum_set!(MyEnum::A | MyEnum::C);
110///
111/// let new_set: EnumSet<MyEnum> = unsafe { some_foreign_function(set) };
112/// assert_eq!(new_set, enum_set!(MyEnum::C));
113/// ```
114///
115/// When an `EnumSet<T>` is received via FFI, all bits that don't correspond to an enum variant
116/// of `T` must be set to `0`. Behavior is **undefined** if any of these bits are set to `1`.
117#[cfg_attr(
118    not(feature = "serde"),
119    doc = "\n\n",
120    doc = "[`Serialize`]: https://docs.rs/serde/latest/serde/trait.Serialize.html\n",
121    doc = "[`Deserialize`]: https://docs.rs/serde/latest/serde/trait.Deserialize.html\n"
122)]
123#[derive(Copy, Clone, PartialEq, Eq)]
124#[repr(transparent)]
125pub struct EnumSet<T: EnumSetType> {
126    #[doc(hidden)]
127    /// This is public due to the `enum_set!` macro.
128    /// This is **NOT** public API and may change at any time.
129    pub __priv_repr: T::Repr,
130}
131
132//region EnumSet operations
133impl<T: EnumSetType> EnumSet<T> {
134    const EMPTY_REPR: Self = EnumSet { __priv_repr: T::Repr::EMPTY };
135    const ALL_REPR: Self = EnumSet { __priv_repr: T::ALL_BITS };
136
137    /// Creates an empty `EnumSet`.
138    #[inline(always)]
139    pub const fn new() -> Self {
140        Self::EMPTY_REPR
141    }
142
143    /// Returns an `EnumSet` containing a single element.
144    #[inline(always)]
145    pub fn only(t: T) -> Self {
146        let mut set = Self::new();
147        set.insert(t);
148        set
149    }
150
151    /// Creates an empty `EnumSet`.
152    ///
153    /// This is an alias for [`EnumSet::new`].
154    #[inline(always)]
155    pub const fn empty() -> Self {
156        Self::EMPTY_REPR
157    }
158
159    /// Returns an `EnumSet` containing all valid variants of the enum.
160    #[inline(always)]
161    pub const fn all() -> Self {
162        Self::ALL_REPR
163    }
164
165    /// Total number of bits used by this type. Note that the actual amount of space used is
166    /// rounded up to the next highest integer type (`u8`, `u16`, `u32`, `u64`, or `u128`).
167    ///
168    /// This is the same as [`EnumSet::variant_count`] except in enums with "sparse" variants.
169    /// (e.g. `enum Foo { A = 10, B = 20 }`)
170    #[inline(always)]
171    pub const fn bit_width() -> u32 {
172        T::BIT_WIDTH
173    }
174
175    /// The number of valid variants that this type can contain.
176    ///
177    /// This is the same as [`EnumSet::bit_width`] except in enums with "sparse" variants.
178    /// (e.g. `enum Foo { A = 10, B = 20 }`)
179    #[inline(always)]
180    pub const fn variant_count() -> u32 {
181        T::VARIANT_COUNT
182    }
183
184    /// Returns the number of elements in this set.
185    #[inline(always)]
186    pub fn len(&self) -> usize {
187        self.__priv_repr.count_ones() as usize
188    }
189    /// Returns `true` if the set contains no elements.
190    #[inline(always)]
191    pub fn is_empty(&self) -> bool {
192        self.__priv_repr.is_empty()
193    }
194    /// Removes all elements from the set.
195    #[inline(always)]
196    pub fn clear(&mut self) {
197        self.__priv_repr = T::Repr::EMPTY;
198    }
199
200    /// Returns `true` if `self` has no elements in common with `other`. This is equivalent to
201    /// checking for an empty intersection.
202    #[inline(always)]
203    pub fn is_disjoint(&self, other: Self) -> bool {
204        (*self & other).is_empty()
205    }
206    /// Returns `true` if the set is a superset of another, i.e., `self` contains at least all the
207    /// values in `other`.
208    #[inline(always)]
209    pub fn is_superset(&self, other: Self) -> bool {
210        (*self & other).__priv_repr == other.__priv_repr
211    }
212    /// Returns `true` if the set is a subset of another, i.e., `other` contains at least all
213    /// the values in `self`.
214    #[inline(always)]
215    pub fn is_subset(&self, other: Self) -> bool {
216        other.is_superset(*self)
217    }
218
219    /// Returns a set containing any elements present in either set.
220    #[inline(always)]
221    pub fn union(&self, other: Self) -> Self {
222        EnumSet { __priv_repr: self.__priv_repr | other.__priv_repr }
223    }
224    /// Returns a set containing every element present in both sets.
225    #[inline(always)]
226    pub fn intersection(&self, other: Self) -> Self {
227        EnumSet { __priv_repr: self.__priv_repr & other.__priv_repr }
228    }
229    /// Returns a set containing element present in `self` but not in `other`.
230    #[inline(always)]
231    pub fn difference(&self, other: Self) -> Self {
232        EnumSet { __priv_repr: self.__priv_repr.and_not(other.__priv_repr) }
233    }
234    /// Returns a set containing every element present in either `self` or `other`, but is not
235    /// present in both.
236    #[inline(always)]
237    pub fn symmetrical_difference(&self, other: Self) -> Self {
238        EnumSet { __priv_repr: self.__priv_repr ^ other.__priv_repr }
239    }
240    /// Returns a set containing all enum variants not in this set.
241    #[inline(always)]
242    pub fn complement(&self) -> Self {
243        EnumSet { __priv_repr: !self.__priv_repr & T::ALL_BITS }
244    }
245
246    /// Checks whether this set contains a value.
247    #[inline(always)]
248    pub fn contains(&self, value: T) -> bool {
249        self.__priv_repr.has_bit(value.enum_into_u32())
250    }
251
252    /// Adds a value to this set.
253    ///
254    /// If the set did not have this value present, `true` is returned.
255    ///
256    /// If the set did have this value present, `false` is returned.
257    #[inline(always)]
258    pub fn insert(&mut self, value: T) -> bool {
259        let contains = !self.contains(value);
260        self.__priv_repr.add_bit(value.enum_into_u32());
261        contains
262    }
263    /// Removes a value from this set. Returns whether the value was present in the set.
264    #[inline(always)]
265    pub fn remove(&mut self, value: T) -> bool {
266        let contains = self.contains(value);
267        self.__priv_repr.remove_bit(value.enum_into_u32());
268        contains
269    }
270
271    /// Adds all elements in another set to this one.
272    #[inline(always)]
273    pub fn insert_all(&mut self, other: Self) {
274        self.__priv_repr = self.__priv_repr | other.__priv_repr
275    }
276    /// Removes all values in another set from this one.
277    #[inline(always)]
278    pub fn remove_all(&mut self, other: Self) {
279        self.__priv_repr = self.__priv_repr.and_not(other.__priv_repr);
280    }
281}
282
283#[doc(hidden)]
284impl<T: EnumSetType> EnumSet<T> {
285    /// Creates a new enumset helper.
286    #[deprecated(note = "This method is an internal implementation detail generated by the \
287                         `enumset` crate's procedural macro. It should not be used directly.")]
288    #[doc(hidden)]
289    #[allow(non_snake_case)]
290    pub const fn __impl_enumset_internal__const_helper(&self) -> T::ConstHelper {
291        T::CONST_HELPER_INSTANCE
292    }
293
294    /// Creates a new enumset with only this variant.
295    #[deprecated(note = "This method is an internal implementation detail generated by the \
296                         `enumset` crate's procedural macro. It should not be used directly.")]
297    #[doc(hidden)]
298    #[allow(non_snake_case)]
299    pub const fn __impl_enumset_internal__const_only(self) -> Self {
300        self
301    }
302}
303
304impl<T: EnumSetType> Default for EnumSet<T> {
305    /// Returns an empty set.
306    fn default() -> Self {
307        Self::new()
308    }
309}
310
311impl<T: EnumSetType, O: Into<EnumSet<T>>> Sub<O> for EnumSet<T> {
312    type Output = Self;
313    #[inline(always)]
314    fn sub(self, other: O) -> Self::Output {
315        self.difference(other.into())
316    }
317}
318impl<T: EnumSetType, O: Into<EnumSet<T>>> BitAnd<O> for EnumSet<T> {
319    type Output = Self;
320    #[inline(always)]
321    fn bitand(self, other: O) -> Self::Output {
322        self.intersection(other.into())
323    }
324}
325impl<T: EnumSetType, O: Into<EnumSet<T>>> BitOr<O> for EnumSet<T> {
326    type Output = Self;
327    #[inline(always)]
328    fn bitor(self, other: O) -> Self::Output {
329        self.union(other.into())
330    }
331}
332impl<T: EnumSetType, O: Into<EnumSet<T>>> BitXor<O> for EnumSet<T> {
333    type Output = Self;
334    #[inline(always)]
335    fn bitxor(self, other: O) -> Self::Output {
336        self.symmetrical_difference(other.into())
337    }
338}
339
340impl<T: EnumSetType, O: Into<EnumSet<T>>> SubAssign<O> for EnumSet<T> {
341    #[inline(always)]
342    fn sub_assign(&mut self, rhs: O) {
343        *self = *self - rhs;
344    }
345}
346impl<T: EnumSetType, O: Into<EnumSet<T>>> BitAndAssign<O> for EnumSet<T> {
347    #[inline(always)]
348    fn bitand_assign(&mut self, rhs: O) {
349        *self = *self & rhs;
350    }
351}
352impl<T: EnumSetType, O: Into<EnumSet<T>>> BitOrAssign<O> for EnumSet<T> {
353    #[inline(always)]
354    fn bitor_assign(&mut self, rhs: O) {
355        *self = *self | rhs;
356    }
357}
358impl<T: EnumSetType, O: Into<EnumSet<T>>> BitXorAssign<O> for EnumSet<T> {
359    #[inline(always)]
360    fn bitxor_assign(&mut self, rhs: O) {
361        *self = *self ^ rhs;
362    }
363}
364
365impl<T: EnumSetType> Not for EnumSet<T> {
366    type Output = Self;
367    #[inline(always)]
368    fn not(self) -> Self::Output {
369        self.complement()
370    }
371}
372
373impl<T: EnumSetType> From<T> for EnumSet<T> {
374    fn from(t: T) -> Self {
375        EnumSet::only(t)
376    }
377}
378
379impl<T: EnumSetType> PartialEq<T> for EnumSet<T> {
380    fn eq(&self, other: &T) -> bool {
381        self.__priv_repr == EnumSet::only(*other).__priv_repr
382    }
383}
384
385impl<T: EnumSetType + Debug> Debug for EnumSet<T> {
386    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
387        // Note: We don't use `.debug_struct` to avoid splitting lines when using `{:x}`
388        f.write_str("EnumSet(")?;
389        let mut i = self.iter();
390        if let Some(v) = i.next() {
391            v.fmt(f)?;
392            for v in i {
393                f.write_str(" | ")?;
394                v.fmt(f)?;
395            }
396        }
397        f.write_str(")")?;
398        Ok(())
399    }
400}
401impl<T: EnumSetType + Display> Display for EnumSet<T> {
402    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
403        let mut i = self.iter();
404        if let Some(v) = i.next() {
405            v.fmt(f)?;
406            for v in i {
407                f.write_str(" | ")?;
408                v.fmt(f)?;
409            }
410        }
411        Ok(())
412    }
413}
414
415#[cfg(feature = "defmt")]
416impl<T: EnumSetType + defmt::Format> defmt::Format for EnumSet<T> {
417    fn format(&self, f: defmt::Formatter) {
418        let mut i = self.iter();
419        if let Some(v) = i.next() {
420            v.format(f);
421            let l = defmt::intern!(" | ");
422            for v in i {
423                l.format(f);
424                v.format(f);
425            }
426        }
427    }
428}
429
430#[allow(clippy::derived_hash_with_manual_eq)] // This impl exists to change trait bounds only.
431impl<T: EnumSetType> Hash for EnumSet<T> {
432    fn hash<H: Hasher>(&self, state: &mut H) {
433        self.__priv_repr.hash(state)
434    }
435}
436#[allow(clippy::non_canonical_partial_ord_impl)]
437impl<T: EnumSetType> PartialOrd for EnumSet<T> {
438    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
439        self.__priv_repr.partial_cmp(&other.__priv_repr)
440    }
441}
442impl<T: EnumSetType> Ord for EnumSet<T> {
443    fn cmp(&self, other: &Self) -> Ordering {
444        self.__priv_repr.cmp(&other.__priv_repr)
445    }
446}
447
448#[cfg(feature = "serde")]
449impl<T: EnumSetType> Serialize for EnumSet<T> {
450    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
451        T::serialize(*self, serializer)
452    }
453}
454
455#[cfg(feature = "serde")]
456impl<'de, T: EnumSetType> Deserialize<'de> for EnumSet<T> {
457    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
458        T::deserialize(deserializer)
459    }
460}
461//endregion
462
463//region Deprecated functions
464/// This impl contains all outdated or deprecated functions.
465impl<T: EnumSetType> EnumSet<T> {
466    /// An empty `EnumSet`.
467    ///
468    /// This is deprecated because [`EnumSet::empty`] is now `const`.
469    #[deprecated = "Use `EnumSet::empty()` instead."]
470    pub const EMPTY: Self = Self::EMPTY_REPR;
471
472    /// An `EnumSet` containing all valid variants of the enum.
473    ///
474    /// This is deprecated because [`EnumSet::all`] is now `const`.
475    #[deprecated = "Use `EnumSet::all()` instead."]
476    pub const ALL: Self = Self::ALL_REPR;
477}
478//endregion
479
480//region EnumSet conversions
481impl<T: EnumSetType + EnumSetTypeWithRepr> EnumSet<T> {
482    /// Returns a `T::Repr` representing the elements of this set.
483    ///
484    /// Unlike the other `as_*` methods, this method is zero-cost and guaranteed not to fail,
485    /// panic or truncate any bits.
486    ///
487    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
488    /// annotation.
489    #[inline(always)]
490    pub const fn as_repr(&self) -> <T as EnumSetTypeWithRepr>::Repr {
491        self.__priv_repr
492    }
493
494    /// Constructs a bitset from a `T::Repr` without checking for invalid bits.
495    ///
496    /// Unlike the other `from_*` methods, this method is zero-cost and guaranteed not to fail,
497    /// panic or truncate any bits, provided the conditions under “Safety” are upheld.
498    ///
499    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
500    /// annotation.
501    ///
502    /// # Safety
503    ///
504    /// All bits in the provided parameter `bits` that don't correspond to an enum variant of
505    /// `T` must be set to `0`. Behavior is **undefined** if any of these bits are set to `1`.
506    #[inline(always)]
507    pub unsafe fn from_repr_unchecked(bits: <T as EnumSetTypeWithRepr>::Repr) -> Self {
508        Self { __priv_repr: bits }
509    }
510
511    /// Constructs a bitset from a `T::Repr`.
512    ///
513    /// If a bit that doesn't correspond to an enum variant is set, this
514    /// method will panic.
515    ///
516    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
517    /// annotation.
518    #[inline(always)]
519    pub fn from_repr(bits: <T as EnumSetTypeWithRepr>::Repr) -> Self {
520        Self::try_from_repr(bits).expect("Bitset contains invalid variants.")
521    }
522
523    /// Attempts to constructs a bitset from a `T::Repr`.
524    ///
525    /// If a bit that doesn't correspond to an enum variant is set, this
526    /// method will return `None`.
527    ///
528    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
529    /// annotation.
530    #[inline(always)]
531    pub fn try_from_repr(bits: <T as EnumSetTypeWithRepr>::Repr) -> Option<Self> {
532        let mask = Self::all().__priv_repr;
533        if bits.and_not(mask).is_empty() {
534            Some(EnumSet { __priv_repr: bits })
535        } else {
536            None
537        }
538    }
539
540    /// Constructs a bitset from a `T::Repr`, ignoring invalid variants.
541    ///
542    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
543    /// annotation.
544    #[inline(always)]
545    pub fn from_repr_truncated(bits: <T as EnumSetTypeWithRepr>::Repr) -> Self {
546        let mask = Self::all().as_repr();
547        let bits = bits & mask;
548        EnumSet { __priv_repr: bits }
549    }
550}
551
552/// Helper macro for generating conversion functions.
553macro_rules! conversion_impls {
554    (
555        $(for_num!(
556            $underlying:ty, $underlying_str:expr,
557            $from_fn:ident $to_fn:ident $from_fn_opt:ident $to_fn_opt:ident,
558            $from:ident $try_from:ident $from_truncated:ident $from_unchecked:ident,
559            $to:ident $try_to:ident $to_truncated:ident
560        );)*
561    ) => {
562        impl<T: EnumSetType> EnumSet<T> {$(
563            #[doc = "Returns a `"]
564            #[doc = $underlying_str]
565            #[doc = "` representing the elements of this set.\n\nIf the underlying bitset will \
566                     not fit in a `"]
567            #[doc = $underlying_str]
568            #[doc = "`, this method will panic."]
569            #[inline(always)]
570            pub fn $to(&self) -> $underlying {
571                self.$try_to().expect("Bitset will not fit into this type.")
572            }
573
574            #[doc = "Tries to return a `"]
575            #[doc = $underlying_str]
576            #[doc = "` representing the elements of this set.\n\nIf the underlying bitset will \
577                     not fit in a `"]
578            #[doc = $underlying_str]
579            #[doc = "`, this method will panic."]
580            #[inline(always)]
581            pub fn $try_to(&self) -> Option<$underlying> {
582                EnumSetTypeRepr::$to_fn_opt(&self.__priv_repr)
583            }
584
585            #[doc = "Returns a truncated `"]
586            #[doc = $underlying_str]
587            #[doc = "` representing the elements of this set.\n\nIf the underlying bitset will \
588                     not fit in a `"]
589            #[doc = $underlying_str]
590            #[doc = "`, this method will truncate any bits that don't fit."]
591            #[inline(always)]
592            pub fn $to_truncated(&self) -> $underlying {
593                EnumSetTypeRepr::$to_fn(&self.__priv_repr)
594            }
595
596            #[doc = "Constructs a bitset from a `"]
597            #[doc = $underlying_str]
598            #[doc = "`.\n\nIf a bit that doesn't correspond to an enum variant is set, this \
599                     method will panic."]
600            #[inline(always)]
601            pub fn $from(bits: $underlying) -> Self {
602                Self::$try_from(bits).expect("Bitset contains invalid variants.")
603            }
604
605            #[doc = "Attempts to constructs a bitset from a `"]
606            #[doc = $underlying_str]
607            #[doc = "`.\n\nIf a bit that doesn't correspond to an enum variant is set, this \
608                     method will return `None`."]
609            #[inline(always)]
610            pub fn $try_from(bits: $underlying) -> Option<Self> {
611                let bits = T::Repr::$from_fn_opt(bits);
612                let mask = T::ALL_BITS;
613                bits.and_then(|bits| if bits.and_not(mask).is_empty() {
614                    Some(EnumSet { __priv_repr: bits })
615                } else {
616                    None
617                })
618            }
619
620            #[doc = "Constructs a bitset from a `"]
621            #[doc = $underlying_str]
622            #[doc = "`, ignoring bits that do not correspond to a variant."]
623            #[inline(always)]
624            pub fn $from_truncated(bits: $underlying) -> Self {
625                let mask = Self::all().$to_truncated();
626                let bits = <T::Repr as EnumSetTypeRepr>::$from_fn(bits & mask);
627                EnumSet { __priv_repr: bits }
628            }
629
630            #[doc = "Constructs a bitset from a `"]
631            #[doc = $underlying_str]
632            #[doc = "`, without checking for invalid bits."]
633            ///
634            /// # Safety
635            ///
636            /// All bits in the provided parameter `bits` that don't correspond to an enum variant
637            /// of `T` must be set to `0`. Behavior is **undefined** if any of these bits are set
638            /// to `1`.
639            #[inline(always)]
640            pub unsafe fn $from_unchecked(bits: $underlying) -> Self {
641                EnumSet { __priv_repr: <T::Repr as EnumSetTypeRepr>::$from_fn(bits) }
642            }
643        )*}
644    }
645}
646conversion_impls! {
647    for_num!(u8, "u8",
648             from_u8 to_u8 from_u8_opt to_u8_opt,
649             from_u8 try_from_u8 from_u8_truncated from_u8_unchecked,
650             as_u8 try_as_u8 as_u8_truncated);
651    for_num!(u16, "u16",
652             from_u16 to_u16 from_u16_opt to_u16_opt,
653             from_u16 try_from_u16 from_u16_truncated from_u16_unchecked,
654             as_u16 try_as_u16 as_u16_truncated);
655    for_num!(u32, "u32",
656             from_u32 to_u32 from_u32_opt to_u32_opt,
657             from_u32 try_from_u32 from_u32_truncated from_u32_unchecked,
658             as_u32 try_as_u32 as_u32_truncated);
659    for_num!(u64, "u64",
660             from_u64 to_u64 from_u64_opt to_u64_opt,
661             from_u64 try_from_u64 from_u64_truncated from_u64_unchecked,
662             as_u64 try_as_u64 as_u64_truncated);
663    for_num!(u128, "u128",
664             from_u128 to_u128 from_u128_opt to_u128_opt,
665             from_u128 try_from_u128 from_u128_truncated from_u128_unchecked,
666             as_u128 try_as_u128 as_u128_truncated);
667    for_num!(usize, "usize",
668             from_usize to_usize from_usize_opt to_usize_opt,
669             from_usize try_from_usize from_usize_truncated from_usize_unchecked,
670             as_usize try_as_usize as_usize_truncated);
671}
672
673impl<T: EnumSetType> EnumSet<T> {
674    /// Returns an `[u64; O]` representing the elements of this set.
675    ///
676    /// If the underlying bitset will not fit in a `[u64; O]`, this method will panic.
677    pub fn as_array<const O: usize>(&self) -> [u64; O] {
678        self.try_as_array()
679            .expect("Bitset will not fit into this type.")
680    }
681
682    /// Returns an `[u64; O]` representing the elements of this set.
683    ///
684    /// If the underlying bitset will not fit in a `[u64; O]`, this method will instead return
685    /// `None`.
686    pub fn try_as_array<const O: usize>(&self) -> Option<[u64; O]> {
687        self.__priv_repr.to_u64_array_opt()
688    }
689
690    /// Returns an `[u64; O]` representing the elements of this set.
691    ///
692    /// If the underlying bitset will not fit in a `[u64; O]`, this method will truncate any bits
693    /// that don't fit.
694    pub fn as_array_truncated<const O: usize>(&self) -> [u64; O] {
695        self.__priv_repr.to_u64_array()
696    }
697
698    /// Attempts to constructs a bitset from a `[u64; O]`.
699    ///
700    /// If a bit that doesn't correspond to an enum variant is set, this method will panic.
701    pub fn from_array<const O: usize>(v: [u64; O]) -> Self {
702        Self::try_from_array(v).expect("Bitset contains invalid variants.")
703    }
704
705    /// Attempts to constructs a bitset from a `[u64; O]`.
706    ///
707    /// If a bit that doesn't correspond to an enum variant is set, this method will return `None`.
708    pub fn try_from_array<const O: usize>(bits: [u64; O]) -> Option<Self> {
709        let bits = T::Repr::from_u64_array_opt::<O>(bits);
710        let mask = T::ALL_BITS;
711        bits.and_then(|bits| {
712            if bits.and_not(mask).is_empty() {
713                Some(EnumSet { __priv_repr: bits })
714            } else {
715                None
716            }
717        })
718    }
719
720    /// Constructs a bitset from a `[u64; O]`, ignoring bits that do not correspond to a variant.
721    pub fn from_array_truncated<const O: usize>(bits: [u64; O]) -> Self {
722        let bits = T::Repr::from_u64_array(bits) & T::ALL_BITS;
723        EnumSet { __priv_repr: bits }
724    }
725
726    /// Constructs a bitset from a `[u64; O]`, without checking for invalid bits.
727    ///
728    /// # Safety
729    ///
730    /// All bits in the provided parameter `bits` that don't correspond to an enum variant
731    /// of `T` must be set to `0`. Behavior is **undefined** if any of these bits are set
732    /// to `1`.
733    #[inline(always)]
734    pub unsafe fn from_array_unchecked<const O: usize>(bits: [u64; O]) -> Self {
735        EnumSet { __priv_repr: T::Repr::from_u64_array(bits) }
736    }
737
738    /// Returns a `Vec<u64>` representing the elements of this set.
739    #[cfg(feature = "alloc")]
740    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
741    pub fn to_vec(&self) -> alloc::vec::Vec<u64> {
742        let mut vec = alloc::vec![0; T::Repr::PREFERRED_ARRAY_LEN];
743        self.__priv_repr.to_u64_slice(&mut vec);
744        vec
745    }
746
747    /// Copies the elements of this set into a `&mut [u64]`.
748    ///
749    /// If the underlying bitset will not fit in the provided slice, this method will panic.
750    pub fn copy_into_slice(&self, data: &mut [u64]) {
751        self.try_copy_into_slice(data)
752            .expect("Bitset will not fit into slice.")
753    }
754
755    /// Copies the elements of this set into a `&mut [u64]`.
756    ///
757    /// If the underlying bitset will not fit in the provided slice, this method will return
758    /// `None`. Otherwise, it will return `Some(())`.
759    #[must_use]
760    pub fn try_copy_into_slice(&self, data: &mut [u64]) -> Option<()> {
761        self.__priv_repr.to_u64_slice_opt(data)
762    }
763
764    /// Copies the elements of this set into a `&mut [u64]`.
765    ///
766    /// If the underlying bitset will not fit in the provided slice, this method will truncate any
767    /// bits that don't fit.
768    pub fn copy_into_slice_truncated(&self, data: &mut [u64]) {
769        self.__priv_repr.to_u64_slice(data)
770    }
771
772    /// Attempts to constructs a bitset from a `&[u64]`.
773    ///
774    /// If a bit that doesn't correspond to an enum variant is set, this method will panic.
775    pub fn from_slice(v: &[u64]) -> Self {
776        Self::try_from_slice(v).expect("Bitset contains invalid variants.")
777    }
778
779    /// Attempts to constructs a bitset from a `&[u64]`.
780    ///
781    /// If a bit that doesn't correspond to an enum variant is set, this method will return `None`.
782    pub fn try_from_slice(bits: &[u64]) -> Option<Self> {
783        let bits = T::Repr::from_u64_slice_opt(bits);
784        let mask = T::ALL_BITS;
785        bits.and_then(|bits| {
786            if bits.and_not(mask).is_empty() {
787                Some(EnumSet { __priv_repr: bits })
788            } else {
789                None
790            }
791        })
792    }
793
794    /// Constructs a bitset from a `&[u64]`, ignoring bits that do not correspond to a variant.
795    pub fn from_slice_truncated(bits: &[u64]) -> Self {
796        let bits = T::Repr::from_u64_slice(bits) & T::ALL_BITS;
797        EnumSet { __priv_repr: bits }
798    }
799
800    /// Constructs a bitset from a `&[u64]`, without checking for invalid bits.
801    ///
802    /// # Safety
803    ///
804    /// All bits in the provided parameter `bits` that don't correspond to an enum variant
805    /// of `T` must be set to `0`. Behavior is **undefined** if any of these bits are set
806    /// to `1`.
807    #[inline(always)]
808    pub unsafe fn from_slice_unchecked(bits: &[u64]) -> Self {
809        EnumSet { __priv_repr: T::Repr::from_u64_slice(bits) }
810    }
811}
812//endregion
813
814//region EnumSet iter
815/// The iterator used by [`EnumSet`]s.
816#[derive(Clone, Debug)]
817pub struct EnumSetIter<T: EnumSetType> {
818    iter: <T::Repr as EnumSetTypeRepr>::Iter,
819}
820impl<T: EnumSetType> EnumSetIter<T> {
821    fn new(set: EnumSet<T>) -> EnumSetIter<T> {
822        EnumSetIter { iter: set.__priv_repr.iter() }
823    }
824}
825
826impl<T: EnumSetType> EnumSet<T> {
827    /// Iterates the contents of the set in order from the least significant bit to the most
828    /// significant bit.
829    ///
830    /// Note that iterator invalidation is impossible as the iterator contains a copy of this type,
831    /// rather than holding a reference to it.
832    pub fn iter(&self) -> EnumSetIter<T> {
833        EnumSetIter::new(*self)
834    }
835}
836
837impl<T: EnumSetType> Iterator for EnumSetIter<T> {
838    type Item = T;
839
840    fn next(&mut self) -> Option<Self::Item> {
841        self.iter.next().map(|x| unsafe { T::enum_from_u32(x) })
842    }
843    fn size_hint(&self) -> (usize, Option<usize>) {
844        self.iter.size_hint()
845    }
846}
847
848impl<T: EnumSetType> DoubleEndedIterator for EnumSetIter<T> {
849    fn next_back(&mut self) -> Option<Self::Item> {
850        self.iter
851            .next_back()
852            .map(|x| unsafe { T::enum_from_u32(x) })
853    }
854}
855
856impl<T: EnumSetType> ExactSizeIterator for EnumSetIter<T> {}
857
858impl<T: EnumSetType> Extend<T> for EnumSet<T> {
859    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
860        iter.into_iter().for_each(|v| {
861            self.insert(v);
862        });
863    }
864}
865
866impl<T: EnumSetType> FromIterator<T> for EnumSet<T> {
867    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
868        let mut set = EnumSet::default();
869        set.extend(iter);
870        set
871    }
872}
873
874impl<T: EnumSetType> Extend<EnumSet<T>> for EnumSet<T> {
875    fn extend<I: IntoIterator<Item = EnumSet<T>>>(&mut self, iter: I) {
876        iter.into_iter().for_each(|v| {
877            self.insert_all(v);
878        });
879    }
880}
881
882impl<T: EnumSetType> FromIterator<EnumSet<T>> for EnumSet<T> {
883    fn from_iter<I: IntoIterator<Item = EnumSet<T>>>(iter: I) -> Self {
884        let mut set = EnumSet::default();
885        set.extend(iter);
886        set
887    }
888}
889
890impl<T: EnumSetType> IntoIterator for EnumSet<T> {
891    type Item = T;
892    type IntoIter = EnumSetIter<T>;
893
894    fn into_iter(self) -> Self::IntoIter {
895        self.iter()
896    }
897}
898impl<T: EnumSetType> Sum for EnumSet<T> {
899    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
900        iter.fold(EnumSet::empty(), |a, v| a | v)
901    }
902}
903impl<'a, T: EnumSetType> Sum<&'a EnumSet<T>> for EnumSet<T> {
904    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
905        iter.fold(EnumSet::empty(), |a, v| a | *v)
906    }
907}
908impl<T: EnumSetType> Sum<T> for EnumSet<T> {
909    fn sum<I: Iterator<Item = T>>(iter: I) -> Self {
910        iter.fold(EnumSet::empty(), |a, v| a | v)
911    }
912}
913impl<'a, T: EnumSetType> Sum<&'a T> for EnumSet<T> {
914    fn sum<I: Iterator<Item = &'a T>>(iter: I) -> Self {
915        iter.fold(EnumSet::empty(), |a, v| a | *v)
916    }
917}
918//endregion