Skip to main content

hexga_map_on/
map_on.rs

1/// A powerful macro to impl other macros for the given types.
2///
3/// Can be used to impl trait to a lot of type using macro, where generic can't.
4///
5/// ```rust
6/// use hexga_map_on::map_on;
7///
8/// trait Zero
9/// {
10///     const ZERO : Self;
11/// }
12///
13/// macro_rules! impl_zero {
14///     ($type_name:ty) => {
15///         impl Zero for $type_name
16///         {
17///             const ZERO : Self = 0 as Self;
18///         }
19///     };
20/// }
21///
22/// map_on!
23/// (
24///     (
25///         i8, i16, i32, i64, isize,
26///         u8, u16, u32, u64, usize,
27///         f32, f64
28///     ),
29///     impl_zero
30/// );
31///
32/// // ^^ this call impl Zero for all the given type
33///
34/// assert_eq!(i32::ZERO  , 0);
35/// assert_eq!(usize::ZERO, 0);
36/// assert_eq!(f32::ZERO  , 0.);
37/// ```
38#[macro_export]
39macro_rules! map_on {
40    // Base case: single type
41    ( ($type_name:tt), $mac:ident $(, $args:tt)* ) => {
42        $mac!($type_name $(, $args)*);
43    };
44    // Recursive case: multiple types
45    ( ($first_type:tt, $($rest_type:tt),+), $mac:ident $(, $args:tt)* ) => {
46        $crate::map_on!(($first_type), $mac $(, $args)*);
47        $crate::map_on!(($($rest_type),+), $mac $(, $args)*);
48    };
49
50    // Limitation :
51    // Can only be used in const context (ex: impl Trait).
52    // Ex: this **won't** work inside a function :
53    // ```
54    // map_on!((i32, f64, bool),
55    //    ($T:ident) => {
56    //        println!("Type: {}", std::any::type_name::<$T>());
57    //    }
58    // );
59    // ```
60    ($tokens:tt, $($macro_arms:tt)+) => {
61        const _: () = {
62            macro_rules! __map_on_inliner {
63                $($macro_arms)+
64            }
65
66            $crate::map_on!(@expand_tokens $tokens);
67        };
68    };
69
70    // Recursive expansion
71    (@expand_tokens ($first:tt $(, $rest:tt)*)) => {
72        __map_on_inliner!($first);
73        $crate::map_on!(@expand_tokens ($($rest),*))
74    };
75
76    (@expand_tokens ($last:tt)) => {
77        __map_on_inliner!($last);
78    };
79
80    (@expand_tokens ()) => {};
81
82
83    // Entry point for list of pairs with inline macro arms
84    ( ( $(($a:tt, $b:tt)),* $(,)? ), ($($params:tt)*) => $body:block ) => {
85        const _: () = {
86            macro_rules! __map_on_inliner {
87                ($($params)*) => $body
88            }
89
90            $(
91                __map_on_inliner!($a, $b);
92            )*
93        };
94    };
95
96    // Simple case: single identifiers
97    ( ($($types:tt),+), $mac:ident $(, $args:tt)* ) => {
98        $(
99            $mac!($types $(, $args)*);
100        )+
101    };
102}