tlbf/
lib.rs

1#![no_std]
2
3/// Type level combinator for bitflags.
4#[ghost::phantom]
5#[derive(Debug, Default)]
6pub struct Or<A, B>;
7
8impl<A: SetMember + Default, B: SetMember<Set = A::Set> + Default> Or<A, B>  {
9    pub fn contains(&self, other: impl SetMember<Set=Self>) -> bool {
10        other.in_set(self)
11    }
12
13    pub fn equals(&self, other: impl SetMember<Set=Self>) -> bool {
14        other.eq_set(self)
15    }
16}
17
18impl<A: SetMember + Default, B: SetMember<Set = A::Set> + Default> SetMember for Or<A, B>  {
19    type Set = A::Set;
20
21    fn to_set(&self) -> Self::Set {
22        A::default_set() | B::default_set()
23    }
24
25    fn eq_set(&self, set: &Self::Set) -> bool {
26        &Self::default_set() == set
27    }
28
29    fn in_set(&self, set: &Self::Set) -> bool {
30        A::default().in_set(set) || B::default().in_set(set)
31    }
32}
33
34/// Member of a set of flags.
35pub trait SetMember: Sized{
36    type Set: PartialEq + core::ops::BitOr<Self::Set, Output = Self::Set>;
37    fn to_set(&self) -> Self::Set;
38    fn eq_set(&self, set: &Self::Set) -> bool;
39    fn in_set(&self, set: &Self::Set) -> bool;
40    fn and_set(self, other: impl SetMember<Set = Self::Set>) -> Self::Set {
41        self.to_set() | other.to_set()
42    }
43    fn default_set() -> Self::Set where Self: Default {
44        Self::to_set(&Default::default())
45    }
46}
47
48/// Type level bitflags.
49/// 
50/// # Example
51/// 
52/// ```
53/// # use tlbf::*;
54/// tlbf!(
55///     pub Color: u64 {
56///         Red,
57///         Green, 
58///         Blue,
59///     }
60/// );
61/// assert!(Color::Red.contains(Red));
62/// assert!(!Color::Red.contains(Green));
63/// assert!(Red|Green == Color::Red|Color::Green);
64/// assert!((Red|Green).contains(Red));
65/// assert!((Red|Green).contains(Green));
66/// assert!(!(Red|Green).contains(Blue));
67/// ```
68#[macro_export]
69macro_rules! tlbf {
70    (
71        $(#[$($flags_args: tt)*])*
72        $vis: vis $flags_name: ident: $repr: ty {
73            $(
74                $(#[$($branch_args: tt)*])*
75                $vis2: vis $name: ident
76            ),* $(,)?
77        }
78    ) => {
79        $crate::tlbf! (
80            $(#[$($flags_args)*])*
81            $vis $flags_name: $repr {
82                $(
83                    $(#[$($branch_args)*])*
84                    $vis2 $name
85                ),*
86            }
87            {} (0)
88        );
89    };
90    (
91        $(#[$($flags_args: tt)*])*
92        $vis: vis $flags_name: ident: $repr: ty {
93            $(#[$($first_args: tt)*])*
94            $vis0: vis $first: ident
95            $(  
96                ,$(#[$($branch_args: tt)*])*
97                $vis2: vis $name: ident
98            )* $(,)?
99        }
100        {$($(#[$($a: tt)*])* $v: vis $x: ident = $y: expr),*} ($value: expr)
101    ) => {
102        $crate::tlbf! (
103            $(#[$($flags_args)*])*
104            $vis $flags_name: $repr {
105                $(
106                    $(#[$($branch_args)*])*
107                    $vis2 $name
108                ),*
109            }
110            {
111                $($(#[$($a)*])* $v $x = $y,)* 
112                $(#[$($first_args)*])*
113                $vis0 $first = $value
114            } ($value + 1)
115        );
116    };
117    (
118        $(#[$($flags_args: tt)*])*
119        $vis: vis $flags_name: ident: $repr: ty {$(,)?}
120        {$($(#[$($a: tt)*])* $vis2: vis $x: ident = $y: expr),*} ($value: expr)
121    ) => {
122        $crate::tlbf! (
123            $(#[$($flags_args)*])*
124            $vis $flags_name: $repr
125            {$($vis2 $x = $y),*}
126        );
127    };
128    (
129        $(#[$($flags_args: tt)*])*
130        $vis: vis $flags_name: ident: $repr: ty {
131            $(
132                $(#[$($branch_args: tt)*])*
133                $vis2: vis $name: ident = $value: expr
134            ),* $(,)?
135        }
136    ) => {
137        #[repr(transparent)]
138        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
139        $(#[$($flags_args)*])*
140        $vis struct $flags_name($repr);
141
142        const _: () = {
143            #[allow(non_upper_case_globals)]
144            impl $flags_name {
145                $($vis const $name: Self = Self(1 << ($value));)*
146
147                pub fn is_empty(&self) -> bool {
148                    self.0 == 0
149                }
150
151                pub fn contains(&self, other: impl $crate::SetMember<Set=Self>) -> bool {
152                    other.in_set(self)
153                }
154
155                pub fn equals(&self, other: impl $crate::SetMember<Set=Self>) -> bool {
156                    other.eq_set(self)
157                }
158
159                pub fn intersects(&self, other: impl $crate::SetMember<Set=Self>) -> bool {
160                    self.0 & other.to_set().0 > 0
161                }
162
163                pub const fn all() -> Self {
164                    Self($(Self::$name.0)|*)
165                }
166            }
167
168            impl $crate::SetMember for $flags_name {
169                type Set = $flags_name;
170                fn to_set(&self) -> Self::Set {
171                    (*self).into()
172                }
173                fn eq_set(&self, set: &Self::Set) -> bool {
174                    self == set
175                }
176                fn in_set(&self, set: &Self::Set) -> bool {
177                    set.0 & self.0 == self.0
178                }
179            }
180
181            impl<T> ::core::ops::BitAnd<T> for $flags_name where T: $crate::SetMember<Set = Self> {
182                type Output = Self;
183                fn bitand(self, rhs: T) -> Self {
184                    Self(self.0 & rhs.to_set().0)
185                }
186            }
187
188            impl<T> ::core::ops::BitOr<T> for $flags_name where T: $crate::SetMember<Set = Self> {
189                type Output = Self;
190                fn bitor(self, rhs: T) -> Self {
191                    Self(self.0 | rhs.to_set().0)
192                }
193            }
194
195            impl<T> ::core::ops::BitXor<T> for $flags_name where T: $crate::SetMember<Set = Self> {
196                type Output = Self;
197                fn bitxor(self, rhs: T) -> Self {
198                    Self(self.0 ^ rhs.to_set().0)
199                }
200            }
201
202            impl<T> ::core::ops::BitAndAssign<T> for $flags_name where T: $crate::SetMember<Set = Self> {
203                fn bitand_assign(&mut self, rhs: T) {
204                    self.0 &= rhs.to_set().0
205                }
206            }
207
208            impl<T> ::core::ops::BitOrAssign<T> for $flags_name where T: $crate::SetMember<Set = Self> {
209                fn bitor_assign(&mut self, rhs: T) {
210                    self.0 |= rhs.to_set().0
211                }
212            }
213
214            impl<T> ::core::ops::BitXorAssign<T> for $flags_name where T: $crate::SetMember<Set = Self> {
215                fn bitxor_assign(&mut self, rhs: T) {
216                    self.0 ^= rhs.to_set().0
217                }
218            }
219        };
220
221
222        $(
223            $(#[$($branch_args)*])*
224            #[derive(Debug, Default, Clone, Copy, Eq, Hash)]
225            $vis2 struct $name;
226
227            const _: () = {
228                use $crate::SetMember;
229                impl ::core::fmt::Display for $name {
230                    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
231                        f.write_str(stringify!($name))
232                    }
233                }
234    
235                impl ::core::convert::From<$name> for $flags_name {
236                    fn from(_: $name) -> Self {
237                        Self::$name
238                    }
239                }
240
241                impl ::core::convert::From<&$name> for $flags_name {
242                    fn from(_: &$name) -> Self {
243                        Self::$name
244                    }
245                }
246    
247                impl $crate::SetMember for $name {
248                    type Set = $flags_name;
249                    fn to_set(&self) -> Self::Set {
250                        self.into()
251                    }
252                    fn eq_set(&self, set: &Self::Set) -> bool {
253                        set == &Self::Set::$name
254                    }
255                    fn in_set(&self, set: &Self::Set) -> bool {
256                        *set & Self::Set::$name == Self::Set::$name
257                    }
258                }
259    
260                impl<T> ::core::ops::BitOr<T> for $name where T: SetMember<Set=$flags_name>{
261                    type Output = $flags_name;
262                    fn bitor(self, rhs: T) -> $flags_name {
263                        $flags_name::$name | rhs.to_set()
264                    }
265                }
266
267                impl<T> ::core::cmp::PartialEq<T> for $name where T: $crate::SetMember<Set=$flags_name>{
268                    fn eq(&self, other: &T) -> bool {
269                        $flags_name::$name == other.to_set()
270                    }
271                }
272            };
273        )*
274    };
275}
276
277
278/// Join bitflags at the type level.
279/// 
280/// ```
281/// # use tlbf::*;
282/// # tlbf!(
283/// #     pub Color: u64 {
284/// #         pub Red, Green, Blue,
285/// #     }
286/// # );
287/// let flags = tyflags!(Red|Blue);
288/// assert!(flags.contains(Color::Red));
289/// assert!(flags.contains(Color::Blue));
290/// assert!(!flags.contains(Color::Green));
291/// ```
292#[macro_export]
293macro_rules! tyflags {
294    ($expr: expr $(,)?) => {
295        $expr
296    };
297    ($first: expr $(,$expr: expr)* $(,)?) => {
298        $crate::Or<$first, $crate::type_join!($($expr),*)>
299    };
300}
301
302#[cfg(test)]
303mod test {
304
305    tlbf!(
306        pub Unit1: u8 {
307            Hello
308        }
309    );
310    tlbf!(
311        pub Unit2: u8 {
312            Hiii,
313        }
314    );
315    #[test]
316    pub fn test(){
317        tlbf!(
318            pub Mascot: u8 {
319                pub Ferris
320            }
321        );
322        tlbf!(
323            #[derive(Default)]
324            LesserMascots: u8 {
325                #[repr(C)]
326                Gopher
327            }
328        );
329        assert_eq!(Mascot::all(), Mascot::Ferris);
330
331        tlbf!(
332            pub Colors: u8 {
333                pub Red,
334                pub Blue,
335                pub Green,
336            }
337        );
338        assert_eq!(Colors::all(), Colors::Red|Colors::Blue|Colors::Green);
339    }
340}