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}