Oregami
Repositories/oxedyne/fe2o3

oxedyne/fe2o3/fe2o3_core/src/macros/meta.rs

7.2 KiB, 15 runs

created by r1870400018:100, which is this file's identity for as long as the history lasts, whatever it is later renamed to

download · who wrote it · its history

1#[macro_export]
2macro_rules! new_type {
3 ($newtyp:ident, $wrapped:ty, $($derive:ty),* $(,)?) => {
4
5 #[repr(transparent)]
6 #[derive($($derive),*)]
7 pub struct $newtyp(pub $wrapped);
8
9 impl std::ops::Deref for $newtyp {
10 type Target = $wrapped;
11 fn deref(&self) -> &Self::Target {
12 &self.0
13 }
14 }
15
16 impl std::ops::DerefMut for $newtyp {
17 fn deref_mut(&mut self) -> &mut Self::Target {
18 &mut self.0
19 }
20 }
21
22 impl oxedyne_fe2o3_core::conv::IntoInner for $newtyp {
23 type Inner = $wrapped;
24 fn into_inner(self) -> Self::Inner {
25 self.0
26 }
27 }
28 };
29 ($newtyp:ident, $wrapped:ty) => {
30
31 #[repr(transparent)]
32 pub struct $newtyp(pub $wrapped);
33
34 impl std::ops::Deref for $newtyp {
35 type Target = $wrapped;
36 fn deref(&self) -> &Self::Target {
37 &self.0
38 }
39 }
40
41 impl std::ops::DerefMut for $newtyp {
42 fn deref_mut(&mut self) -> &mut Self::Target {
43 &mut self.0
44 }
45 }
46
47 impl oxedyne_fe2o3_core::conv::IntoInner for $newtyp {
48 type Inner = $wrapped;
49 fn into_inner(self) -> Self::Inner {
50 self.0
51 }
52 }
53 };
54}
55
56#[macro_export]
57macro_rules! new_type_priv {
58 ($newtyp:ident, $wrapped:ty, $($derive:ty),* $(,)?) => {
59
60 #[repr(transparent)]
61 #[derive($($derive),*)]
62 pub struct $newtyp($wrapped);
63
64 impl std::ops::Deref for $newtyp {
65 type Target = $wrapped;
66 fn deref(&self) -> &Self::Target {
67 &self.0
68 }
69 }
70
71 impl oxedyne_fe2o3_core::conv::IntoInner for $newtyp {
72 type Inner = $wrapped;
73 fn into_inner(self) -> Self::Inner {
74 self.0
75 }
76 }
77 };
78 ($newtyp:ident, $wrapped:ty) => {
79
80 #[repr(transparent)]
81 pub struct $newtyp($wrapped);
82
83 impl std::ops::Deref for $newtyp {
84 type Target = $wrapped;
85 fn deref(&self) -> &Self::Target {
86 &self.0
87 }
88 }
89
90 impl oxedyne_fe2o3_core::conv::IntoInner for $newtyp {
91 type Inner = $wrapped;
92 fn into_inner(self) -> Self::Inner {
93 self.0
94 }
95 }
96 };
97}
98
99#[macro_export]
100macro_rules! new_type_gen {
101 ($newtyp:ident, $($bound:ident),* ; $($derive:ty),* $(,)? ) => {
102
103 #[derive($($derive),*)]
104 pub struct $newtyp<N: $($bound)+>(pub N);
105
106 impl<N: $($bound)+> std::ops::Deref for $newtyp<N> {
107 type Target = N;
108 fn deref(&self) -> &Self::Target {
109 &self.0
110 }
111 }
112 }
113}
114
115/// Creates iteration capabilities for enums by implementing methods to access variants as arrays
116/// and count them.
117///
118/// # Features
119/// - `variants()`: Returns a const array containing all enum variants
120/// - `num_of_variants()`: Returns the total number of variants as a const usize
121///
122/// # Use Cases
123/// - Error handling and status reporting
124/// - State machine implementations
125/// - Configuration options
126/// - UI element types
127/// - Protocol message types
128/// - Testing different cases systematically
129///
130/// # Examples
131///
132/// ## Basic enum without fields
133/// ```rust
134/// #[derive(Clone, Copy, Debug)]
135/// pub enum LogLevel {
136/// Debug,
137/// Info,
138/// Warning,
139/// Error,
140/// }
141///
142/// new_enum!(LogLevel; Debug, Info, Warning, Error);
143///
144/// // Iterate through all log levels.
145/// for level in LogLevel::variants() {
146/// println!("Processing log level: {:?}", level);
147/// }
148/// ```
149///
150/// ## Enum with fields
151/// ```rust
152/// #[derive(Debug)]
153/// pub enum DatabaseError {
154/// ConnectionFailed(String),
155/// QueryError(i32, String),
156/// Timeout(u64),
157/// }
158///
159/// new_enum!(DatabaseError;
160/// ConnectionFailed("connection refused".to_string()),
161/// QueryError(-1, "syntax error".to_string()),
162/// Timeout(30),
163/// );
164///
165/// // Use in error handling.
166/// for error in DatabaseError::variants() {
167/// println!("Error handler for: {:?}", error);
168/// }
169/// ```
170///
171/// ## State machine states
172/// ```rust
173/// #[derive(Clone, Copy, Debug, PartialEq)]
174/// pub enum ConnectionState {
175/// Disconnected,
176/// Connecting,
177/// Connected,
178/// Closing,
179/// }
180///
181/// new_enum!(ConnectionState; Disconnected, Connecting, Connected, Closing);
182///
183/// // Validate state transitions.
184/// fn is_valid_transition(from: ConnectionState, to: ConnectionState) -> bool {
185/// match (from, to) {
186/// (ConnectionState::Disconnected, ConnectionState::Connecting) => true,
187/// (ConnectionState::Connecting, ConnectionState::Connected) => true,
188/// (ConnectionState::Connected, ConnectionState::Closing) => true,
189/// (ConnectionState::Closing, ConnectionState::Disconnected) => true,
190/// _ => false,
191/// }
192/// }
193///
194/// // Test all possible state transitions.
195/// for from_state in ConnectionState::variants() {
196/// for to_state in ConnectionState::variants() {
197/// println!("{:?} -> {:?}: {}",
198/// from_state,
199/// to_state,
200/// is_valid_transition(from_state, to_state)
201/// );
202/// }
203/// }
204/// ```
205///
206/// ## UI Components
207/// ```rust
208/// #[derive(Debug)]
209/// pub enum DialogType {
210/// Info(String),
211/// Warning(String, bool),
212/// Error(String, String), // message and technical details
213/// }
214///
215/// new_enum!(DialogType;
216/// Info("Information".to_string()),
217/// Warning("Warning".to_string(), true),
218/// Error("Error".to_string(), "Stack trace".to_string()),
219/// );
220///
221/// // Test rendering of all dialog types.
222/// fn test_dialog_rendering() {
223/// for dialog in DialogType::variants() {
224/// println!("Rendering dialog: {:?}", dialog);
225/// }
226/// }
227/// ```
228///
229/// # Note
230/// - **Variant Duplication Required**: This macro requires duplicating enum variants to avoid
231/// compile-time overhead from proc-macro parsing. This trade-off is acceptable for enums
232/// with variants that aren't likely to change frequently (like Country, Color, etc.).
233/// The duplication ensures fast compile times while providing convenient iteration and
234/// random selection functionality.
235/// - The macro generates const methods, allowing use in const contexts
236/// - Fields in variants must implement Copy or provide owned values
237/// - Useful for exhaustive testing and validation
238/// - Can be combined with other derive macros like Clone, Copy, Debug
239#[macro_export]
240macro_rules! new_enum {
241 ($name:ident; $($variant:ident $(($($field:expr),+))?,)*) => {
242 impl $name {
243 const fn variants() -> [$name; 0 $(+ (1 $(+ <[()]>::len(&[$($field),+]))?))*] {
244 [$($name::$variant $(($($field),+))?),*]
245 }
246 const fn num_of_variants() -> usize {
247 0 $(+ (1 $(+ <[()]>::len(&[$($field),+]))?))*
248 }
249 pub fn rand() -> Self {
250 let index = ::oxedyne_fe2o3_core::rand::Rand::in_range(0, Self::num_of_variants());
251 Self::variants()[index]
252 }
253 }
254 }
255}