]> git.lizzy.rs Git - enumset.git/blob - enumset/src/lib.rs
Fix documentation.
[enumset.git] / enumset / src / lib.rs
1 #![no_std]
2 #![forbid(missing_docs)]
3
4 //! A library for defining enums that can be used in compact bit sets. It supports enums up to 128
5 //! variants, and has a macro to use these sets in constants.
6 //!
7 //! For serde support, enable the `serde` feature.
8 //!
9 //! # Defining enums for use with EnumSet
10 //!
11 //! Enums to be used with [`EnumSet`] should be defined using `#[derive(EnumSetType)]`:
12 //!
13 //! ```rust
14 //! # use enumset::*;
15 //! #[derive(EnumSetType, Debug)]
16 //! pub enum Enum {
17 //!    A, B, C, D, E, F, G,
18 //! }
19 //! ```
20 //!
21 //! # Working with EnumSets
22 //!
23 //! EnumSets can be constructed via [`EnumSet::new()`] like a normal set. In addition,
24 //! `#[derive(EnumSetType)]` creates operator overloads that allow you to create EnumSets like so:
25 //!
26 //! ```rust
27 //! # use enumset::*;
28 //! # #[derive(EnumSetType, Debug)] pub enum Enum { A, B, C, D, E, F, G }
29 //! let new_set = Enum::A | Enum::C | Enum::G;
30 //! assert_eq!(new_set.len(), 3);
31 //! ```
32 //!
33 //! All bitwise operations you would expect to work on bitsets also work on both EnumSets and
34 //! enums with `#[derive(EnumSetType)]`:
35 //! ```rust
36 //! # use enumset::*;
37 //! # #[derive(EnumSetType, Debug)] pub enum Enum { A, B, C, D, E, F, G }
38 //! // Intersection of sets
39 //! assert_eq!((Enum::A | Enum::B) & Enum::C, EnumSet::empty());
40 //! assert_eq!((Enum::A | Enum::B) & Enum::A, Enum::A);
41 //! assert_eq!(Enum::A & Enum::B, EnumSet::empty());
42 //!
43 //! // Symmetric difference of sets
44 //! assert_eq!((Enum::A | Enum::B) ^ (Enum::B | Enum::C), Enum::A | Enum::C);
45 //! assert_eq!(Enum::A ^ Enum::C, Enum::A | Enum::C);
46 //!
47 //! // Difference of sets
48 //! assert_eq!((Enum::A | Enum::B | Enum::C) - Enum::B, Enum::A | Enum::C);
49 //!
50 //! // Complement of sets
51 //! assert_eq!(!(Enum::E | Enum::G), Enum::A | Enum::B | Enum::C | Enum::D | Enum::F);
52 //! ```
53 //!
54 //! The [`enum_set!`] macro allows you to create EnumSets in constant contexts:
55 //!
56 //! ```rust
57 //! # use enumset::*;
58 //! # #[derive(EnumSetType, Debug)] pub enum Enum { A, B, C, D, E, F, G }
59 //! const CONST_SET: EnumSet<Enum> = enum_set!(Enum::A | Enum::B);
60 //! assert_eq!(CONST_SET, Enum::A | Enum::B);
61 //! ```
62 //!
63 //! Mutable operations on the [`EnumSet`] otherwise work basically as expected:
64 //!
65 //! ```rust
66 //! # use enumset::*;
67 //! # #[derive(EnumSetType, Debug)] pub enum Enum { A, B, C, D, E, F, G }
68 //! let mut set = EnumSet::new();
69 //! set.insert(Enum::A);
70 //! set.insert_all(Enum::E | Enum::G);
71 //! assert!(set.contains(Enum::A));
72 //! assert!(!set.contains(Enum::B));
73 //! assert_eq!(set, Enum::A | Enum::E | Enum::G);
74 //! ```
75
76 pub use enumset_derive::*;
77
78 use core::cmp::Ordering;
79 use core::fmt;
80 use core::fmt::{Debug, Formatter};
81 use core::hash::{Hash, Hasher};
82 use core::ops::*;
83
84 use num_traits::*;
85
86 #[doc(hidden)]
87 /// Everything in this module is internal API and may change at any time.
88 pub mod internal {
89     use super::*;
90
91     /// A struct used to type check [`enum_set!`].
92     pub struct EnumSetSameTypeHack<'a, T: EnumSetType + 'static> {
93         pub unified: &'a [T],
94         pub enum_set: EnumSet<T>,
95     }
96
97     /// A reexport of core to allow our macros to be generic to std vs core.
98     pub extern crate core;
99
100     /// A reexport of serde so there is no requirement to depend on serde.
101     #[cfg(feature = "serde")] pub use serde2 as serde;
102
103     /// The actual members of EnumSetType. Put here to avoid polluting global namespaces.
104     pub unsafe trait EnumSetTypePrivate {
105         type Repr: EnumSetTypeRepr;
106         const ALL_BITS: Self::Repr;
107         fn enum_into_u8(self) -> u8;
108         unsafe fn enum_from_u8(val: u8) -> Self;
109
110         #[cfg(feature = "serde")]
111         fn serialize<S: serde::Serializer>(set: EnumSet<Self>, ser: S) -> Result<S::Ok, S::Error>
112             where Self: EnumSetType;
113         #[cfg(feature = "serde")]
114         fn deserialize<'de, D: serde::Deserializer<'de>>(de: D) -> Result<EnumSet<Self>, D::Error>
115             where Self: EnumSetType;
116     }
117 }
118 use internal::EnumSetTypePrivate;
119 #[cfg(feature = "serde")] use internal::serde;
120 #[cfg(feature = "serde")] use serde::{Serialize, Deserialize};
121
122 mod private {
123     use super::*;
124     pub trait EnumSetTypeRepr : PrimInt + FromPrimitive + WrappingSub + CheckedShl + Debug + Hash {
125         const WIDTH: u8;
126     }
127     macro_rules! prim {
128         ($name:ty, $width:expr) => {
129             impl EnumSetTypeRepr for $name {
130                 const WIDTH: u8 = $width;
131             }
132         }
133     }
134     prim!(u8  , 8  );
135     prim!(u16 , 16 );
136     prim!(u32 , 32 );
137     prim!(u64 , 64 );
138     prim!(u128, 128);
139 }
140 use private::EnumSetTypeRepr;
141
142 /// The trait used to define enum types that may be used with [`EnumSet`].
143 ///
144 /// This trait should be implemented using `#[derive(EnumSetType)]`. Its internal structure is
145 /// not currently stable, and may change at any time.
146 ///
147 /// # Custom Derive
148 ///
149 /// The custom derive for [`EnumSetType`] automatically creates implementations of [`PartialEq`],
150 /// [`Sub`], [`BitAnd`], [`BitOr`], [`BitXor`], and [`Not`] allowing the enum to be used as
151 /// if it were an [`EnumSet`] in expressions. This can be disabled by adding an `#[enumset(no_ops)]`
152 /// annotation to the enum.
153 ///
154 /// The custom derive for `EnumSetType` automatically implements [`Copy`], [`Clone`], [`Eq`], and
155 /// [`PartialEq`] on the enum. These are required for the [`EnumSet`] to function.
156 ///
157 /// Any C-like enum is supported, as long as there are no more than 128 variants in the enum,
158 /// and no variant discriminator is larger than 127.
159 ///
160 /// # Examples
161 ///
162 /// Deriving a plain EnumSetType:
163 ///
164 /// ```rust
165 /// # use enumset::*;
166 /// #[derive(EnumSetType)]
167 /// pub enum Enum {
168 ///    A, B, C, D, E, F, G,
169 /// }
170 /// ```
171 ///
172 /// Deriving a sparse EnumSetType:
173 ///
174 /// ```rust
175 /// # use enumset::*;
176 /// #[derive(EnumSetType)]
177 /// pub enum SparseEnum {
178 ///    A = 10, B = 20, C = 30, D = 127,
179 /// }
180 /// ```
181 ///
182 /// Deriving an EnumSetType without adding ops:
183 ///
184 /// ```rust
185 /// # use enumset::*;
186 /// #[derive(EnumSetType)]
187 /// #[enumset(no_ops)]
188 /// pub enum NoOpsEnum {
189 ///    A, B, C, D, E, F, G,
190 /// }
191 /// ```
192 pub unsafe trait EnumSetType: Copy + Eq + EnumSetTypePrivate { }
193
194 /// An efficient set type for enums.
195 ///
196 /// # Serialization
197 ///
198 /// The default representation serializes enumsets as an `u8`, `u16`, `u32`, `u64`, or `u128`,
199 /// whichever is the smallest that can contain all bits that are part of the set.
200 ///
201 /// Unknown bits are ignored, and are simply dropped. To override this behavior, you can add a
202 /// `#[enumset(serialize_deny_unknown)]` annotation to your enum.
203 ///
204 /// You can add a `#[enumset(serialize_repr = "u8")]` annotation to your enum to explicitly set
205 /// the bit width the `EnumSet` is serialized as. This can be used to avoid breaking changes in
206 /// certain serialization formats (such as `bincode`).
207 ///
208 /// In addition, the `#[enumset(serialize_as_list)]` annotation causes the `EnumSet` to be
209 /// instead serialized as a list. This requires your enum type implement [`Serialize`] and
210 /// [`Deserialize`].
211 #[derive(Copy, Clone, PartialEq, Eq)]
212 pub struct EnumSet<T : EnumSetType> {
213     #[doc(hidden)]
214     /// This is public due to the [`enum_set!`] macro.
215     /// This is **NOT** public API and may change at any time.
216     pub __enumset_underlying: T::Repr
217 }
218 impl <T : EnumSetType> EnumSet<T> {
219     fn mask(bit: u8) -> T::Repr {
220         Shl::<usize>::shl(T::Repr::one(), bit as usize)
221     }
222     fn has_bit(&self, bit: u8) -> bool {
223         let mask = Self::mask(bit);
224         self.__enumset_underlying & mask == mask
225     }
226     fn partial_bits(bits: u8) -> T::Repr {
227         T::Repr::one().checked_shl(bits.into())
228             .unwrap_or(T::Repr::zero())
229             .wrapping_sub(&T::Repr::one())
230     }
231
232     // Returns all bits valid for the enum
233     fn all_bits() -> T::Repr {
234         T::ALL_BITS
235     }
236
237     /// Returns an empty set.
238     pub fn new() -> Self {
239         EnumSet { __enumset_underlying: T::Repr::zero() }
240     }
241
242     /// Returns a set containing a single value.
243     pub fn only(t: T) -> Self {
244         EnumSet { __enumset_underlying: Self::mask(t.enum_into_u8()) }
245     }
246
247     /// Returns an empty set.
248     pub fn empty() -> Self {
249         Self::new()
250     }
251     /// Returns a set with all bits set.
252     pub fn all() -> Self {
253         EnumSet { __enumset_underlying: Self::all_bits() }
254     }
255
256     /// Total number of bits this enumset uses. Note that the actual amount of space used is
257     /// rounded up to the next highest integer type (`u8`, `u16`, `u32`, `u64`, or `u128`).
258     ///
259     /// This is the same as [`EnumSet::variant_count`] except in enums with "sparse" variants.
260     /// (e.g. `enum Foo { A = 10, B = 20 }`)
261     pub fn bit_width() -> u8 {
262         T::Repr::WIDTH - T::ALL_BITS.leading_zeros() as u8
263     }
264
265     /// The number of valid variants in this enumset.
266     ///
267     /// This is the same as [`EnumSet::bit_width`] except in enums with "sparse" variants.
268     /// (e.g. `enum Foo { A = 10, B = 20 }`)
269     pub fn variant_count() -> u8 {
270         T::ALL_BITS.count_ones() as u8
271     }
272
273     /// Returns the raw bits of this set
274     pub fn to_bits(&self) -> u128 {
275         self.__enumset_underlying.to_u128()
276             .expect("Impossible: Bits cannot be to converted into i128?")
277     }
278
279     /// Constructs a bitset from raw bits.
280     ///
281     /// # Panics
282     /// If bits not in the enum are set.
283     pub fn from_bits(bits: u128) -> Self {
284         assert!((bits & !Self::all().to_bits()) == 0, "Bits not valid for the enum were set.");
285         EnumSet {
286             __enumset_underlying: T::Repr::from_u128(bits)
287                 .expect("Impossible: Valid bits too large to fit in repr?")
288         }
289     }
290
291     /// Returns the number of values in this set.
292     pub fn len(&self) -> usize {
293         self.__enumset_underlying.count_ones() as usize
294     }
295     /// Checks if the set is empty.
296     pub fn is_empty(&self) -> bool {
297         self.__enumset_underlying.is_zero()
298     }
299     /// Removes all elements from the set.
300     pub fn clear(&mut self) {
301         self.__enumset_underlying = T::Repr::zero()
302     }
303
304     /// Checks if this set shares no elements with another.
305     pub fn is_disjoint(&self, other: Self) -> bool {
306         (*self & other).is_empty()
307     }
308     /// Checks if all elements in another set are in this set.
309     pub fn is_superset(&self, other: Self) -> bool {
310         (*self & other).__enumset_underlying == other.__enumset_underlying
311     }
312     /// Checks if all elements of this set are in another set.
313     pub fn is_subset(&self, other: Self) -> bool {
314         other.is_superset(*self)
315     }
316
317     /// Returns a set containing the union of all elements in both sets.
318     pub fn union(&self, other: Self) -> Self {
319         EnumSet { __enumset_underlying: self.__enumset_underlying | other.__enumset_underlying }
320     }
321     /// Returns a set containing all elements in common with another set.
322     pub fn intersection(&self, other: Self) -> Self {
323         EnumSet { __enumset_underlying: self.__enumset_underlying & other.__enumset_underlying }
324     }
325     /// Returns a set with all elements of the other set removed.
326     pub fn difference(&self, other: Self) -> Self {
327         EnumSet { __enumset_underlying: self.__enumset_underlying & !other.__enumset_underlying }
328     }
329     /// Returns a set with all elements not contained in both sets.
330     pub fn symmetrical_difference(&self, other: Self) -> Self {
331         EnumSet { __enumset_underlying: self.__enumset_underlying ^ other.__enumset_underlying }
332     }
333     /// Returns a set containing all elements not in this set.
334     pub fn complement(&self) -> Self {
335         EnumSet { __enumset_underlying: !self.__enumset_underlying & Self::all_bits() }
336     }
337
338     /// Checks whether this set contains a value.
339     pub fn contains(&self, value: T) -> bool {
340         self.has_bit(value.enum_into_u8())
341     }
342
343     /// Adds a value to this set.
344     pub fn insert(&mut self, value: T) -> bool {
345         let contains = self.contains(value);
346         self.__enumset_underlying = self.__enumset_underlying | Self::mask(value.enum_into_u8());
347         contains
348     }
349     /// Removes a value from this set.
350     pub fn remove(&mut self, value: T) -> bool {
351         let contains = self.contains(value);
352         self.__enumset_underlying = self.__enumset_underlying & !Self::mask(value.enum_into_u8());
353         contains
354     }
355
356     /// Adds all elements in another set to this one.
357     pub fn insert_all(&mut self, other: Self) {
358         self.__enumset_underlying = self.__enumset_underlying | other.__enumset_underlying
359     }
360     /// Removes all values in another set from this one.
361     pub fn remove_all(&mut self, other: Self) {
362         self.__enumset_underlying = self.__enumset_underlying & !other.__enumset_underlying
363     }
364
365     /// Creates an iterator over the values in this set.
366     pub fn iter(&self) -> EnumSetIter<T> {
367         EnumSetIter(*self, 0)
368     }
369 }
370
371 impl <T: EnumSetType> Default for EnumSet<T> {
372     /// Returns an empty set.
373     fn default() -> Self {
374         Self::new()
375     }
376 }
377
378 impl <T : EnumSetType> IntoIterator for EnumSet<T> {
379     type Item = T;
380     type IntoIter = EnumSetIter<T>;
381
382     fn into_iter(self) -> Self::IntoIter {
383         self.iter()
384     }
385 }
386
387 impl <T : EnumSetType, O: Into<EnumSet<T>>> Sub<O> for EnumSet<T> {
388     type Output = Self;
389     fn sub(self, other: O) -> Self::Output {
390         self.difference(other.into())
391     }
392 }
393 impl <T : EnumSetType, O: Into<EnumSet<T>>> BitAnd<O> for EnumSet<T> {
394     type Output = Self;
395     fn bitand(self, other: O) -> Self::Output {
396         self.intersection(other.into())
397     }
398 }
399 impl <T : EnumSetType, O: Into<EnumSet<T>>> BitOr<O> for EnumSet<T> {
400     type Output = Self;
401     fn bitor(self, other: O) -> Self::Output {
402         self.union(other.into())
403     }
404 }
405 impl <T : EnumSetType, O: Into<EnumSet<T>>> BitXor<O> for EnumSet<T> {
406     type Output = Self;
407     fn bitxor(self, other: O) -> Self::Output {
408         self.symmetrical_difference(other.into())
409     }
410 }
411
412 impl <T : EnumSetType, O: Into<EnumSet<T>>> SubAssign<O> for EnumSet<T> {
413     fn sub_assign(&mut self, rhs: O) {
414         *self = *self - rhs;
415     }
416 }
417 impl <T : EnumSetType, O: Into<EnumSet<T>>> BitAndAssign<O> for EnumSet<T> {
418     fn bitand_assign(&mut self, rhs: O) {
419         *self = *self & rhs;
420     }
421 }
422 impl <T : EnumSetType, O: Into<EnumSet<T>>> BitOrAssign<O> for EnumSet<T> {
423     fn bitor_assign(&mut self, rhs: O) {
424         *self = *self | rhs;
425     }
426 }
427 impl <T : EnumSetType, O: Into<EnumSet<T>>> BitXorAssign<O> for EnumSet<T> {
428     fn bitxor_assign(&mut self, rhs: O) {
429         *self = *self ^ rhs;
430     }
431 }
432
433 impl <T : EnumSetType> Not for EnumSet<T> {
434     type Output = Self;
435     fn not(self) -> Self::Output {
436         self.complement()
437     }
438 }
439
440 impl <T : EnumSetType> From<T> for EnumSet<T> {
441     fn from(t: T) -> Self {
442         EnumSet::only(t)
443     }
444 }
445
446 impl <T : EnumSetType> PartialEq<T> for EnumSet<T> {
447     fn eq(&self, other: &T) -> bool {
448         self.__enumset_underlying == EnumSet::<T>::mask(other.enum_into_u8())
449     }
450 }
451 impl <T : EnumSetType + Debug> Debug for EnumSet<T> {
452     fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
453         let mut is_first = true;
454         f.write_str("EnumSet(")?;
455         for v in self.iter() {
456             if !is_first { f.write_str(" | ")?; }
457             is_first = false;
458             v.fmt(f)?;
459         }
460         f.write_str(")")?;
461         Ok(())
462     }
463 }
464
465 impl <T: EnumSetType> Hash for EnumSet<T> {
466     fn hash<H: Hasher>(&self, state: &mut H) {
467         self.__enumset_underlying.hash(state)
468     }
469 }
470 impl <T: EnumSetType> PartialOrd for EnumSet<T> {
471     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
472         self.__enumset_underlying.partial_cmp(&other.__enumset_underlying)
473     }
474 }
475 impl <T: EnumSetType> Ord for EnumSet<T> {
476     fn cmp(&self, other: &Self) -> Ordering {
477         self.__enumset_underlying.cmp(&other.__enumset_underlying)
478     }
479 }
480
481 #[cfg(feature = "serde")]
482 impl <T : EnumSetType> Serialize for EnumSet<T> {
483     fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
484         T::serialize(*self, serializer)
485     }
486 }
487
488 #[cfg(feature = "serde")]
489 impl <'de, T : EnumSetType> Deserialize<'de> for EnumSet<T> {
490     fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
491         T::deserialize(deserializer)
492     }
493 }
494
495 /// The iterator used by [`EnumSet`](./struct.EnumSet.html).
496 #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
497 pub struct EnumSetIter<T : EnumSetType>(EnumSet<T>, u8);
498 impl <T : EnumSetType> Iterator for EnumSetIter<T> {
499     type Item = T;
500
501     fn next(&mut self) -> Option<Self::Item> {
502         while self.1 < EnumSet::<T>::bit_width() {
503             let bit = self.1;
504             self.1 += 1;
505             if self.0.has_bit(bit) {
506                 return unsafe { Some(T::enum_from_u8(bit)) }
507             }
508         }
509         None
510     }
511     fn size_hint(&self) -> (usize, Option<usize>) {
512         let left_mask = EnumSet::<T>::partial_bits(self.1);
513         let left = (self.0.__enumset_underlying & left_mask).count_ones() as usize;
514         (left, Some(left))
515     }
516 }
517
518 /// Creates a EnumSet literal, which can be used in const contexts.
519 ///
520 /// The syntax used is `enum_set!(Type::A | Type::B | Type::C)`. Each variant must be of the same
521 /// type, or a error will occur at compile-time.
522 ///
523 /// # Examples
524 ///
525 /// ```rust
526 /// # use enumset::*;
527 /// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C }
528 /// const CONST_SET: EnumSet<Enum> = enum_set!(Enum::A | Enum::B);
529 /// assert_eq!(CONST_SET, Enum::A | Enum::B);
530 /// ```
531 ///
532 /// This macro is strongly typed. For example, the following will not compile:
533 ///
534 /// ```compile_fail
535 /// # use enumset::*;
536 /// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C }
537 /// # #[derive(EnumSetType, Debug)] enum Enum2 { A, B, C }
538 /// let type_error = enum_set!(Enum::A | Enum2::B);
539 /// ```
540 #[macro_export]
541 macro_rules! enum_set {
542     () => {
543         $crate::EnumSet { __enumset_underlying: 0 }
544     };
545     ($($value:path)|* $(|)*) => {
546         $crate::internal::EnumSetSameTypeHack {
547             unified: &[$($value,)*],
548             enum_set: $crate::EnumSet {
549                 __enumset_underlying: 0 $(| (1 << ($value as u8)))*
550             },
551         }.enum_set
552     };
553 }