Coverage Report

Created: 2025-11-02 06:39

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/enumset-1.1.2/src/set.rs
Line
Count
Source
1
use crate::repr::EnumSetTypeRepr;
2
use crate::traits::EnumSetType;
3
use crate::EnumSetTypeWithRepr;
4
use core::cmp::Ordering;
5
use core::fmt::{Debug, Formatter};
6
use core::hash::{Hash, Hasher};
7
use core::iter::Sum;
8
use core::ops::{
9
    BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Not, Sub, SubAssign,
10
};
11
12
#[cfg(feature = "serde")]
13
use {
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)]
125
pub 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
133
impl<T: EnumSetType> EnumSet<T> {
134
    /// An empty `EnumSet`.
135
    ///
136
    /// This is available as a constant for use in constant expressions.
137
    pub const EMPTY: Self = EnumSet { __priv_repr: T::Repr::EMPTY };
138
139
    /// An `EnumSet` containing all valid variants of the enum.
140
    ///
141
    /// This is available as a constant for use in constant expressions.
142
    pub const ALL: Self = EnumSet { __priv_repr: T::ALL_BITS };
143
144
    /// Creates an empty `EnumSet`.
145
    #[inline(always)]
146
442
    pub fn new() -> Self {
147
442
        Self::EMPTY
148
442
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState>>::new
<enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace>>::new
Line
Count
Source
146
442
    pub fn new() -> Self {
147
442
        Self::EMPTY
148
442
    }
149
150
    /// Returns an `EnumSet` containing a single element.
151
    #[inline(always)]
152
0
    pub fn only(t: T) -> Self {
153
0
        let mut set = Self::new();
154
0
        set.insert(t);
155
0
        set
156
0
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState>>::only
Unexecuted instantiation: <enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace>>::only
157
158
    /// Creates an empty `EnumSet`.
159
    ///
160
    /// This is an alias for [`EnumSet::new`].
161
    #[inline(always)]
162
1.69k
    pub fn empty() -> Self {
163
1.69k
        Self::EMPTY
164
1.69k
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState>>::empty
<enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace>>::empty
Line
Count
Source
162
1.69k
    pub fn empty() -> Self {
163
1.69k
        Self::EMPTY
164
1.69k
    }
165
166
    /// Returns an `EnumSet` containing all valid variants of the enum.
167
    #[inline(always)]
168
0
    pub fn all() -> Self {
169
0
        Self::ALL
170
0
    }
171
172
    /// Total number of bits used by this type. Note that the actual amount of space used is
173
    /// rounded up to the next highest integer type (`u8`, `u16`, `u32`, `u64`, or `u128`).
174
    ///
175
    /// This is the same as [`EnumSet::variant_count`] except in enums with "sparse" variants.
176
    /// (e.g. `enum Foo { A = 10, B = 20 }`)
177
    #[inline(always)]
178
    pub fn bit_width() -> u32 {
179
        T::BIT_WIDTH
180
    }
181
182
    /// The number of valid variants that this type can contain.
183
    ///
184
    /// This is the same as [`EnumSet::bit_width`] except in enums with "sparse" variants.
185
    /// (e.g. `enum Foo { A = 10, B = 20 }`)
186
    #[inline(always)]
187
    pub fn variant_count() -> u32 {
188
        T::VARIANT_COUNT
189
    }
190
191
    /// Returns the number of elements in this set.
192
    #[inline(always)]
193
    pub fn len(&self) -> usize {
194
        self.__priv_repr.count_ones() as usize
195
    }
196
    /// Returns `true` if the set contains no elements.
197
    #[inline(always)]
198
    pub fn is_empty(&self) -> bool {
199
        self.__priv_repr.is_empty()
200
    }
201
    /// Removes all elements from the set.
202
    #[inline(always)]
203
    pub fn clear(&mut self) {
204
        self.__priv_repr = T::Repr::EMPTY;
205
    }
206
207
    /// Returns `true` if `self` has no elements in common with `other`. This is equivalent to
208
    /// checking for an empty intersection.
209
    #[inline(always)]
210
    pub fn is_disjoint(&self, other: Self) -> bool {
211
        (*self & other).is_empty()
212
    }
213
    /// Returns `true` if the set is a superset of another, i.e., `self` contains at least all the
214
    /// values in `other`.
215
    #[inline(always)]
216
    pub fn is_superset(&self, other: Self) -> bool {
217
        (*self & other).__priv_repr == other.__priv_repr
218
    }
219
    /// Returns `true` if the set is a subset of another, i.e., `other` contains at least all
220
    /// the values in `self`.
221
    #[inline(always)]
222
    pub fn is_subset(&self, other: Self) -> bool {
223
        other.is_superset(*self)
224
    }
225
226
    /// Returns a set containing any elements present in either set.
227
    #[inline(always)]
228
0
    pub fn union(&self, other: Self) -> Self {
229
0
        EnumSet { __priv_repr: self.__priv_repr | other.__priv_repr }
230
0
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState>>::union
Unexecuted instantiation: <enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace>>::union
231
    /// Returns a set containing every element present in both sets.
232
    #[inline(always)]
233
0
    pub fn intersection(&self, other: Self) -> Self {
234
0
        EnumSet { __priv_repr: self.__priv_repr & other.__priv_repr }
235
0
    }
236
    /// Returns a set containing element present in `self` but not in `other`.
237
    #[inline(always)]
238
0
    pub fn difference(&self, other: Self) -> Self {
239
0
        EnumSet { __priv_repr: self.__priv_repr.and_not(other.__priv_repr) }
240
0
    }
241
    /// Returns a set containing every element present in either `self` or `other`, but is not
242
    /// present in both.
243
    #[inline(always)]
244
    pub fn symmetrical_difference(&self, other: Self) -> Self {
245
        EnumSet { __priv_repr: self.__priv_repr ^ other.__priv_repr }
246
    }
247
    /// Returns a set containing all enum variants not in this set.
248
    #[inline(always)]
249
0
    pub fn complement(&self) -> Self {
250
0
        EnumSet { __priv_repr: !self.__priv_repr & T::ALL_BITS }
251
0
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState>>::complement
Unexecuted instantiation: <enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace>>::complement
252
253
    /// Checks whether this set contains a value.
254
    #[inline(always)]
255
2.57k
    pub fn contains(&self, value: T) -> bool {
256
2.57k
        self.__priv_repr.has_bit(value.enum_into_u32())
257
2.57k
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState>>::contains
<enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace>>::contains
Line
Count
Source
255
2.57k
    pub fn contains(&self, value: T) -> bool {
256
2.57k
        self.__priv_repr.has_bit(value.enum_into_u32())
257
2.57k
    }
258
259
    /// Adds a value to this set.
260
    ///
261
    /// If the set did not have this value present, `true` is returned.
262
    ///
263
    /// If the set did have this value present, `false` is returned.
264
    #[inline(always)]
265
0
    pub fn insert(&mut self, value: T) -> bool {
266
0
        let contains = !self.contains(value);
267
0
        self.__priv_repr.add_bit(value.enum_into_u32());
268
0
        contains
269
0
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState>>::insert
Unexecuted instantiation: <enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace>>::insert
270
    /// Removes a value from this set. Returns whether the value was present in the set.
271
    #[inline(always)]
272
0
    pub fn remove(&mut self, value: T) -> bool {
273
0
        let contains = self.contains(value);
274
0
        self.__priv_repr.remove_bit(value.enum_into_u32());
275
0
        contains
276
0
    }
277
278
    /// Adds all elements in another set to this one.
279
    #[inline(always)]
280
    pub fn insert_all(&mut self, other: Self) {
281
        self.__priv_repr = self.__priv_repr | other.__priv_repr
282
    }
283
    /// Removes all values in another set from this one.
284
    #[inline(always)]
285
    pub fn remove_all(&mut self, other: Self) {
286
        self.__priv_repr = self.__priv_repr.and_not(other.__priv_repr);
287
    }
288
}
289
290
impl<T: EnumSetType> Default for EnumSet<T> {
291
    /// Returns an empty set.
292
442
    fn default() -> Self {
293
442
        Self::new()
294
442
    }
295
}
296
297
impl<T: EnumSetType, O: Into<EnumSet<T>>> Sub<O> for EnumSet<T> {
298
    type Output = Self;
299
    #[inline(always)]
300
0
    fn sub(self, other: O) -> Self::Output {
301
0
        self.difference(other.into())
302
0
    }
303
}
304
impl<T: EnumSetType, O: Into<EnumSet<T>>> BitAnd<O> for EnumSet<T> {
305
    type Output = Self;
306
    #[inline(always)]
307
0
    fn bitand(self, other: O) -> Self::Output {
308
0
        self.intersection(other.into())
309
0
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState> as core::ops::bit::BitAnd<neqo_http3::headers_checks::PseudoHeaderState>>::bitand
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState> as core::ops::bit::BitAnd>::bitand
310
}
311
impl<T: EnumSetType, O: Into<EnumSet<T>>> BitOr<O> for EnumSet<T> {
312
    type Output = Self;
313
    #[inline(always)]
314
0
    fn bitor(self, other: O) -> Self::Output {
315
0
        self.union(other.into())
316
0
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState> as core::ops::bit::BitOr<neqo_http3::headers_checks::PseudoHeaderState>>::bitor
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState> as core::ops::bit::BitOr>::bitor
Unexecuted instantiation: <enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace> as core::ops::bit::BitOr>::bitor
317
}
318
impl<T: EnumSetType, O: Into<EnumSet<T>>> BitXor<O> for EnumSet<T> {
319
    type Output = Self;
320
    #[inline(always)]
321
    fn bitxor(self, other: O) -> Self::Output {
322
        self.symmetrical_difference(other.into())
323
    }
324
}
325
326
impl<T: EnumSetType, O: Into<EnumSet<T>>> SubAssign<O> for EnumSet<T> {
327
    #[inline(always)]
328
0
    fn sub_assign(&mut self, rhs: O) {
329
0
        *self = *self - rhs;
330
0
    }
331
}
332
impl<T: EnumSetType, O: Into<EnumSet<T>>> BitAndAssign<O> for EnumSet<T> {
333
    #[inline(always)]
334
    fn bitand_assign(&mut self, rhs: O) {
335
        *self = *self & rhs;
336
    }
337
}
338
impl<T: EnumSetType, O: Into<EnumSet<T>>> BitOrAssign<O> for EnumSet<T> {
339
    #[inline(always)]
340
0
    fn bitor_assign(&mut self, rhs: O) {
341
0
        *self = *self | rhs;
342
0
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState> as core::ops::bit::BitOrAssign<neqo_http3::headers_checks::PseudoHeaderState>>::bitor_assign
Unexecuted instantiation: <enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace> as core::ops::bit::BitOrAssign>::bitor_assign
343
}
344
impl<T: EnumSetType, O: Into<EnumSet<T>>> BitXorAssign<O> for EnumSet<T> {
345
    #[inline(always)]
346
    fn bitxor_assign(&mut self, rhs: O) {
347
        *self = *self ^ rhs;
348
    }
349
}
350
351
impl<T: EnumSetType> Not for EnumSet<T> {
352
    type Output = Self;
353
    #[inline(always)]
354
0
    fn not(self) -> Self::Output {
355
0
        self.complement()
356
0
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState> as core::ops::bit::Not>::not
Unexecuted instantiation: <enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace> as core::ops::bit::Not>::not
357
}
358
359
impl<T: EnumSetType> From<T> for EnumSet<T> {
360
0
    fn from(t: T) -> Self {
361
0
        EnumSet::only(t)
362
0
    }
Unexecuted instantiation: <enumset::set::EnumSet<neqo_http3::headers_checks::PseudoHeaderState> as core::convert::From<neqo_http3::headers_checks::PseudoHeaderState>>::from
Unexecuted instantiation: <enumset::set::EnumSet<neqo_transport::tracking::PacketNumberSpace> as core::convert::From<neqo_transport::tracking::PacketNumberSpace>>::from
363
}
364
365
impl<T: EnumSetType> PartialEq<T> for EnumSet<T> {
366
    fn eq(&self, other: &T) -> bool {
367
        self.__priv_repr == EnumSet::only(*other).__priv_repr
368
    }
369
}
370
impl<T: EnumSetType + Debug> Debug for EnumSet<T> {
371
0
    fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
372
0
        let mut is_first = true;
373
0
        f.write_str("EnumSet(")?;
374
0
        for v in self.iter() {
375
0
            if !is_first {
376
0
                f.write_str(" | ")?;
377
0
            }
378
0
            is_first = false;
379
0
            v.fmt(f)?;
380
        }
381
0
        f.write_str(")")?;
382
0
        Ok(())
383
0
    }
384
}
385
386
#[allow(clippy::derived_hash_with_manual_eq)] // This impl exists to change trait bounds only.
387
impl<T: EnumSetType> Hash for EnumSet<T> {
388
    fn hash<H: Hasher>(&self, state: &mut H) {
389
        self.__priv_repr.hash(state)
390
    }
391
}
392
impl<T: EnumSetType> PartialOrd for EnumSet<T> {
393
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
394
        self.__priv_repr.partial_cmp(&other.__priv_repr)
395
    }
396
}
397
impl<T: EnumSetType> Ord for EnumSet<T> {
398
    fn cmp(&self, other: &Self) -> Ordering {
399
        self.__priv_repr.cmp(&other.__priv_repr)
400
    }
401
}
402
403
#[cfg(feature = "serde")]
404
impl<T: EnumSetType> Serialize for EnumSet<T> {
405
    fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
406
        T::serialize(*self, serializer)
407
    }
408
}
409
410
#[cfg(feature = "serde")]
411
impl<'de, T: EnumSetType> Deserialize<'de> for EnumSet<T> {
412
    fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
413
        T::deserialize(deserializer)
414
    }
415
}
416
//endregion
417
418
//region EnumSet conversions
419
impl<T: EnumSetType + EnumSetTypeWithRepr> EnumSet<T> {
420
    /// Returns a `T::Repr` representing the elements of this set.
421
    ///
422
    /// Unlike the other `as_*` methods, this method is zero-cost and guaranteed not to fail,
423
    /// panic or truncate any bits.
424
    ///
425
    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
426
    /// annotation.
427
    #[inline(always)]
428
    pub fn as_repr(&self) -> <T as EnumSetTypeWithRepr>::Repr {
429
        self.__priv_repr
430
    }
431
432
    /// Constructs a bitset from a `T::Repr` without checking for invalid bits.
433
    ///
434
    /// Unlike the other `from_*` methods, this method is zero-cost and guaranteed not to fail,
435
    /// panic or truncate any bits, provided the conditions under “Safety” are upheld.
436
    ///
437
    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
438
    /// annotation.
439
    ///
440
    /// # Safety
441
    ///
442
    /// All bits in the provided parameter `bits` that don't correspond to an enum variant of
443
    /// `T` must be set to `0`. Behavior is **undefined** if any of these bits are set to `1`.
444
    #[inline(always)]
445
    pub unsafe fn from_repr_unchecked(bits: <T as EnumSetTypeWithRepr>::Repr) -> Self {
446
        Self { __priv_repr: bits }
447
    }
448
449
    /// Constructs a bitset from a `T::Repr`.
450
    ///
451
    /// If a bit that doesn't correspond to an enum variant is set, this
452
    /// method will panic.
453
    ///
454
    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
455
    /// annotation.
456
    #[inline(always)]
457
    pub fn from_repr(bits: <T as EnumSetTypeWithRepr>::Repr) -> Self {
458
        Self::try_from_repr(bits).expect("Bitset contains invalid variants.")
459
    }
460
461
    /// Attempts to constructs a bitset from a `T::Repr`.
462
    ///
463
    /// If a bit that doesn't correspond to an enum variant is set, this
464
    /// method will return `None`.
465
    ///
466
    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
467
    /// annotation.
468
    #[inline(always)]
469
    pub fn try_from_repr(bits: <T as EnumSetTypeWithRepr>::Repr) -> Option<Self> {
470
        let mask = Self::all().__priv_repr;
471
        if bits.and_not(mask).is_empty() {
472
            Some(EnumSet { __priv_repr: bits })
473
        } else {
474
            None
475
        }
476
    }
477
478
    /// Constructs a bitset from a `T::Repr`, ignoring invalid variants.
479
    ///
480
    /// In order to use this method, the definition of `T` must have the `#[enumset(repr = "…")]`
481
    /// annotation.
482
    #[inline(always)]
483
    pub fn from_repr_truncated(bits: <T as EnumSetTypeWithRepr>::Repr) -> Self {
484
        let mask = Self::all().as_repr();
485
        let bits = bits & mask;
486
        EnumSet { __priv_repr: bits }
487
    }
488
}
489
490
/// Helper macro for generating conversion functions.
491
macro_rules! conversion_impls {
492
    (
493
        $(for_num!(
494
            $underlying:ty, $underlying_str:expr,
495
            $from_fn:ident $to_fn:ident $from_fn_opt:ident $to_fn_opt:ident,
496
            $from:ident $try_from:ident $from_truncated:ident $from_unchecked:ident,
497
            $to:ident $try_to:ident $to_truncated:ident
498
        );)*
499
    ) => {
500
        impl<T: EnumSetType> EnumSet<T> {$(
501
            #[doc = "Returns a `"]
502
            #[doc = $underlying_str]
503
            #[doc = "` representing the elements of this set.\n\nIf the underlying bitset will \
504
                     not fit in a `"]
505
            #[doc = $underlying_str]
506
            #[doc = "`, this method will panic."]
507
            #[inline(always)]
508
            pub fn $to(&self) -> $underlying {
509
                self.$try_to().expect("Bitset will not fit into this type.")
510
            }
511
512
            #[doc = "Tries to return a `"]
513
            #[doc = $underlying_str]
514
            #[doc = "` representing the elements of this set.\n\nIf the underlying bitset will \
515
                     not fit in a `"]
516
            #[doc = $underlying_str]
517
            #[doc = "`, this method will panic."]
518
            #[inline(always)]
519
            pub fn $try_to(&self) -> Option<$underlying> {
520
                EnumSetTypeRepr::$to_fn_opt(&self.__priv_repr)
521
            }
522
523
            #[doc = "Returns a truncated `"]
524
            #[doc = $underlying_str]
525
            #[doc = "` representing the elements of this set.\n\nIf the underlying bitset will \
526
                     not fit in a `"]
527
            #[doc = $underlying_str]
528
            #[doc = "`, this method will truncate any bits that don't fit."]
529
            #[inline(always)]
530
            pub fn $to_truncated(&self) -> $underlying {
531
                EnumSetTypeRepr::$to_fn(&self.__priv_repr)
532
            }
533
534
            #[doc = "Constructs a bitset from a `"]
535
            #[doc = $underlying_str]
536
            #[doc = "`.\n\nIf a bit that doesn't correspond to an enum variant is set, this \
537
                     method will panic."]
538
            #[inline(always)]
539
            pub fn $from(bits: $underlying) -> Self {
540
                Self::$try_from(bits).expect("Bitset contains invalid variants.")
541
            }
542
543
            #[doc = "Attempts to constructs a bitset from a `"]
544
            #[doc = $underlying_str]
545
            #[doc = "`.\n\nIf a bit that doesn't correspond to an enum variant is set, this \
546
                     method will return `None`."]
547
            #[inline(always)]
548
            pub fn $try_from(bits: $underlying) -> Option<Self> {
549
                let bits = T::Repr::$from_fn_opt(bits);
550
                let mask = T::ALL_BITS;
551
                bits.and_then(|bits| if bits.and_not(mask).is_empty() {
552
                    Some(EnumSet { __priv_repr: bits })
553
                } else {
554
                    None
555
                })
556
            }
557
558
            #[doc = "Constructs a bitset from a `"]
559
            #[doc = $underlying_str]
560
            #[doc = "`, ignoring bits that do not correspond to a variant."]
561
            #[inline(always)]
562
            pub fn $from_truncated(bits: $underlying) -> Self {
563
                let mask = Self::all().$to_truncated();
564
                let bits = <T::Repr as EnumSetTypeRepr>::$from_fn(bits & mask);
565
                EnumSet { __priv_repr: bits }
566
            }
567
568
            #[doc = "Constructs a bitset from a `"]
569
            #[doc = $underlying_str]
570
            #[doc = "`, without checking for invalid bits."]
571
            ///
572
            /// # Safety
573
            ///
574
            /// All bits in the provided parameter `bits` that don't correspond to an enum variant
575
            /// of `T` must be set to `0`. Behavior is **undefined** if any of these bits are set
576
            /// to `1`.
577
            #[inline(always)]
578
            pub unsafe fn $from_unchecked(bits: $underlying) -> Self {
579
                EnumSet { __priv_repr: <T::Repr as EnumSetTypeRepr>::$from_fn(bits) }
580
            }
581
        )*}
582
    }
583
}
584
conversion_impls! {
585
    for_num!(u8, "u8",
586
             from_u8 to_u8 from_u8_opt to_u8_opt,
587
             from_u8 try_from_u8 from_u8_truncated from_u8_unchecked,
588
             as_u8 try_as_u8 as_u8_truncated);
589
    for_num!(u16, "u16",
590
             from_u16 to_u16 from_u16_opt to_u16_opt,
591
             from_u16 try_from_u16 from_u16_truncated from_u16_unchecked,
592
             as_u16 try_as_u16 as_u16_truncated);
593
    for_num!(u32, "u32",
594
             from_u32 to_u32 from_u32_opt to_u32_opt,
595
             from_u32 try_from_u32 from_u32_truncated from_u32_unchecked,
596
             as_u32 try_as_u32 as_u32_truncated);
597
    for_num!(u64, "u64",
598
             from_u64 to_u64 from_u64_opt to_u64_opt,
599
             from_u64 try_from_u64 from_u64_truncated from_u64_unchecked,
600
             as_u64 try_as_u64 as_u64_truncated);
601
    for_num!(u128, "u128",
602
             from_u128 to_u128 from_u128_opt to_u128_opt,
603
             from_u128 try_from_u128 from_u128_truncated from_u128_unchecked,
604
             as_u128 try_as_u128 as_u128_truncated);
605
    for_num!(usize, "usize",
606
             from_usize to_usize from_usize_opt to_usize_opt,
607
             from_usize try_from_usize from_usize_truncated from_usize_unchecked,
608
             as_usize try_as_usize as_usize_truncated);
609
}
610
611
impl<T: EnumSetType> EnumSet<T> {
612
    /// Returns an `[u64; O]` representing the elements of this set.
613
    ///
614
    /// If the underlying bitset will not fit in a `[u64; O]`, this method will panic.
615
    pub fn as_array<const O: usize>(&self) -> [u64; O] {
616
        self.try_as_array()
617
            .expect("Bitset will not fit into this type.")
618
    }
619
620
    /// Returns an `[u64; O]` representing the elements of this set.
621
    ///
622
    /// If the underlying bitset will not fit in a `[u64; O]`, this method will instead return
623
    /// `None`.
624
    pub fn try_as_array<const O: usize>(&self) -> Option<[u64; O]> {
625
        self.__priv_repr.to_u64_array_opt()
626
    }
627
628
    /// Returns an `[u64; O]` representing the elements of this set.
629
    ///
630
    /// If the underlying bitset will not fit in a `[u64; O]`, this method will truncate any bits
631
    /// that don't fit.
632
    pub fn as_array_truncated<const O: usize>(&self) -> [u64; O] {
633
        self.__priv_repr.to_u64_array()
634
    }
635
636
    /// Attempts to constructs a bitset from a `[u64; O]`.
637
    ///
638
    /// If a bit that doesn't correspond to an enum variant is set, this method will panic.
639
    pub fn from_array<const O: usize>(v: [u64; O]) -> Self {
640
        Self::try_from_array(v).expect("Bitset contains invalid variants.")
641
    }
642
643
    /// Attempts to constructs a bitset from a `[u64; O]`.
644
    ///
645
    /// If a bit that doesn't correspond to an enum variant is set, this method will return `None`.
646
    pub fn try_from_array<const O: usize>(bits: [u64; O]) -> Option<Self> {
647
        let bits = T::Repr::from_u64_array_opt::<O>(bits);
648
        let mask = T::ALL_BITS;
649
        bits.and_then(|bits| {
650
            if bits.and_not(mask).is_empty() {
651
                Some(EnumSet { __priv_repr: bits })
652
            } else {
653
                None
654
            }
655
        })
656
    }
657
658
    /// Constructs a bitset from a `[u64; O]`, ignoring bits that do not correspond to a variant.
659
    pub fn from_array_truncated<const O: usize>(bits: [u64; O]) -> Self {
660
        let bits = T::Repr::from_u64_array(bits) & T::ALL_BITS;
661
        EnumSet { __priv_repr: bits }
662
    }
663
664
    /// Constructs a bitset from a `[u64; O]`, without checking for invalid bits.
665
    ///
666
    /// # Safety
667
    ///
668
    /// All bits in the provided parameter `bits` that don't correspond to an enum variant
669
    /// of `T` must be set to `0`. Behavior is **undefined** if any of these bits are set
670
    /// to `1`.
671
    #[inline(always)]
672
    pub unsafe fn from_array_unchecked<const O: usize>(bits: [u64; O]) -> Self {
673
        EnumSet { __priv_repr: T::Repr::from_u64_array(bits) }
674
    }
675
676
    /// Returns a `Vec<u64>` representing the elements of this set.
677
    #[cfg(feature = "alloc")]
678
    #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
679
    pub fn to_vec(&self) -> alloc::vec::Vec<u64> {
680
        let mut vec = alloc::vec![0; T::Repr::PREFERRED_ARRAY_LEN];
681
        self.__priv_repr.to_u64_slice(&mut vec);
682
        vec
683
    }
684
685
    /// Copies the elements of this set into a `&mut [u64]`.
686
    ///
687
    /// If the underlying bitset will not fit in the provided slice, this method will panic.
688
    pub fn copy_into_slice(&self, data: &mut [u64]) {
689
        self.try_copy_into_slice(data)
690
            .expect("Bitset will not fit into slice.")
691
    }
692
693
    /// Copies the elements of this set into a `&mut [u64]`.
694
    ///
695
    /// If the underlying bitset will not fit in the provided slice, this method will return
696
    /// `None`. Otherwise, it will return `Some(())`.
697
    #[must_use]
698
    pub fn try_copy_into_slice(&self, data: &mut [u64]) -> Option<()> {
699
        self.__priv_repr.to_u64_slice_opt(data)
700
    }
701
702
    /// Copies the elements of this set into a `&mut [u64]`.
703
    ///
704
    /// If the underlying bitset will not fit in the provided slice, this method will truncate any
705
    /// bits that don't fit.
706
    pub fn copy_into_slice_truncated(&self, data: &mut [u64]) {
707
        self.__priv_repr.to_u64_slice(data)
708
    }
709
710
    /// Attempts to constructs a bitset from a `&[u64]`.
711
    ///
712
    /// If a bit that doesn't correspond to an enum variant is set, this method will panic.
713
    pub fn from_slice(v: &[u64]) -> Self {
714
        Self::try_from_slice(v).expect("Bitset contains invalid variants.")
715
    }
716
717
    /// Attempts to constructs a bitset from a `&[u64]`.
718
    ///
719
    /// If a bit that doesn't correspond to an enum variant is set, this method will return `None`.
720
    pub fn try_from_slice(bits: &[u64]) -> Option<Self> {
721
        let bits = T::Repr::from_u64_slice_opt(bits);
722
        let mask = T::ALL_BITS;
723
        bits.and_then(|bits| {
724
            if bits.and_not(mask).is_empty() {
725
                Some(EnumSet { __priv_repr: bits })
726
            } else {
727
                None
728
            }
729
        })
730
    }
731
732
    /// Constructs a bitset from a `&[u64]`, ignoring bits that do not correspond to a variant.
733
    pub fn from_slice_truncated(bits: &[u64]) -> Self {
734
        let bits = T::Repr::from_u64_slice(bits) & T::ALL_BITS;
735
        EnumSet { __priv_repr: bits }
736
    }
737
738
    /// Constructs a bitset from a `&[u64]`, without checking for invalid bits.
739
    ///
740
    /// # Safety
741
    ///
742
    /// All bits in the provided parameter `bits` that don't correspond to an enum variant
743
    /// of `T` must be set to `0`. Behavior is **undefined** if any of these bits are set
744
    /// to `1`.
745
    #[inline(always)]
746
    pub unsafe fn from_slice_unchecked(bits: &[u64]) -> Self {
747
        EnumSet { __priv_repr: T::Repr::from_u64_slice(bits) }
748
    }
749
}
750
//endregion
751
752
//region EnumSet iter
753
/// The iterator used by [`EnumSet`]s.
754
#[derive(Clone, Debug)]
755
pub struct EnumSetIter<T: EnumSetType> {
756
    iter: <T::Repr as EnumSetTypeRepr>::Iter,
757
}
758
impl<T: EnumSetType> EnumSetIter<T> {
759
0
    fn new(set: EnumSet<T>) -> EnumSetIter<T> {
760
0
        EnumSetIter { iter: set.__priv_repr.iter() }
761
0
    }
762
}
763
764
impl<T: EnumSetType> EnumSet<T> {
765
    /// Iterates the contents of the set in order from the least significant bit to the most
766
    /// significant bit.
767
    ///
768
    /// Note that iterator invalidation is impossible as the iterator contains a copy of this type,
769
    /// rather than holding a reference to it.
770
0
    pub fn iter(&self) -> EnumSetIter<T> {
771
0
        EnumSetIter::new(*self)
772
0
    }
773
}
774
775
impl<T: EnumSetType> Iterator for EnumSetIter<T> {
776
    type Item = T;
777
778
0
    fn next(&mut self) -> Option<Self::Item> {
779
0
        self.iter.next().map(|x| unsafe { T::enum_from_u32(x) })
780
0
    }
781
    fn size_hint(&self) -> (usize, Option<usize>) {
782
        self.iter.size_hint()
783
    }
784
}
785
786
impl<T: EnumSetType> DoubleEndedIterator for EnumSetIter<T> {
787
    fn next_back(&mut self) -> Option<Self::Item> {
788
        self.iter
789
            .next_back()
790
            .map(|x| unsafe { T::enum_from_u32(x) })
791
    }
792
}
793
794
impl<T: EnumSetType> ExactSizeIterator for EnumSetIter<T> {}
795
796
impl<T: EnumSetType> Extend<T> for EnumSet<T> {
797
    fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
798
        iter.into_iter().for_each(|v| {
799
            self.insert(v);
800
        });
801
    }
802
}
803
804
impl<T: EnumSetType> FromIterator<T> for EnumSet<T> {
805
    fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
806
        let mut set = EnumSet::default();
807
        set.extend(iter);
808
        set
809
    }
810
}
811
812
impl<T: EnumSetType> Extend<EnumSet<T>> for EnumSet<T> {
813
    fn extend<I: IntoIterator<Item = EnumSet<T>>>(&mut self, iter: I) {
814
        iter.into_iter().for_each(|v| {
815
            self.insert_all(v);
816
        });
817
    }
818
}
819
820
impl<T: EnumSetType> FromIterator<EnumSet<T>> for EnumSet<T> {
821
    fn from_iter<I: IntoIterator<Item = EnumSet<T>>>(iter: I) -> Self {
822
        let mut set = EnumSet::default();
823
        set.extend(iter);
824
        set
825
    }
826
}
827
828
impl<T: EnumSetType> IntoIterator for EnumSet<T> {
829
    type Item = T;
830
    type IntoIter = EnumSetIter<T>;
831
832
    fn into_iter(self) -> Self::IntoIter {
833
        self.iter()
834
    }
835
}
836
impl<T: EnumSetType> Sum for EnumSet<T> {
837
    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
838
        iter.fold(EnumSet::empty(), |a, v| a | v)
839
    }
840
}
841
impl<'a, T: EnumSetType> Sum<&'a EnumSet<T>> for EnumSet<T> {
842
    fn sum<I: Iterator<Item = &'a Self>>(iter: I) -> Self {
843
        iter.fold(EnumSet::empty(), |a, v| a | *v)
844
    }
845
}
846
impl<T: EnumSetType> Sum<T> for EnumSet<T> {
847
    fn sum<I: Iterator<Item = T>>(iter: I) -> Self {
848
        iter.fold(EnumSet::empty(), |a, v| a | v)
849
    }
850
}
851
impl<'a, T: EnumSetType> Sum<&'a T> for EnumSet<T> {
852
    fn sum<I: Iterator<Item = &'a T>>(iter: I) -> Self {
853
        iter.fold(EnumSet::empty(), |a, v| a | *v)
854
    }
855
}
856
//endregion