/// Everything in this module is internal API and may change at any time. #[doc(hidden)] pub mod __internal { /// A reexport of core to allow our macros to be generic to std vs core. pub use ::core as core_export; /// A reexport of serde so our users don't have to also have a serde dependency. #[cfg(feature = "serde")] pub use serde; /// Reexports of internal types pub use crate::{ repr::{ArrayRepr, EnumSetTypeRepr}, traits::{EnumSetConstHelper, EnumSetTypePrivate}, }; #[cfg(feature = "serde")] #[doc(hidden)] #[macro_export] macro_rules! __if_serde { ($($tt:tt)*) => { $($tt)* }; } #[cfg(not(feature = "serde"))] #[doc(hidden)] #[macro_export] macro_rules! __if_serde { ($($tt:tt)*) => {}; } /// Macro to wrap serde-related code generated by the derive, discarding it /// if serde support is not enabled. pub use __if_serde; pub use crate::macros::set; } /// Helper functions for sets. pub mod set { use crate::__internal::EnumSetConstHelper; use crate::{EnumSet, EnumSetType}; /// Retrieves the helper used in constant time operations. #[inline(always)] pub const fn op_helper(_: &T) -> T::ConstOpHelper { T::CONST_OP_HELPER } /// Retrieves the helper used in constant time conversions. #[inline(always)] pub const fn init_helper(_: &T) -> T::ConstInitHelper { T::CONST_INIT_HELPER } /// Gets the underlying repr from an EnumSet #[inline(always)] pub const fn get(set: EnumSet) -> T::Repr { set.repr } /// Constructs an EnumSet from the underlying repr #[inline(always)] pub const fn new(set: T::Repr) -> EnumSet { EnumSet { repr: set } } } /// Creates a EnumSet literal, which can be used in const contexts. /// /// The syntax used is `enum_set!(Type::A | Type::B | Type::C)`. Each variant must be of the same /// type, or an error will occur at compile-time. /// /// This macro accepts trailing `|`s to allow easier use in other macros. /// /// # Performance /// /// This macro is designed for use in const contexts, not for execution as normal code. It may be /// significantly slower than normal code outside const contexts. /// /// In normal code, directly use `Type::A | Type::B | Type::C` instead. /// /// # Examples /// /// ```rust /// # use enumset::*; /// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C } /// const CONST_SET: EnumSet = enum_set!(Enum::A | Enum::B); /// assert_eq!(CONST_SET, Enum::A | Enum::B); /// ``` /// /// This macro is strongly typed. For example, the following will not compile: /// /// ```compile_fail /// # use enumset::*; /// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C } /// # #[derive(EnumSetType, Debug)] enum Enum2 { A, B, C } /// let type_error = enum_set!(Enum::A | Enum2::B); /// ``` #[macro_export] macro_rules! enum_set { ($(|)*) => { $crate::EnumSet::empty() }; ($value:path $(|)*) => { { $crate::__internal::set::init_helper(&$value).const_only($value) } }; ($value:path | $($rest:path)|* $(|)*) => { $crate::enum_set_union!($value, $($rest,)*) }; } /// Computes the union of multiple enums or constants enumset at compile time. /// /// The syntax used is `enum_set_union!(ENUM_A, ENUM_B, ENUM_C)`, computing the equivalent of /// `ENUM_A | ENUM_B | ENUM_C` at compile time. Each variant must be of the same type, or an error /// will occur at compile-time. /// /// # Performance /// /// This macro is designed for use in const contexts, not for execution as normal code. It may be /// significantly slower than normal code outside const contexts. /// /// In normal code, directly use the `|` operator instead. /// /// # Examples /// /// ```rust /// # use enumset::*; /// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C } /// const CONST_SET: EnumSet = enum_set_union!(Enum::A, Enum::B); /// assert_eq!(CONST_SET, Enum::A | Enum::B); /// ``` #[macro_export] macro_rules! enum_set_union { ($value:path $(,)?) => { $crate::enum_set!($value) }; ($value:path, $($rest:path),* $(,)?) => { { let op_helper = $crate::__internal::set::op_helper(&$value); let value = $crate::enum_set!($value); $(let value = { let new = $crate::enum_set!($rest); op_helper.const_union(value, new) };)* value } }; } /// Computes the intersection of multiple enums or constants enumset at compile time. /// /// The syntax used is `enum_set_intersection!(ENUM_A, ENUM_B, ENUM_C)`, computing the equivalent /// of `ENUM_A & ENUM_B & ENUM_C` at compile time. Each variant must be of the same type, or an /// error will occur at compile-time. /// /// # Performance /// /// This macro is designed for use in const contexts, not for execution as normal code. It may be /// significantly slower than normal code outside const contexts. /// /// In normal code, directly use the `&` operator instead. /// /// # Examples /// /// ```rust /// # use enumset::*; /// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C, D } /// const SET_A: EnumSet = enum_set!(Enum::A | Enum::B); /// const SET_B: EnumSet = enum_set!(Enum::B | Enum::C); /// const CONST_SET: EnumSet = enum_set_intersection!(SET_A, SET_B); /// assert_eq!(CONST_SET, Enum::B); /// ``` #[macro_export] macro_rules! enum_set_intersection { ($value:path $(,)?) => { $crate::enum_set!($value) }; ($value:path, $($rest:path),* $(,)?) => { { let op_helper = $crate::__internal::set::op_helper(&$value); let value = $crate::enum_set!($value); $(let value = { let new = $crate::enum_set!($rest); op_helper.const_intersection(value, new) };)* value } }; } /// Computes the complement of an enums or constants enumset at compile time. /// /// # Performance /// /// This macro is designed for use in const contexts, not for execution as normal code. It may be /// significantly slower than normal code outside const contexts. /// /// In normal code, directly use the `!` operator instead. /// /// # Examples /// /// ```rust /// # use enumset::*; /// #[derive(EnumSetType, Debug)] /// enum Enum { A, B, C, D } /// /// const SET: EnumSet = enum_set!(Enum::B | Enum::C); /// const CONST_SET: EnumSet = enum_set_complement!(SET); /// assert_eq!(CONST_SET, Enum::A | Enum::D); /// ``` #[macro_export] macro_rules! enum_set_complement { ($value:path $(,)?) => {{ let op_helper = $crate::__internal::set::op_helper(&$value); let value = $crate::enum_set!($value); op_helper.const_complement(value) }}; } /// Computes the difference of multiple enums or constants enumset at compile time. /// /// The syntax used is `enum_set_difference!(ENUM_A, ENUM_B, ENUM_C)`, computing the equivalent /// of `ENUM_A - ENUM_B - ENUM_C` at compile time. Each variant must be of the same type, or an /// error will occur at compile-time. /// /// # Performance /// /// This macro is designed for use in const contexts, not for execution as normal code. It may be /// significantly slower than normal code outside const contexts. /// /// In normal code, directly use the `-` operator instead. /// /// # Examples /// /// ```rust /// # use enumset::*; /// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C, D } /// const SET_A: EnumSet = enum_set!(Enum::A | Enum::B | Enum::D); /// const SET_B: EnumSet = enum_set!(Enum::B | Enum::C); /// const CONST_SET: EnumSet = enum_set_symmetric_difference!(SET_A, SET_B); /// assert_eq!(CONST_SET, Enum::A | Enum::C | Enum::D); /// ``` #[macro_export] macro_rules! enum_set_difference { ($value:path $(,)?) => { $crate::enum_set!($value) }; ($value:path, $($rest:path),* $(,)?) => { { let op_helper = $crate::__internal::set::op_helper(&$value); let value = $crate::enum_set!($value); $(let value = { let new = $crate::enum_set!($rest); op_helper.const_intersection(value, op_helper.const_complement(new)) };)* value } }; } /// Computes the symmetric difference of multiple enums or constants enumset at compile time. /// /// The syntax used is `enum_set_symmetric_difference!(ENUM_A, ENUM_B, ENUM_C)`, computing the /// equivalent of `ENUM_A ^ ENUM_B ^ ENUM_C` at compile time. Each variant must be of the same /// type, or an error will occur at compile-time. /// /// # Performance /// /// This macro is designed for use in const contexts, not for execution as normal code. It may be /// significantly slower than normal code outside const contexts. /// /// In normal code, directly use the `^` operator instead. /// /// # Examples /// /// ```rust /// # use enumset::*; /// # #[derive(EnumSetType, Debug)] enum Enum { A, B, C, D } /// const SET_A: EnumSet = EnumSet::all(); /// const SET_B: EnumSet = enum_set!(Enum::B | Enum::C); /// const CONST_SET: EnumSet = enum_set_difference!(SET_A, SET_B); /// assert_eq!(CONST_SET, Enum::A | Enum::D); /// ``` #[macro_export] macro_rules! enum_set_symmetric_difference { ($value:path $(,)?) => { $crate::enum_set!($value) }; ($value:path, $($rest:path),* $(,)?) => { { let op_helper = $crate::__internal::set::op_helper(&$value); let value = $crate::enum_set!($value); $(let value = { let new = $crate::enum_set!($rest); op_helper.const_symmetric_difference(value, new) };)* value } }; }