]> git.lizzy.rs Git - enumset.git/blob - src/lib.rs
Allow empty enum_set! entries (for use with macros).
[enumset.git] / src / lib.rs
1 #![cfg_attr(all(test, feature = "i128"), feature(i128, i128_type))]
2
3 //! A library for defining enums that can be used in compact bit sets.
4 //!
5 //! It supports enums up to 64 variants on stable Rust, and up to 128 variants on nightly Rust with
6 //! the `i128` feature enabled.
7 //!
8 //! # Defining enums for use with EnumSet
9 //!
10 //! Enums to be used with [`EnumSet`] should be defined through the [`enum_set_type!`] macro:
11 //!
12 //! ```rust
13 //! # #[macro_use] extern crate enumset;
14 //! # use enumset::*;
15 //! enum_set_type! {
16 //!     /// Documentation for the enum
17 //!     pub enum Enum {
18 //!         A, B, C, D, E, F, G,
19 //!         #[doc(hidden)] __NonExhaustive,
20 //!     }
21 //! }
22 //! # fn main() { }
23 //! ```
24 //!
25 //! # Working with EnumSets
26 //!
27 //! EnumSets can be constructed via [`EnumSet::new()`] like a normal set. In addition,
28 //! [`enum_set_type!`] creates operator overloads that allow you to create EnumSets like so:
29 //!
30 //! ```rust
31 //! # #[macro_use] extern crate enumset;
32 //! # use enumset::*;
33 //! # enum_set_type! {
34 //! #      pub enum Enum {
35 //! #        A, B, C, D, E, F, G,
36 //! #    }
37 //! # }
38 //! # fn main() {
39 //! let new_set = Enum::A | Enum::C | Enum::G;
40 //! assert_eq!(new_set.len(), 3);
41 //! # }
42 //! ```
43 //!
44 //! The [`enum_set!`] macro also allows you to create constant EnumSets:
45 //!
46 //! ```rust
47 //! # #[macro_use] extern crate enumset;
48 //! # use enumset::*;
49 //! # enum_set_type! {
50 //! #     enum Enum { A, B, C }
51 //! # }
52 //! # fn main() {
53 //! const CONST_SET: EnumSet<Enum> = enum_set!(Enum, Enum::A | Enum::B);
54 //! assert_eq!(CONST_SET, Enum::A | Enum::B);
55 //! # }
56 //! ```
57 //!
58 //! Mutable operations on the [`EnumSet`] otherwise work basically as expected:
59 //!
60 //! ```rust
61 //! # #[macro_use] extern crate enumset;
62 //! # use enumset::*;
63 //! # enum_set_type! {
64 //! #      pub enum Enum {
65 //! #        A, B, C, D, E, F, G,
66 //! #    }
67 //! # }
68 //! # fn main() {
69 //! let mut set = EnumSet::new();
70 //! set.insert(Enum::A);
71 //! set.insert_all(Enum::E | Enum::G);
72 //! assert!(set.contains(Enum::A));
73 //! assert!(!set.contains(Enum::B));
74 //! assert_eq!(set, Enum::A | Enum::E | Enum::G);
75 //! # }
76 //! ```
77 //!
78 //! [`EnumSet`]: ./struct.EnumSet.html
79 //! [`EnumSet::new()`]: ./struct.EnumSet.html#method.new
80 //! [`enum_set!`]: ./macro.enum_set.html
81 //! [`enum_set_type!`]: ./macro.enum_set_type.html
82
83 use std::fmt;
84 use std::fmt::{Debug, Formatter};
85 use std::hash::Hash;
86 use std::ops::*;
87
88 #[doc(hidden)]
89 pub trait EnumSetType : Copy {
90     type Repr: Shl<u8, Output = Self::Repr> + Eq + Not<Output = Self::Repr> +
91                Sub<Output = Self::Repr> + BitOr<Output = Self::Repr> +
92                BitAnd<Output = Self::Repr> + BitXor<Output = Self::Repr> +
93                BitOrAssign + BitAndAssign + Copy + Debug + Ord + Eq + Hash;
94     const ZERO: Self::Repr;
95     const ONE : Self::Repr;
96     const VARIANT_COUNT: u8;
97
98     fn count_ones(val: Self::Repr) -> usize;
99     fn into_u8(self) -> u8;
100     fn from_u8(val: u8) -> Self;
101 }
102
103 /// An efficient set type for enums created with the [`enum_set_type!`](./macro.enum_set_type.html)
104 /// macro.
105 #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash)]
106 pub struct EnumSet<T : EnumSetType>(#[doc(hidden)] pub T::Repr);
107 impl <T : EnumSetType> EnumSet<T> {
108     fn mask(bit: u8) -> T::Repr {
109         T::ONE << bit
110     }
111     fn has_bit(&self, bit: u8) -> bool {
112         let mask = Self::mask(bit);
113         self.0 & mask == mask
114     }
115
116     /// Returns an empty set.
117     pub fn new() -> Self {
118         EnumSet(T::ZERO)
119     }
120
121     /// Returns the number of values in this set.
122     pub fn len(&self) -> usize {
123         T::count_ones(self.0)
124     }
125     /// Checks if the set is empty.
126     pub fn is_empty(&self) -> bool {
127         self.0 == T::ZERO
128     }
129     /// Removes all elements from the set.
130     pub fn clear(&mut self) {
131         self.0 = T::ZERO
132     }
133
134     /// Checks if this set shares no elements with another.
135     pub fn is_disjoint(&self, other: Self) -> bool {
136         self.0 & other.0 == T::ZERO
137     }
138     /// Checks if all elements in another set are in this set.
139     pub fn is_superset(&self, other: Self) -> bool {
140         other.0 & self.0 == other.0
141     }
142     /// Checks if all elements of this set are in another set.
143     pub fn is_subset(&self, other: Self) -> bool {
144         other.is_superset(*self)
145     }
146
147     /// Returns a set containing the union of all elements in both sets.
148     pub fn union(&self, other: Self) -> Self {
149         EnumSet(self.0 | other.0)
150     }
151     /// Returns a set containing all elements in common with another set.
152     pub fn intersection(&self, other: Self) -> Self {
153         EnumSet(self.0 & other.0)
154     }
155     /// Returns a set with all elements of the other set removed.
156     pub fn difference(&self, other: Self) -> Self {
157         EnumSet(self.0 & !other.0)
158     }
159     /// Returns a set with all elements not contained in both sets.
160     pub fn symmetrical_difference(&self, other: Self) -> Self {
161         EnumSet(self.0 ^ other.0)
162     }
163
164     /// Checks whether this set contains a value.
165     pub fn contains(&self, value: T) -> bool {
166         self.has_bit(value.into_u8())
167     }
168     /// Adds a value to this set.
169     pub fn insert(&mut self, value: T) -> bool {
170         let contains = self.contains(value);
171         self.0 |= Self::mask(value.into_u8());
172         contains
173     }
174     /// Removes a value from this set.
175     pub fn remove(&mut self, value: T) -> bool {
176         let contains = self.contains(value);
177         self.0 &= !Self::mask(value.into_u8());
178         contains
179     }
180
181     /// Adds all elements in another set to this one.
182     pub fn insert_all(&mut self, other: Self) {
183         self.0 |= other.0
184     }
185     /// Removes all values in another set from this one.
186     pub fn remove_all(&mut self, other: Self) {
187         self.0 &= !other.0
188     }
189
190     pub fn iter(&self) -> EnumSetIter<T> {
191         EnumSetIter(*self, 0)
192     }
193 }
194 impl <T : EnumSetType> IntoIterator for EnumSet<T> {
195     type Item = T;
196     type IntoIter = EnumSetIter<T>;
197
198     fn into_iter(self) -> Self::IntoIter {
199         self.iter()
200     }
201 }
202 impl <T : EnumSetType> Sub<EnumSet<T>> for EnumSet<T> {
203     type Output = Self;
204     fn sub(self, other: Self) -> Self::Output {
205         self.difference(other)
206     }
207 }
208 impl <T : EnumSetType> BitAnd<EnumSet<T>> for EnumSet<T> {
209     type Output = Self;
210     fn bitand(self, other: Self) -> Self::Output {
211         self.intersection(other)
212     }
213 }
214 impl <T : EnumSetType> BitOr<EnumSet<T>> for EnumSet<T> {
215     type Output = Self;
216     fn bitor(self, other: Self) -> Self::Output {
217         self.union(other)
218     }
219 }
220 impl <T : EnumSetType> BitXor<EnumSet<T>> for EnumSet<T> {
221     type Output = Self;
222     fn bitxor(self, other: Self) -> Self::Output {
223         self.symmetrical_difference(other)
224     }
225 }
226 impl <T : EnumSetType> BitOr<T> for EnumSet<T> {
227     type Output = Self;
228     fn bitor(self, other: T) -> Self::Output {
229         EnumSet(self.0 | Self::mask(other.into_u8()))
230     }
231 }
232
233 impl <T : EnumSetType + Debug> Debug for EnumSet<T> {
234     fn fmt(&self, f: &mut Formatter) -> fmt::Result {
235         let mut is_first = true;
236         f.write_str("EnumSet(")?;
237         for v in self.iter() {
238             if !is_first { f.write_str(" | ")?; }
239             is_first = false;
240             v.fmt(f)?;
241         }
242         f.write_str(")")?;
243         Ok(())
244     }
245 }
246
247 /// The iterator used by [`EnumSet`](./struct.EnumSet.html).
248 #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
249 pub struct EnumSetIter<T : EnumSetType>(EnumSet<T>, u8);
250 impl <T : EnumSetType> Iterator for EnumSetIter<T> {
251     type Item = T;
252
253     fn next(&mut self) -> Option<Self::Item> {
254         while self.1 < T::VARIANT_COUNT {
255             let bit = self.1;
256             self.1 += 1;
257             if self.0.has_bit(bit) {
258                 return Some(T::from_u8(bit))
259             }
260         }
261         None
262     }
263     fn size_hint(&self) -> (usize, Option<usize>) {
264         let left = T::count_ones((self.0).0 & !((T::ONE << self.1) - T::ONE));
265         (left, Some(left))
266     }
267 }
268
269 #[macro_export]
270 #[doc(hidden)]
271 #[cfg(feature = "i128")]
272 macro_rules! enum_set_type_internal_count_variants {
273     ($next:ident ($($args:tt)*)
274         $_00:ident $_01:ident $_02:ident $_03:ident $_04:ident $_05:ident $_06:ident $_07:ident
275         $_10:ident $_11:ident $_12:ident $_13:ident $_14:ident $_15:ident $_16:ident $_17:ident
276         $_20:ident $_21:ident $_22:ident $_23:ident $_24:ident $_25:ident $_26:ident $_27:ident
277         $_30:ident $_31:ident $_32:ident $_33:ident $_34:ident $_35:ident $_36:ident $_37:ident
278         $_40:ident $_41:ident $_42:ident $_43:ident $_44:ident $_45:ident $_46:ident $_47:ident
279         $_50:ident $_51:ident $_52:ident $_53:ident $_54:ident $_55:ident $_56:ident $_57:ident
280         $_60:ident $_61:ident $_62:ident $_63:ident $_64:ident $_65:ident $_66:ident $_67:ident
281         $_70:ident $_71:ident $_72:ident $_73:ident $_74:ident $_75:ident $_76:ident $_77:ident
282         $_80:ident $_81:ident $_82:ident $_83:ident $_84:ident $_85:ident $_86:ident $_87:ident
283         $_90:ident $_91:ident $_92:ident $_93:ident $_94:ident $_95:ident $_96:ident $_97:ident
284         $_a0:ident $_a1:ident $_a2:ident $_a3:ident $_a4:ident $_a5:ident $_a6:ident $_a7:ident
285         $_b0:ident $_b1:ident $_b2:ident $_b3:ident $_b4:ident $_b5:ident $_b6:ident $_b7:ident
286         $_c0:ident $_c1:ident $_c2:ident $_c3:ident $_c4:ident $_c5:ident $_c6:ident $_c7:ident
287         $_d0:ident $_d1:ident $_d2:ident $_d3:ident $_d4:ident $_d5:ident $_d6:ident $_d7:ident
288         $_e0:ident $_e1:ident $_e2:ident $_e3:ident $_e4:ident $_e5:ident $_e6:ident $_e7:ident
289         $_f0:ident $_f1:ident $_f2:ident $_f3:ident $_f4:ident $_f5:ident $_f6:ident $_f7:ident
290         $($rest:ident)+
291     ) => {
292         ENUM_SET___TOO_MANY_ENUM_VARIANTS___MAX_IS_128
293     };
294     ($next:ident ($($args:tt)*)
295         $_00:ident $_01:ident $_02:ident $_03:ident $_04:ident $_05:ident $_06:ident $_07:ident
296         $_10:ident $_11:ident $_12:ident $_13:ident $_14:ident $_15:ident $_16:ident $_17:ident
297         $_20:ident $_21:ident $_22:ident $_23:ident $_24:ident $_25:ident $_26:ident $_27:ident
298         $_30:ident $_31:ident $_32:ident $_33:ident $_34:ident $_35:ident $_36:ident $_37:ident
299         $_40:ident $_41:ident $_42:ident $_43:ident $_44:ident $_45:ident $_46:ident $_47:ident
300         $_50:ident $_51:ident $_52:ident $_53:ident $_54:ident $_55:ident $_56:ident $_57:ident
301         $_60:ident $_61:ident $_62:ident $_63:ident $_64:ident $_65:ident $_66:ident $_67:ident
302         $_70:ident $_71:ident $_72:ident $_73:ident $_74:ident $_75:ident $_76:ident $_77:ident
303         $($rest:ident)+
304     ) => {
305         enum_set_type_internal! { @$next u128 $($args)* }
306     };
307     ($next:ident ($($args:tt)*)
308         $_00:ident $_01:ident $_02:ident $_03:ident $_04:ident $_05:ident $_06:ident $_07:ident
309         $_10:ident $_11:ident $_12:ident $_13:ident $_14:ident $_15:ident $_16:ident $_17:ident
310         $_20:ident $_21:ident $_22:ident $_23:ident $_24:ident $_25:ident $_26:ident $_27:ident
311         $_30:ident $_31:ident $_32:ident $_33:ident $_34:ident $_35:ident $_36:ident $_37:ident
312         $($rest:ident)+
313     ) => {
314         enum_set_type_internal! { @$next u64 $($args)* }
315     };
316     ($next:ident ($($args:tt)*)
317         $_00:ident $_01:ident $_02:ident $_03:ident $_04:ident $_05:ident $_06:ident $_07:ident
318         $_10:ident $_11:ident $_12:ident $_13:ident $_14:ident $_15:ident $_16:ident $_17:ident
319         $($rest:ident)+
320     ) => {
321         enum_set_type_internal! { @$next u32 $($args)* }
322     };
323     ($next:ident ($($args:tt)*)
324         $_00:ident $_01:ident $_02:ident $_03:ident $_04:ident $_05:ident $_06:ident $_07:ident
325         $($rest:ident)+
326     ) => {
327         enum_set_type_internal! { @$next u16 $($args)* }
328     };
329     ($next:ident ($($args:tt)*) $($rest:ident)*) => {
330         enum_set_type_internal! { @$next u8 $($args)* }
331     };
332 }
333
334 #[macro_export]
335 #[doc(hidden)]
336 #[cfg(not(feature = "i128"))]
337 macro_rules! enum_set_type_internal_count_variants {
338     ($next:ident ($($args:tt)*)
339         $_00:ident $_01:ident $_02:ident $_03:ident $_04:ident $_05:ident $_06:ident $_07:ident
340         $_10:ident $_11:ident $_12:ident $_13:ident $_14:ident $_15:ident $_16:ident $_17:ident
341         $_20:ident $_21:ident $_22:ident $_23:ident $_24:ident $_25:ident $_26:ident $_27:ident
342         $_30:ident $_31:ident $_32:ident $_33:ident $_34:ident $_35:ident $_36:ident $_37:ident
343         $_40:ident $_41:ident $_42:ident $_43:ident $_44:ident $_45:ident $_46:ident $_47:ident
344         $_50:ident $_51:ident $_52:ident $_53:ident $_54:ident $_55:ident $_56:ident $_57:ident
345         $_60:ident $_61:ident $_62:ident $_63:ident $_64:ident $_65:ident $_66:ident $_67:ident
346         $_70:ident $_71:ident $_72:ident $_73:ident $_74:ident $_75:ident $_76:ident $_77:ident
347         $($rest:ident)+
348     ) => {
349         ENUM_SET___TOO_MANY_ENUM_VARIANTS___MAX_IS_64
350     };
351     ($next:ident ($($args:tt)*)
352         $_00:ident $_01:ident $_02:ident $_03:ident $_04:ident $_05:ident $_06:ident $_07:ident
353         $_10:ident $_11:ident $_12:ident $_13:ident $_14:ident $_15:ident $_16:ident $_17:ident
354         $_20:ident $_21:ident $_22:ident $_23:ident $_24:ident $_25:ident $_26:ident $_27:ident
355         $_30:ident $_31:ident $_32:ident $_33:ident $_34:ident $_35:ident $_36:ident $_37:ident
356         $($rest:ident)+
357     ) => {
358         enum_set_type_internal! { @$next u64 $($args)* }
359     };
360     ($next:ident ($($args:tt)*)
361         $_00:ident $_01:ident $_02:ident $_03:ident $_04:ident $_05:ident $_06:ident $_07:ident
362         $_10:ident $_11:ident $_12:ident $_13:ident $_14:ident $_15:ident $_16:ident $_17:ident
363         $($rest:ident)+
364     ) => {
365         enum_set_type_internal! { @$next u32 $($args)* }
366     };
367     ($next:ident ($($args:tt)*)
368         $_00:ident $_01:ident $_02:ident $_03:ident $_04:ident $_05:ident $_06:ident $_07:ident
369         $($rest:ident)+
370     ) => {
371         enum_set_type_internal! { @$next u16 $($args)* }
372     };
373     ($next:ident ($($args:tt)*) $($rest:ident)*) => {
374         enum_set_type_internal! { @$next u8 $($args)* }
375     };
376 }
377
378 #[macro_export]
379 #[doc(hidden)]
380 macro_rules! enum_set_type_internal {
381     // Counting functions
382     (@ident ($($random:tt)*) $value:expr) => { $value };
383     (@count $($value:tt)*) => {
384         0u8 $(+ enum_set_type_internal!(@ident ($value) 1u8))*
385     };
386
387     // Codegen
388     (@body $repr:ident ($(#[$enum_attr:meta])*) ($($vis:tt)*) $enum_name:ident {
389         $($(#[$attr:meta])* $variant:ident,)*
390     }) => {
391         $(#[$enum_attr])* #[repr(u8)]
392         #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
393         $($vis)* enum $enum_name {
394             $($(#[$attr])* $variant,)*
395         }
396         impl $crate::EnumSetType for $enum_name {
397             type Repr = $repr;
398             const ZERO: Self::Repr = 0;
399             const ONE : Self::Repr = 1;
400             const VARIANT_COUNT: u8 = enum_set_type_internal!(@count $($variant)*);
401
402             fn count_ones(val: Self::Repr) -> usize {
403                 val.count_ones() as usize
404             }
405             fn into_u8(self) -> u8 {
406                 self as u8
407             }
408             fn from_u8(val: u8) -> Self {
409                 unsafe { ::std::mem::transmute(val) }
410             }
411         }
412         impl ::std::ops::BitOr<$enum_name> for $enum_name {
413             type Output = $crate::EnumSet<$enum_name>;
414             fn bitor(self, other: $enum_name) -> Self::Output {
415                 enum_set!($enum_name, self | other)
416             }
417         }
418     };
419 }
420
421 /// Defines enums which can be used with EnumSet.
422 ///
423 /// While attributes and documentation can be attached to the enums, the variants may not
424 /// contain data.
425 ///
426 /// # Examples
427 ///
428 /// ```rust
429 /// # #[macro_use] extern crate enumset;
430 /// # use enumset::*;
431 /// enum_set_type! {
432 ///     enum Enum {
433 ///         A, B, C, D, E, F, G
434 ///     }
435 ///
436 ///     /// Documentation
437 ///     pub enum Enum2 {
438 ///         A, B, C, D, E, F, G,
439 ///         #[doc(hidden)] __NonExhaustive,
440 ///     }
441 /// }
442 /// # fn main() { }
443 /// ```
444 #[macro_export]
445 macro_rules! enum_set_type {
446     ($(#[$enum_attr:meta])* pub enum $enum_name:ident {
447         $($(#[$attr:meta])* $variant:ident),* $(,)*
448     } $($rest:tt)*) => {
449         enum_set_type_internal_count_variants!(body (($(#[$enum_attr])*) (pub) $enum_name {
450             $($(#[$attr])* $variant,)*
451         }) $($variant)*);
452         enum_set_type!($($rest)*);
453     };
454     ($(#[$enum_attr:meta])* enum $enum_name:ident {
455         $($(#[$attr:meta])* $variant:ident),* $(,)*
456     } $($rest:tt)*) => {
457         enum_set_type_internal_count_variants!(body (($(#[$enum_attr])*) () $enum_name {
458             $($(#[$attr])* $variant,)*
459         }) $($variant)*);
460         enum_set_type!($($rest)*);
461     };
462     () => { };
463 }
464
465 /// Creates a EnumSet literal, which can be used in const contexts.
466 ///
467 /// The format is `enum_set_type!(Type, Type::A | Type::B | Type::C)`, where `Type` is the type
468 /// the enum will contain, and the rest is the variants that the set will contain.
469 ///
470 /// # Examples
471 ///
472 /// ```rust
473 /// # #[macro_use] extern crate enumset;
474 /// # use enumset::*;
475 /// # enum_set_type! {
476 /// #     enum Enum { A, B, C }
477 /// # }
478 /// # fn main() {
479 /// const CONST_SET: EnumSet<Enum> = enum_set!(Enum, Enum::A | Enum::B);
480 /// assert_eq!(CONST_SET, Enum::A | Enum::B);
481 /// # }
482 /// ```
483 #[macro_export]
484 macro_rules! enum_set {
485     ($enum_name:ty, $($value:path)|* $(|)*) => {
486         $crate::EnumSet::<$enum_name>(
487             <$enum_name as $crate::EnumSetType>::ZERO
488             $(| (<$enum_name as $crate::EnumSetType>::ONE << ($value as u8)))*
489         )
490     }
491 }
492
493 #[cfg(test)]
494 #[allow(dead_code)]
495 mod test {
496     use super::*;
497
498     enum_set_type! {
499         enum Enum {
500             A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
501         }
502         enum Enum2 {
503             A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
504         }
505     }
506
507     #[cfg(feature = "i128")]
508     enum_set_type! {
509         enum LargeEnum {
510             _00,  _01,  _02,  _03,  _04,  _05,  _06,  _07,
511             _10,  _11,  _12,  _13,  _14,  _15,  _16,  _17,
512             _20,  _21,  _22,  _23,  _24,  _25,  _26,  _27,
513             _30,  _31,  _32,  _33,  _34,  _35,  _36,  _37,
514             _40,  _41,  _42,  _43,  _44,  _45,  _46,  _47,
515             _50,  _51,  _52,  _53,  _54,  _55,  _56,  _57,
516             _60,  _61,  _62,  _63,  _64,  _65,  _66,  _67,
517             _70,  _71,  _72,  _73,  _74,  _75,  _76,  _77,
518             A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
519         }
520     }
521
522     macro_rules! test_variants {
523         ($enum_name:ident $test_name:ident $($variant:ident,)*) => {
524             #[test]
525             fn $test_name() {
526                 let count = enum_set_type_internal!(@count u8 $($variant)*);
527                 $(
528                     assert!(($enum_name::$variant as u8) < count);
529                 )*
530             }
531         }
532     }
533
534     test_variants! { Enum enum_variant_range_test
535         A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
536     }
537
538     #[cfg(feature = "i128")]
539     test_variants! { LargeEnum large_enum_variant_range_test
540         _00,  _01,  _02,  _03,  _04,  _05,  _06,  _07,
541         _10,  _11,  _12,  _13,  _14,  _15,  _16,  _17,
542         _20,  _21,  _22,  _23,  _24,  _25,  _26,  _27,
543         _30,  _31,  _32,  _33,  _34,  _35,  _36,  _37,
544         _40,  _41,  _42,  _43,  _44,  _45,  _46,  _47,
545         _50,  _51,  _52,  _53,  _54,  _55,  _56,  _57,
546         _60,  _61,  _62,  _63,  _64,  _65,  _66,  _67,
547         _70,  _71,  _72,  _73,  _74,  _75,  _76,  _77,
548         A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z,
549     }
550
551     macro_rules! test_enum {
552         ($e:ident, $m:ident) => {
553             mod $m {
554                 use super::*;
555
556                 const CONST_SET: EnumSet<$e> = enum_set!($e, $e::A | $e::Y);
557                 const EMPTY_SET: EnumSet<$e> = enum_set!($e, );
558                 #[test]
559                 fn const_set() {
560                     assert_eq!(CONST_SET.len(), 2);
561                     assert!(CONST_SET.contains($e::A));
562                     assert!(CONST_SET.contains($e::Y));
563                     assert!(EMPTY_SET.is_empty());
564                 }
565
566                 #[test]
567                 fn basic_add_remove() {
568                     let mut set = EnumSet::new();
569                     set.insert($e::A);
570                     set.insert($e::B);
571                     set.insert($e::C);
572                     assert_eq!(set, $e::A | $e::B | $e::C);
573                     set.remove($e::B);
574                     assert_eq!(set, $e::A | $e::C);
575                     set.insert($e::D);
576                     assert_eq!(set, $e::A | $e::C | $e::D);
577                     set.insert_all($e::F | $e::E | $e::G);
578                     assert_eq!(set, $e::A | $e::C | $e::D | $e::F | $e::E | $e::G);
579                     set.remove_all($e::A | $e::D | $e::G);
580                     assert_eq!(set, $e::C | $e::F | $e::E);
581                     assert!(!set.is_empty());
582                     set.clear();
583                     assert!(set.is_empty());
584                 }
585
586                 #[test]
587                 fn basic_iter_test() {
588                     let mut set = EnumSet::new();
589                     set.insert($e::A);
590                     set.insert($e::B);
591                     set.insert($e::C);
592                     set.insert($e::E);
593
594                     let mut set_2 = EnumSet::new();
595                     let vec: Vec<$e> = set.iter().collect();
596                     for val in vec {
597                         set_2.insert(val);
598                     }
599                     assert_eq!(set, set_2);
600
601                     let mut set_3 = EnumSet::new();
602                     for val in set {
603                         set_3.insert(val);
604                     }
605                     assert_eq!(set, set_3);
606                 }
607
608                 #[test]
609                 fn basic_ops_test() {
610                     assert_eq!(($e::A | $e::B) | ($e::B | $e::C), $e::A | $e::B | $e::C);
611                     assert_eq!(($e::A | $e::B) & ($e::B | $e::C), EnumSet::new() | $e::B);
612                     assert_eq!(($e::A | $e::B) ^ ($e::B | $e::C), $e::A | $e::C);
613                     assert_eq!(($e::A | $e::B) - ($e::B | $e::C), EnumSet::new() | $e::A);
614                 }
615
616                 #[test]
617                 fn basic_set_status() {
618                     assert!(($e::A | $e::B | $e::C).is_disjoint($e::D | $e::E | $e::F));
619                     assert!(!($e::A | $e::B | $e::C | $e::D).is_disjoint($e::D | $e::E | $e::F));
620                     assert!(($e::A | $e::B).is_subset($e::A | $e::B | $e::C));
621                     assert!(!($e::A | $e::D).is_subset($e::A | $e::B | $e::C));
622                 }
623
624                 #[test]
625                 fn debug_impl() {
626                     assert_eq!(format!("{:?}", $e::A | $e::B | $e::W), "EnumSet(A | B | W)");
627                 }
628             }
629         }
630     }
631
632     test_enum!(Enum, small_enum);
633     #[cfg(feature = "i128")]
634     test_enum!(LargeEnum, large_enum);
635 }