hexga_map_on/
lib.rs

1#![no_std]
2
3/// A powerful macro to impl other macros for the given types.
4/// 
5/// Can be used to impl trait to a lot of type using macro, where generic can't.
6///
7/// ```rust
8/// use hexga_map_on::map_on;
9/// 
10/// trait Zero
11/// {
12///     const ZERO : Self;
13/// }
14/// 
15/// macro_rules! impl_zero {
16///     ($type_name:ty) => {
17///         impl Zero for $type_name
18///         {
19///             const ZERO : Self = 0 as Self;
20///         }
21///     };
22/// }
23/// 
24/// map_on!
25/// (
26///     (
27///         i8, i16, i32, i64, isize,
28///         u8, u16, u32, u64, usize,
29///         f32, f64
30///     ), 
31///     impl_zero
32/// );
33/// 
34/// // ^^ this call impl Zero for all the given type
35/// 
36/// assert_eq!(i32::ZERO  , 0);
37/// assert_eq!(usize::ZERO, 0);
38/// assert_eq!(f32::ZERO  , 0.);
39/// ``` 
40#[macro_export]
41macro_rules! map_on {
42    // Base case: single type
43    ( ($type_name:tt), $mac:ident $(, $args:tt)* ) => {
44        $mac!($type_name $(, $args)*);
45    };
46    // Recursive case: multiple types
47    ( ($first_type:tt, $($rest_type:tt),+), $mac:ident $(, $args:tt)* ) => {
48        map_on!(($first_type), $mac $(, $args)*);
49        map_on!(($($rest_type),+), $mac $(, $args)*);
50    };
51
52    // Limitation :
53    // Can only be used in const context (ex: impl Trait).
54    // Ex: this **won't** work inside a function :
55    // ```
56    // map_on!((i32, f64, bool),
57    //    ($T:ident) => {
58    //        println!("Type: {}", std::any::type_name::<$T>());
59    //    }
60    // );
61    // ```
62    ($tokens:tt, $($macro_arms:tt)+) => {
63        const _: () = {
64            macro_rules! __map_on_inliner {
65                $($macro_arms)+
66            }
67
68            $crate::map_on!(@expand_tokens $tokens);
69        };
70    };
71
72    // Recursive expansion
73    (@expand_tokens ($first:tt $(, $rest:tt)*)) => {
74        __map_on_inliner!($first);
75        $crate::map_on!(@expand_tokens ($($rest),*))
76    };
77
78    (@expand_tokens ($last:tt)) => {
79        __map_on_inliner!($last);
80    };
81
82    (@expand_tokens ()) => {};
83
84
85    // Entry point for list of pairs with inline macro arms
86    ( ( $(($a:tt, $b:tt)),* $(,)? ), ($($params:tt)*) => $body:block ) => {
87        const _: () = {
88            macro_rules! __map_on_inliner {
89                ($($params)*) => $body
90            }
91
92            $(
93                __map_on_inliner!($a, $b);
94            )*
95        };
96    };
97
98    // Simple case: single identifiers
99    ( ($($types:tt),+), $mac:ident $(, $args:tt)* ) => {
100        $(
101            $mac!($types $(, $args)*);
102        )+
103    };
104}
105
106/// `u8`, `u16`, `u32`, `u64`, `usize`
107#[macro_export]
108macro_rules! map_on_integer_unsigned {
109    ($($macro_arms:tt)*) => {
110        $crate::map_on!((u8, u16, u32, u64, usize), $($macro_arms)*);
111    };
112}
113
114
115/// `i8`, `i16`, `i32`, `i64`, `isize`
116#[macro_export]
117macro_rules! map_on_integer_signed {
118    ($($macro_arms:tt)*) => {
119        $crate::map_on!((i8, i16, i32, i64, isize), $($macro_arms)*);
120    };
121}
122
123/// (`u8`, `u16`, `u32`, `u64`, `usize`) + (`i8`, `i16`, `i32`, `i64`, `isize`)
124#[macro_export]
125macro_rules! map_on_integer 
126{
127    ($($macro_arms:tt)*) => {
128        $crate::map_on_integer_unsigned!($($macro_arms)*);
129        $crate::map_on_integer_signed!($($macro_arms)*);
130    };
131}
132
133/// `f32`, `f64`
134#[macro_export]
135macro_rules! map_on_float 
136{
137    ($($macro_arms:tt)*) => {
138        $crate::map_on!((f32, f64), $($macro_arms)*);
139    };
140}
141
142/// (`u8`, `u16`, `u32`, `u64`, `usize`) + (`i8`, `i16`, `i32`, `i64`, `isize`) + (`f32`, `f64`)
143#[macro_export]
144macro_rules! map_on_number 
145{
146    ($($macro_arms:tt)*) => {
147        $crate::map_on_integer!($($macro_arms)*);
148        $crate::map_on_float!($($macro_arms)*);
149    };
150}
151
152/// (`u8`, `u16`, `u32`, `u64`, `usize`) + (`i8`, `i16`, `i32`, `i64`, `isize`) + (`f32`, `f64`) + (`bool`)
153#[macro_export]
154macro_rules! map_on_number_and_bool 
155{
156    ($($macro_arms:tt)*) => {
157        $crate::map_on_number!($($macro_arms)*);
158        $crate::map_on!((bool), $($macro_arms)*);
159    };
160}
161
162
163/// `Add`, `Sub`
164#[macro_export]
165macro_rules! map_on_operator_binary_arithmetic_unit {
166    ($($macro_arms:tt)*) => {
167        $crate::map_on!
168        (
169            (
170                (Add, add),
171                (Sub, sub)
172            ), 
173            $($macro_arms)*
174        );
175    };
176}
177
178
179/// (`Add`, `Sub`) + (`Mul`, `Div`, `Rem`)
180#[macro_export]
181macro_rules! map_on_operator_binary_arithmetic {
182    ($($macro_arms:tt)*) => {
183        $crate::map_on_operator_binary_arithmetic_unit!($($macro_arms)*);
184        $crate::map_on!
185        (
186            (
187                (Mul, mul),
188                (Div, div),
189                (Rem, rem)
190            ), 
191            $($macro_arms)*
192        );
193    };
194}
195
196/// `BitOr`, `BitAnd`, `Shl`, `Shr`
197#[macro_export]
198macro_rules! map_on_operator_binary_bit {
199    ($($macro_arms:tt)*) => {
200        $crate::map_on!
201        (
202            (
203                (BitOr, bitor),
204                (BitAnd, bitand),
205                (Shl, shl),
206                (Shr, shr)
207            ), 
208            $($macro_arms)*
209        );
210    };
211}
212
213/// (`Add`, `Sub`) + (`Mul`, `Div`, `Rem`) + (`BitOr`, `BitAnd`, `Shl`, `Shr`)
214#[macro_export]
215macro_rules! map_on_operator_binary 
216{
217    ($($macro_arms:tt)*) => {
218        $crate::map_on_operator_binary_arithmetic!($($macro_arms)*);
219        $crate::map_on_operator_binary_bit!($($macro_arms)*);
220    };
221}
222
223
224
225
226
227/// `AddAssign`, `SubAssign`
228#[macro_export]
229macro_rules! map_on_operator_assign_arithmetic_unit {
230    ($($macro_arms:tt)*) => {
231        $crate::map_on!
232        (
233            (
234                (AddAssign, add_assign),
235                (SubAssign, sub_assign)
236            ), 
237            $($macro_arms)*
238        );
239    };
240}
241
242
243/// (`AddAssign`, `SubAssign`) + (`MulAssign`, `DivAssign`, `RemAssign`)
244#[macro_export]
245macro_rules! map_on_operator_assign_arithmetic {
246    ($($macro_arms:tt)*) => {
247        $crate::map_on_operator_assign_arithmetic_unit!($($macro_arms)*);
248        $crate::map_on!
249        (
250            (
251                (MulAssign, mul_assign),
252                (DivAssign, div_assign),
253                (RemAssign, rem_assign)
254            ), 
255            $($macro_arms)*
256        );
257    };
258}
259
260/// `BitOrAssign`, `BitAndAssign`, `ShlAssign`, `ShrAssign`
261#[macro_export]
262macro_rules! map_on_operator_assign_bit {
263    ($($macro_arms:tt)*) => {
264        $crate::map_on!
265        (
266            (
267                (BitOrAssign, bitor_assign),
268                (BitAndAssign, bitand_assign),
269                (ShlAssign, shl_assign),
270                (ShrAssign, shr_assign)
271            ), 
272            $($macro_arms)*
273        );
274    };
275}
276
277/// (`AddAssign`, `SubAssign`) + (`MulAssign`, `DivAssign`, `RemAssign`) + (`BitOrAssign`, `BitAndAssign`, `ShlAssign`, `ShrAssign`)
278#[macro_export]
279macro_rules! map_on_operator_assign 
280{
281    ($($macro_arms:tt)*) => {
282        $crate::map_on_operator_assign_arithmetic!($($macro_arms)*);
283        $crate::map_on_operator_assign_bit!($($macro_arms)*);
284    };
285}
286
287
288
289
290
291
292
293
294/// `Not`
295#[macro_export]
296macro_rules! map_on_operator_unary_bit 
297{
298    ($($macro_arms:tt)*) => {
299        $crate::map_on!
300        (
301            (
302                (Not, not)
303            ), 
304            $($macro_arms)*
305        );
306    };
307}
308
309/// `Neg`, `Abs`
310#[macro_export]
311macro_rules! map_on_operator_unary_arithmetic_unit 
312{
313    ($($macro_arms:tt)*) => {
314        $crate::map_on!
315        (
316            (
317                (Neg, neg),
318                (Abs, abs)
319            ), 
320            $($macro_arms)*
321        );
322    };
323}
324
325
326/// (`Not`) + (`Neg`, `Abs`)
327#[macro_export]
328macro_rules! map_on_operator_unary
329{
330    ($($macro_arms:tt)*) => {
331        $crate::map_on_operator_unary_bit!($($macro_arms)*);
332        $crate::map_on_operator_unary_arithmetic_unit!($($macro_arms)*);
333    };
334}