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}