modio/types/
macros.rs

1// macro: bitflags {{{
2macro_rules! bitflags {
3    (
4        $(#[$outer:meta])*
5        $vis:vis struct $BitFlags:ident: $T:ty {
6            $(
7                $(#[$inner:ident $($args:tt)*])*
8                const $Flag:ident = $value:expr;
9            )*
10        }
11
12        $($t:tt)*
13    ) => {
14        $(#[$outer])*
15        #[derive(Copy, Clone, Eq, PartialEq, Deserialize)]
16        $vis struct $BitFlags($T);
17
18        bitflags::bitflags! {
19            impl $BitFlags: $T {
20                $(
21                    $(#[$inner $($args)*])*
22                    const $Flag = $value;
23                )*
24            }
25        }
26
27        impl std::fmt::Debug for $BitFlags {
28            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
29                struct Internal($BitFlags);
30                impl std::fmt::Debug for Internal {
31                    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32                        bitflags::parser::to_writer(&self.0, f)
33                    }
34                }
35                let mut tuple = f.debug_tuple(stringify!($BitFlags));
36                if self.is_empty() {
37                    tuple.field(&format_args!("{0:#x}", <$T as bitflags::Bits>::EMPTY));
38                } else {
39                    tuple.field(&Internal(*self));
40                }
41                tuple.finish()
42            }
43        }
44
45        impl ::std::fmt::Display for $BitFlags {
46            fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
47                self.bits().fmt(f)
48            }
49        }
50
51        bitflags! {
52            $($t)*
53        }
54    };
55    () => {};
56}
57// }}}
58
59// macro: newtype_enum {{{
60macro_rules! newtype_enum {
61    (
62        $(#[$outer:meta])*
63        $vis:vis struct $NewtypeEnum:ident: $T:ty {
64            $(
65                $(#[$inner:meta $($args:tt)*])*
66                const $Variant:ident = $value:expr;
67            )*
68        }
69
70        $($t:tt)*
71    ) => {
72        $(#[$outer])*
73        #[derive(Clone, Copy, Eq, Hash, PartialEq, Deserialize)]
74        $vis struct $NewtypeEnum($T);
75
76        impl $NewtypeEnum {
77            $(
78                $(#[$inner $($args)*])*
79                pub const $Variant: Self = Self($value);
80            )*
81
82            /// Create a new value from a raw value.
83            pub fn new(raw_value: $T) -> Self {
84                Self(raw_value)
85            }
86
87            /// Retrieve the raw value.
88            pub fn get(self) -> $T {
89                self.0
90            }
91        }
92
93        impl std::fmt::Debug for $NewtypeEnum {
94            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
95                match *self {
96                    $(Self::$Variant => f.write_str(concat!(stringify!($NewtypeEnum), "::", stringify!($Variant))),)*
97                    _ => f.debug_tuple(stringify!($NewtypeEnum)).field(&self.0).finish(),
98                }
99            }
100        }
101
102        impl std::fmt::Display for $NewtypeEnum {
103            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104                std::fmt::Display::fmt(&self.0, f)
105            }
106        }
107
108        impl From<$T> for $NewtypeEnum {
109            fn from(value: $T) -> Self {
110                Self(value)
111            }
112        }
113
114        impl From<$NewtypeEnum> for $T {
115            fn from(value: $NewtypeEnum) -> $T {
116                value.get()
117            }
118        }
119
120        newtype_enum! {
121            $($t)*
122        }
123    };
124    (
125        $(#[$outer:meta])*
126        $vis:vis struct $NewtypeEnum:ident<$LENGTH:literal> {
127            $(
128                $(#[$inner:meta $($args:tt)*])*
129                const $Variant:ident = $value:expr;
130            )*
131        }
132
133        $($t:tt)*
134    ) => {
135        $(#[$outer])*
136        #[derive(Clone, Copy, Eq, Hash, PartialEq)]
137        $vis struct $NewtypeEnum(crate::types::utils::SmallStr<$LENGTH>);
138
139        impl $NewtypeEnum {
140            $(
141                $(#[$inner $($args)*])*
142                pub const $Variant: Self = Self::from_bytes($value);
143            )*
144
145            const fn from_bytes(input: &[u8]) -> Self {
146                Self(crate::types::utils::SmallStr::from_bytes(input))
147            }
148
149            pub fn as_str(&self) -> &str {
150                self.0.as_str()
151            }
152        }
153
154        impl std::fmt::Debug for $NewtypeEnum {
155            fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
156                match *self {
157                    $(Self::$Variant => f.write_str(concat!(stringify!($NewtypeEnum), "::", stringify!($Variant))),)*
158                    _ => f.debug_tuple(stringify!($NewtypeEnum)).field(&self.0).finish(),
159                }
160            }
161        }
162
163        impl PartialEq<&str> for $NewtypeEnum {
164            fn eq(&self, other: &&str) -> bool {
165                self.as_str().eq_ignore_ascii_case(other)
166            }
167        }
168
169        impl PartialEq<$NewtypeEnum> for &str {
170            fn eq(&self, other: &$NewtypeEnum) -> bool {
171                self.eq_ignore_ascii_case(other.as_str())
172            }
173        }
174
175        impl PartialEq<str> for $NewtypeEnum {
176            fn eq(&self, other: &str) -> bool {
177                self.as_str().eq_ignore_ascii_case(other)
178            }
179        }
180
181        impl PartialEq<$NewtypeEnum> for str {
182            fn eq(&self, other: &$NewtypeEnum) -> bool {
183                self.eq_ignore_ascii_case(other.as_str())
184            }
185        }
186
187        newtype_enum! {
188            $($t)*
189        }
190    };
191    () => {};
192}
193// }}}
194
195// vim: fdm=marker