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