meta_tuple/
macro.rs

1#[allow(unused)]
2use crate::{IntoMetaTuple, MetaItem, MetaTuple};
3
4/// Create a [`MetaTuple`].
5///
6/// # Syntax
7///
8/// To create a tuple like [`MetaTuple`]:
9///
10/// ```
11/// meta_tuple!(1, 2.0, "hello", vec![1, 2])
12/// ```
13///
14/// You can use `&` and `&mut`, to create non-static [`MetaTuple`]s,
15/// keep in mind these are handled at the syntax level and not the type level.
16///
17/// ```
18/// let a = 1;
19/// let b = true
20/// meta_tuple!(&a, &mut b);
21/// ```
22///
23/// If already given a reference `x: &T`, using `x` is not allowed as the type of
24/// `x` is not static, use `&*x` instead.
25///
26/// ```
27/// let a = &1;
28/// let b = &mut true
29/// meta_tuple!(&*a, &mut *b);
30/// ```
31///
32/// To join types that are already [`MetaTuple`]s, denote with a `#`.
33///
34/// ```
35/// let a = meta_tuple!(1, 2.0);
36/// let b = meta_tuple!(true);
37/// let c = meta_tuple!(#a, #b, "hello");
38/// ```
39#[macro_export]
40macro_rules! meta_tuple {
41    () => {()};
42    (@[$prev: expr]) => {
43        $prev
44    };
45    (@[$prev: expr] #$e: expr $(, $($rest: tt)*)?) => {
46        meta_tuple!(@[$crate::Join($prev, $e)] $($($rest)*)?)
47    };
48    (@[$prev: expr] &mut $e: expr $(, $($rest: tt)*)?) => {
49        meta_tuple!(@[$crate::Join($prev, $crate::MetaItem::from_mut(&mut $e))] $($($rest)*)?)
50    };
51    (@[$prev: expr] &$e: expr $(, $($rest: tt)*)?) => {
52        meta_tuple!(@[$crate::Join($prev, $crate::MetaItem::from_ref(&$e))] $($($rest)*)?)
53    };
54    (@[$prev: expr] $e: expr $(, $($rest: tt)*)?) => {
55        meta_tuple!(@[$crate::Join($prev, $crate::MetaItem($e))] $($($rest)*)?)
56    };
57    (#$e: expr $(, $($rest: tt)*)?) => {
58        meta_tuple!(@[$e] $($($rest)*)?)
59    };
60    (&mut $e: expr $(, $($rest: tt)*)?) => {
61        meta_tuple!(@[$crate::MetaItem::from_mut(&mut $e)] $($($rest)*)?)
62    };
63    (&$e: expr $(, $($rest: tt)*)?) => {
64        meta_tuple!(@[$crate::MetaItem::from_ref(&$e)] $($($rest)*)?)
65    };
66    ($e: expr $(, $($rest: tt)*)?) => {
67        meta_tuple!(@[$crate::MetaItem($e)] $($($rest)*)?)
68    };
69}
70
71/// Creates the typing of a [`MetaTuple`].
72#[macro_export]
73macro_rules! meta_tuple_type {
74    () => {()};
75    (@[$prev: ty]) => {
76        $prev
77    };
78    (@[$prev: ty] #$ty: ty $(, $($tt:tt)*)?) => {
79        $crate::meta_tuple_type!{@[$crate::Join<$prev, $ty>] $($($tt)*)?}
80    };
81    (@[$prev: ty] &mut $ty: ty $(, $($tt:tt)*)?) => {
82        $crate::meta_tuple_type!{@[$crate::Join<$prev, &mut $crate::MetaItem<$ty>>] $($($tt)*)?}
83    };
84    (@[$prev: ty] &$ty: ty $(, $($tt:tt)*)?) => {
85        $crate::meta_tuple_type!{@[$crate::Join<$prev, &$crate::MetaItem<$ty>>] $($($tt)*)?}
86    };
87    (@[$prev: ty] $ty: ty $(, $($tt:tt)*)?) => {
88        $crate::meta_tuple_type!{@[$crate::Join<$prev, $crate::MetaItem<$ty>>] $($($tt)*)?}
89    };
90    (#$ty: ty $(, $($tt:tt)*)?) => {
91        $crate::meta_tuple_type!{@[$ty] $($($tt)*)?}
92    };
93    (&mut $ty: ty $(, $($tt:tt)*)?) => {
94        $crate::meta_tuple_type!{@[&mut $crate::MetaItem<$ty>] $($($tt)*)?}
95    };
96    (&$ty: ty $(, $($tt:tt)*)?) => {
97        $crate::meta_tuple_type!{@[&$crate::MetaItem<$ty>] $($($tt)*)?}
98    };
99    ($ty: ty $(, $($tt:tt)*)?) => {
100        $crate::meta_tuple_type!{@[$crate::MetaItem<$ty>] $($($tt)*)?}
101    };
102}
103
104/// Implement [`MetaTuple`] for a type and by proxy [`IntoMetaTuple`], making it equivalent to [`MetaItem<T>`].
105///
106/// This is useful to satisfy API constraints.
107///
108/// # Syntax
109///
110/// This is equivalent to a derive macro.
111///
112/// ```
113/// // Equivalent to impl MetaTuple for MyType {}
114/// impl_meta_tuple!(MyType)
115///
116/// // Equivalent to impl<T: Copy> MetaTuple for MyType <T> {}
117/// impl_meta_tuple!([T: Copy]MyType[T])
118/// ```
119#[macro_export]
120macro_rules! impl_meta_tuple {
121    ($ty: ident) => {
122        impl $crate::MetaBox for $ty {
123            fn as_erased(&self) -> $crate::ErasedInner<'_> {
124                $crate::ErasedInner::Any(self)
125            }
126            fn as_erased_mut(&mut self) -> $crate::ErasedInnerMut<'_> {
127                $crate::ErasedInnerMut::Any(self)
128            }
129        }
130        impl $crate::MetaTuple for $ty {
131            fn get<__T: 'static>(&self) -> Option<&__T> {
132                (self as &dyn $crate::Any).downcast_ref()
133            }
134            fn get_mut<__T: 'static>(&mut self) -> Option<&mut __T> {
135                (self as &mut dyn $crate::Any).downcast_mut()
136            }
137        }
138    };
139
140    ($ty: ident [$($a: tt)*]) => {
141        $crate::impl_meta_tuple!{[$($a)*] $ty [$($a)*]}
142    };
143
144    ([$($a: tt)*]$ty: ident [$($b: tt)*]) => {
145        impl<$($a)*> $crate::MetaBox for $ty<$($b)*> where Self: 'static {
146            fn as_erased(&self) -> $crate::ErasedInner<'_> {
147                $crate::ErasedInner::Any(self)
148            }
149            fn as_erased_mut(&mut self) -> $crate::ErasedInnerMut<'_> {
150                $crate::ErasedInnerMut::Any(self)
151            }
152        }
153        impl<$($a)*> $crate::MetaTuple for $ty<$($b)*> where Self: 'static {
154            /// Obtain an item, if exists.
155            fn get<__T: 'static>(&self) -> Option<&__T> {
156                (self as &dyn $crate::Any).downcast_ref()
157            }
158            /// Obtain a mutable item, if exists.
159            fn get_mut<__T: 'static>(&mut self) -> Option<&mut __T> {
160                (self as &mut dyn $crate::Any).downcast_mut()
161            }
162        }
163    };
164}