nutype_enum/
lib.rs

1/// Helper macro to create a new enum type with a single field.
2///
3/// The enum type is derived with the `Clone`, `Copy`, `PartialEq`, `Eq`,
4/// `PartialOrd`, `Ord`, and `Hash` traits. The nutype also impls `From` and
5/// `Into` for the underlying type. As well as a custom `Debug` impl for human
6/// readable output.
7///
8/// # Examples
9///
10/// ```rust
11/// # use nutype_enum::nutype_enum;
12/// nutype_enum! {
13///     pub enum AacPacketType(u8) {
14///         SeqHdr = 0x0,
15///         Raw = 0x1,
16///     }
17/// }
18/// ```
19#[macro_export]
20macro_rules! nutype_enum {
21    (
22        $(#[$attr:meta])*
23        $vis:vis enum $name:ident($type:ty) {
24            $(
25                $(#[$variant_attr:meta])*
26                $variant:ident = $value:expr
27            ),*$(,)?
28        }
29    ) => {
30        #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
31        $(#[$attr])*
32        #[repr(transparent)]
33        $vis struct $name(pub $type);
34
35        impl ::std::fmt::Debug for $name {
36            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37                match self {
38                    $(
39                        &$name::$variant => write!(f, "{}::{}", stringify!($name), stringify!($variant)),
40                    )*
41                    _ => write!(f, "{}({:?})", stringify!($name), self.0),
42                }
43            }
44        }
45
46        impl $name {
47            $(
48                $(#[$variant_attr])*
49                #[allow(non_upper_case_globals)]
50                pub const $variant: Self = Self($value);
51            )*
52        }
53
54        impl From<$type> for $name {
55            fn from(value: $type) -> Self {
56                Self(value)
57            }
58        }
59
60        impl From<$name> for $type {
61            fn from(value: $name) -> Self {
62                value.0
63            }
64        }
65    };
66}
67
68/// Helper macro to create a bitwise enum.
69///
70/// The enum type is derived with the `BitAnd`, `BitOr`, `BitXor`, `BitAndAssign`,
71/// `BitOrAssign`, and `BitXorAssign` traits.
72///
73/// # Examples
74///
75/// ```rust
76/// # use nutype_enum::{nutype_enum, bitwise_enum};
77/// nutype_enum! {
78///     pub enum IoFlags(u8) {
79///         Seek = 0x1,
80///         Write = 0x2,
81///         Read = 0x4,
82///     }
83/// }
84///
85/// bitwise_enum!(IoFlags);
86/// ```
87#[macro_export]
88macro_rules! bitwise_enum {
89    ($name:ident) => {
90        impl ::std::ops::BitAnd for $name {
91            type Output = Self;
92
93            fn bitand(self, rhs: Self) -> Self::Output {
94                Self(self.0 & rhs.0)
95            }
96        }
97
98        impl ::std::ops::BitOr for $name {
99            type Output = Self;
100
101            fn bitor(self, rhs: Self) -> Self::Output {
102                Self(self.0 | rhs.0)
103            }
104        }
105
106        impl ::std::ops::BitXor for $name {
107            type Output = Self;
108
109            fn bitxor(self, rhs: Self) -> Self::Output {
110                Self(self.0 ^ rhs.0)
111            }
112        }
113
114        impl ::std::ops::Not for $name {
115            type Output = Self;
116
117            fn not(self) -> Self::Output {
118                Self(!self.0)
119            }
120        }
121
122        impl ::std::ops::BitAndAssign for $name {
123            fn bitand_assign(&mut self, rhs: Self) {
124                self.0 &= rhs.0;
125            }
126        }
127
128        impl ::std::ops::BitOrAssign for $name {
129            fn bitor_assign(&mut self, rhs: Self) {
130                self.0 |= rhs.0;
131            }
132        }
133
134        impl ::std::ops::BitXorAssign for $name {
135            fn bitxor_assign(&mut self, rhs: Self) {
136                self.0 ^= rhs.0;
137            }
138        }
139    };
140}