nutype_enum/lib.rs
1//! The crate provides a macro to create a new enum type with a single field.
2//!
3//! ## Why do we need this?
4//!
5//! This is useful when you have a value and you want to have enum like behavior and have a catch all case for all other values.
6//!
7//! ## Examples
8//!
9//! ```rust
10//! use nutype_enum::nutype_enum;
11//!
12//! nutype_enum! {
13//! pub enum AacPacketType(u8) {
14//! SeqHdr = 0x0,
15//! Raw = 0x1,
16//! }
17//! }
18//! ```
19//!
20//! ## License
21//!
22//! This project is licensed under the [MIT](./LICENSE.MIT) or [Apache-2.0](./LICENSE.Apache-2.0) license.
23//! You can choose between one of them if you use this work.
24//!
25//! `SPDX-License-Identifier: MIT OR Apache-2.0`
26#![deny(missing_docs)]
27#![deny(unsafe_code)]
28#![deny(unreachable_pub)]
29
30/// Helper macro to create a new enum type with a single field.
31///
32/// The enum type is derived with the `Clone`, `Copy`, `PartialEq`, `Eq`,
33/// `PartialOrd`, `Ord`, and `Hash` traits. The nutype also impls `From` and
34/// `Into` for the underlying type. As well as a custom `Debug` impl for human
35/// readable output.
36///
37/// # Examples
38///
39/// ```rust
40/// # use nutype_enum::nutype_enum;
41/// nutype_enum! {
42/// pub enum AacPacketType(u8) {
43/// SeqHdr = 0x0,
44/// Raw = 0x1,
45/// }
46/// }
47/// ```
48#[macro_export]
49macro_rules! nutype_enum {
50 (
51 $(#[$attr:meta])*
52 $vis:vis enum $name:ident($type:ty) {
53 $(
54 $(#[$variant_attr:meta])*
55 $variant:ident = $value:expr
56 ),*$(,)?
57 }
58 ) => {
59 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
60 $(#[$attr])*
61 #[repr(transparent)]
62 $vis struct $name(pub $type);
63
64 impl ::std::fmt::Debug for $name {
65 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66 match self {
67 $(
68 &$name::$variant => write!(f, "{}::{}", stringify!($name), stringify!($variant)),
69 )*
70 _ => write!(f, "{}({:?})", stringify!($name), self.0),
71 }
72 }
73 }
74
75 impl $name {
76 $(
77 $(#[$variant_attr])*
78 #[allow(non_upper_case_globals)]
79 pub const $variant: Self = Self($value);
80 )*
81 }
82
83 impl From<$type> for $name {
84 fn from(value: $type) -> Self {
85 Self(value)
86 }
87 }
88
89 impl From<$name> for $type {
90 fn from(value: $name) -> Self {
91 value.0
92 }
93 }
94 };
95}
96
97/// Helper macro to create a bitwise enum.
98///
99/// The enum type is derived with the `BitAnd`, `BitOr`, `BitXor`, `BitAndAssign`,
100/// `BitOrAssign`, and `BitXorAssign` traits.
101///
102/// # Examples
103///
104/// ```rust
105/// # use nutype_enum::{nutype_enum, bitwise_enum};
106/// nutype_enum! {
107/// pub enum IoFlags(u8) {
108/// Seek = 0x1,
109/// Write = 0x2,
110/// Read = 0x4,
111/// }
112/// }
113///
114/// bitwise_enum!(IoFlags);
115/// ```
116#[macro_export]
117macro_rules! bitwise_enum {
118 ($name:ident) => {
119 impl ::std::ops::BitAnd for $name {
120 type Output = Self;
121
122 fn bitand(self, rhs: Self) -> Self::Output {
123 Self(self.0 & rhs.0)
124 }
125 }
126
127 impl ::std::ops::BitOr for $name {
128 type Output = Self;
129
130 fn bitor(self, rhs: Self) -> Self::Output {
131 Self(self.0 | rhs.0)
132 }
133 }
134
135 impl ::std::ops::BitXor for $name {
136 type Output = Self;
137
138 fn bitxor(self, rhs: Self) -> Self::Output {
139 Self(self.0 ^ rhs.0)
140 }
141 }
142
143 impl ::std::ops::Not for $name {
144 type Output = Self;
145
146 fn not(self) -> Self::Output {
147 Self(!self.0)
148 }
149 }
150
151 impl ::std::ops::BitAndAssign for $name {
152 fn bitand_assign(&mut self, rhs: Self) {
153 self.0 &= rhs.0;
154 }
155 }
156
157 impl ::std::ops::BitOrAssign for $name {
158 fn bitor_assign(&mut self, rhs: Self) {
159 self.0 |= rhs.0;
160 }
161 }
162
163 impl ::std::ops::BitXorAssign for $name {
164 fn bitxor_assign(&mut self, rhs: Self) {
165 self.0 ^= rhs.0;
166 }
167 }
168 };
169}