enumset/
macros.rs

1/// Everything in this module is internal API and may change at any time.
2#[doc(hidden)]
3pub mod __internal {
4    /// A reexport of core to allow our macros to be generic to std vs core.
5    pub use ::core as core_export;
6
7    /// A reexport of serde so our users don't have to also have a serde dependency.
8    #[cfg(feature = "serde")]
9    pub use serde2 as serde;
10
11    /// Reexports of internal types
12    pub use crate::{
13        repr::{ArrayRepr, EnumSetTypeRepr},
14        traits::EnumSetTypePrivate,
15    };
16}
17
18/// Creates a EnumSet literal, which can be used in const contexts.
19///
20/// The syntax used is `enum_set!(Type::A | Type::B | Type::C)`. Each variant must be of the same
21/// type, or an error will occur at compile-time.
22///
23/// This macro accepts trailing `|`s to allow easier use in other macros.
24///
25/// # Examples
26///
27/// ```rust
28/// # use enumset::*;
29/// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C }
30/// const CONST_SET: EnumSet<Enum> = enum_set!(Enum::A | Enum::B);
31/// assert_eq!(CONST_SET, Enum::A | Enum::B);
32/// ```
33///
34/// This macro is strongly typed. For example, the following will not compile:
35///
36/// ```compile_fail
37/// # use enumset::*;
38/// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C }
39/// # #[derive(EnumSetType, Debug)] enum Enum2 { A, B, C }
40/// let type_error = enum_set!(Enum::A | Enum2::B);
41/// ```
42#[macro_export]
43macro_rules! enum_set {
44    ($(|)*) => {
45        EnumSet::empty()
46    };
47    ($value:path $(|)*) => {
48        {
49            #[allow(deprecated)] let value = $value.__impl_enumset_internal__const_only();
50            value
51        }
52    };
53    ($value:path | $($rest:path)|* $(|)*) => {
54        $crate::enum_set_union!($value, $($rest,)*)
55    };
56}
57
58/// Computes the union of multiple enums or constants enumset at compile time.
59///
60/// The syntax used is `enum_set_union!(ENUM_A, ENUM_B, ENUM_C)`, computing the equivalent of
61/// `ENUM_A | ENUM_B | ENUM_C` at compile time. Each variant must be of the same type, or an error
62/// will occur at compile-time.
63///
64/// # Examples
65///
66/// ```rust
67/// # use enumset::*;
68/// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C }
69/// const CONST_SET: EnumSet<Enum> = enum_set_union!(Enum::A, Enum::B);
70/// assert_eq!(CONST_SET, Enum::A | Enum::B);
71/// ```
72#[macro_export]
73macro_rules! enum_set_union {
74    ($value:path $(,)?) => {
75        $crate::enum_set!($value)
76    };
77    ($value:path, $($rest:path),* $(,)?) => {
78        {
79            #[allow(deprecated)] let helper = $value.__impl_enumset_internal__const_helper();
80            #[allow(deprecated)] let value = $value.__impl_enumset_internal__const_only();
81            $(#[allow(deprecated)] let value = {
82                let new = $rest.__impl_enumset_internal__const_only();
83                helper.const_union(value, new)
84            };)*
85            value
86        }
87    };
88}
89
90/// Computes the intersection of multiple enums or constants enumset at compile time.
91///
92/// The syntax used is `enum_set_intersection!(ENUM_A, ENUM_B, ENUM_C)`, computing the equivalent
93/// of `ENUM_A & ENUM_B & ENUM_C` at compile time. Each variant must be of the same type, or an
94/// error will occur at compile-time.
95///
96/// # Examples
97///
98/// ```rust
99/// # use enumset::*;
100/// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C, D }
101/// const SET_A: EnumSet<Enum> = enum_set!(Enum::A | Enum::B);
102/// const SET_B: EnumSet<Enum> = enum_set!(Enum::B | Enum::C);
103/// const CONST_SET: EnumSet<Enum> = enum_set_intersection!(SET_A, SET_B);
104/// assert_eq!(CONST_SET, Enum::B);
105/// ```
106#[macro_export]
107macro_rules! enum_set_intersection {
108    ($value:path $(,)?) => {
109        $crate::enum_set!($value)
110    };
111    ($value:path, $($rest:path),* $(,)?) => {
112        {
113            #[allow(deprecated)] let helper = $value.__impl_enumset_internal__const_helper();
114            #[allow(deprecated)] let value = $value.__impl_enumset_internal__const_only();
115            $(#[allow(deprecated)] let value = {
116                let new = $rest.__impl_enumset_internal__const_only();
117                helper.const_intersection(value, new)
118            };)*
119            value
120        }
121    };
122}
123
124/// Computes the complement of an enums or constants enumset at compile time.
125///
126/// # Examples
127///
128/// ```rust
129/// # use enumset::*;
130/// #[derive(EnumSetType, Debug)]
131/// enum Enum { A, B, C, D }
132///
133/// const SET: EnumSet<Enum> = enum_set!(Enum::B | Enum::C);
134/// const CONST_SET: EnumSet<Enum> = enum_set_complement!(SET);
135/// assert_eq!(CONST_SET, Enum::A | Enum::D);
136/// ```
137#[macro_export]
138macro_rules! enum_set_complement {
139    ($value:path $(,)?) => {{
140        #[allow(deprecated)]
141        let helper = $value.__impl_enumset_internal__const_helper();
142        #[allow(deprecated)]
143        let value = $value.__impl_enumset_internal__const_only();
144        helper.const_complement(value)
145    }};
146}
147
148/// Computes the difference of multiple enums or constants enumset at compile time.
149///
150/// The syntax used is `enum_set_difference!(ENUM_A, ENUM_B, ENUM_C)`, computing the equivalent
151/// of `ENUM_A - ENUM_B - ENUM_C` at compile time. Each variant must be of the same type, or an
152/// error will occur at compile-time.
153///
154/// # Examples
155///
156/// ```rust
157/// # use enumset::*;
158/// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C, D }
159/// const SET_A: EnumSet<Enum> = enum_set!(Enum::A | Enum::B | Enum::D);
160/// const SET_B: EnumSet<Enum> = enum_set!(Enum::B | Enum::C);
161/// const CONST_SET: EnumSet<Enum> = enum_set_symmetric_difference!(SET_A, SET_B);
162/// assert_eq!(CONST_SET, Enum::A | Enum::C | Enum::D);
163/// ```
164#[macro_export]
165macro_rules! enum_set_difference {
166    ($value:path $(,)?) => {
167        $crate::enum_set!($value)
168    };
169    ($value:path, $($rest:path),* $(,)?) => {
170        {
171            #[allow(deprecated)] let helper = $value.__impl_enumset_internal__const_helper();
172            #[allow(deprecated)] let value = $value.__impl_enumset_internal__const_only();
173            $(#[allow(deprecated)] let value = {
174                let new = $rest.__impl_enumset_internal__const_only();
175                helper.const_intersection(value, helper.const_complement(new))
176            };)*
177            value
178        }
179    };
180}
181
182/// Computes the symmetric difference of multiple enums or constants enumset at compile time.
183///
184/// The syntax used is `enum_set_symmetric_difference!(ENUM_A, ENUM_B, ENUM_C)`, computing the
185/// equivalent of `ENUM_A ^ ENUM_B ^ ENUM_C` at compile time. Each variant must be of the same
186/// type, or an error will occur at compile-time.
187///
188/// # Examples
189///
190/// ```rust
191/// # use enumset::*;
192/// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C, D }
193/// const SET_A: EnumSet<Enum> = EnumSet::all();
194/// const SET_B: EnumSet<Enum> = enum_set!(Enum::B | Enum::C);
195/// const CONST_SET: EnumSet<Enum> = enum_set_difference!(SET_A, SET_B);
196/// assert_eq!(CONST_SET, Enum::A | Enum::D);
197/// ```
198#[macro_export]
199macro_rules! enum_set_symmetric_difference {
200    ($value:path $(,)?) => {
201        $crate::enum_set!($value)
202    };
203    ($value:path, $($rest:path),* $(,)?) => {
204        {
205            #[allow(deprecated)] let helper = $value.__impl_enumset_internal__const_helper();
206            #[allow(deprecated)] let value = $value.__impl_enumset_internal__const_only();
207            $(#[allow(deprecated)] let value = {
208                let new = $rest.__impl_enumset_internal__const_only();
209                helper.const_symmetric_difference(value, new)
210            };)*
211            value
212        }
213    };
214}