enumset/lib.rs
1#![no_std]
2#![deny(missing_docs)]
3#![allow(clippy::missing_safety_doc)] // The safety requirement is "use the procedural derive".
4#![allow(clippy::needless_range_loop)] // range loop style is clearer in most places in enumset
5#![cfg_attr(docsrs, feature(doc_cfg))]
6
7//! A library for defining enums that can be used in compact bit sets. It supports arbitrarily
8//! large enums, and has very basic support for using them in constants.
9//!
10//! # Cargo Features
11//!
12//! The following cargo features are available for this crate:
13//!
14//! * `serde`: Allows serialization and deserialization of the types in this crate.
15//! * `alloc`: Enables the use of functions that requires an allocator.
16//! * `proc-macro-crate`: Enable the use of the `proc-macro-crate` crate to allow the renaming of
17//! the `enumset` crate in your user crate. This feature increases the MSRV to 1.69.0
18//!
19//! # Defining enums for use with EnumSet
20//!
21//! Enums to be used with [`EnumSet`] should be defined using `#[derive(EnumSetType)]`:
22//!
23//! ```rust
24//! # use enumset::*;
25//! #[derive(EnumSetType, Debug)]
26//! pub enum Enum {
27//! A, B, C, D, E, F, G,
28//! }
29//! ```
30//!
31//! For more information on more advanced use cases, see the documentation for
32//! [`#[derive(EnumSetType)]`](./derive.EnumSetType.html).
33//!
34//! # Working with EnumSets
35//!
36//! EnumSets can be constructed via [`EnumSet::new()`] like a normal set. In addition,
37//! `#[derive(EnumSetType)]` creates operator overloads that allow you to create EnumSets like so:
38//!
39//! ```rust
40//! # use enumset::*;
41//! # #[derive(EnumSetType, Debug)] pub enum Enum { A, B, C, D, E, F, G }
42//! let new_set = Enum::A | Enum::C | Enum::G;
43//! assert_eq!(new_set.len(), 3);
44//! ```
45//!
46//! All bitwise operations you would expect to work on bitsets also work on both EnumSets and
47//! enums with `#[derive(EnumSetType)]`:
48//! ```rust
49//! # use enumset::*;
50//! # #[derive(EnumSetType, Debug)] pub enum Enum { A, B, C, D, E, F, G }
51//! // Intersection of sets
52//! assert_eq!((Enum::A | Enum::B) & Enum::C, EnumSet::empty());
53//! assert_eq!((Enum::A | Enum::B) & Enum::A, Enum::A);
54//! assert_eq!(Enum::A & Enum::B, EnumSet::empty());
55//!
56//! // Symmetric difference of sets
57//! assert_eq!((Enum::A | Enum::B) ^ (Enum::B | Enum::C), Enum::A | Enum::C);
58//! assert_eq!(Enum::A ^ Enum::C, Enum::A | Enum::C);
59//!
60//! // Difference of sets
61//! assert_eq!((Enum::A | Enum::B | Enum::C) - Enum::B, Enum::A | Enum::C);
62//!
63//! // Complement of sets
64//! assert_eq!(!(Enum::E | Enum::G), Enum::A | Enum::B | Enum::C | Enum::D | Enum::F);
65//! ```
66//!
67//! The [`enum_set!`] macro allows you to create EnumSets in constant contexts:
68//!
69//! ```rust
70//! # use enumset::*;
71//! # #[derive(EnumSetType, Debug)] pub enum Enum { A, B, C, D, E, F, G }
72//! const CONST_SET: EnumSet<Enum> = enum_set!(Enum::A | Enum::B);
73//! assert_eq!(CONST_SET, Enum::A | Enum::B);
74//! ```
75//!
76//! Mutable operations on the [`EnumSet`] otherwise similarly to Rust's builtin sets:
77//!
78//! ```rust
79//! # use enumset::*;
80//! # #[derive(EnumSetType, Debug)] pub enum Enum { A, B, C, D, E, F, G }
81//! let mut set = EnumSet::new();
82//! set.insert(Enum::A);
83//! set.insert_all(Enum::E | Enum::G);
84//! assert!(set.contains(Enum::A));
85//! assert!(!set.contains(Enum::B));
86//! assert_eq!(set, Enum::A | Enum::E | Enum::G);
87//! ```
88
89#[cfg(feature = "alloc")]
90extern crate alloc;
91
92mod macros;
93
94mod derive;
95mod repr;
96mod set;
97mod traits;
98
99pub use crate::derive::EnumSetType;
100pub use crate::macros::__internal;
101pub use crate::set::{EnumSet, EnumSetIter};
102pub use crate::traits::{EnumSetType, EnumSetTypeWithRepr};