dynamic_provider/
tag_macro.rs

1/// Declares one or more [`ResourceTag`][crate::ResourceTag] implementations.
2///
3/// ```
4/// # use dynamic_provider::define_tag;
5/// use core::ops::Deref;
6///
7/// define_tag! {
8///     /// Tag describing a numeric status code.
9///     pub tag StatusCode: i32;
10///
11///     /// Tag describing a pair of references to `T` and the target of `U`.
12///     pub tag RefPair<T, U>: for<'x> (&'x T, &'x U::Target) where U: Deref;
13///
14///     /// Tag for retrieving a reference given a string slice.
15///     pub tag GetRefByName<T: ?Sized>: for<'data, 'request> &'request str => &'data T;
16/// }
17/// ```
18#[macro_export]
19macro_rules! define_tag {
20    {} => {};
21    {
22        $(#$attr:tt)*
23        $vis:vis tag $Name:ident $(<$($T:ident),* $(,)?>)? : for<$($lt:lifetime),* $(,)?> $T1:ty $( => $T2:ty )? ;
24        $($rest:tt)*
25    } => {
26        $crate::__define_tag! {
27            @lt_generics = {};
28            @generics = { $($($T,)*)? };
29            @lt_generics_with_bounds = {};
30            @generics_with_bounds = { $($T,)* };
31            @attrs = { $($attr)* };
32            $vis tag $Name<>: for<$($lt),*> $T1 $(=> $T2)?;
33        }
34
35        $crate::define_tag! { $($rest)* };
36    };
37    {
38        $(#$attr:tt)*
39        $vis:vis tag $Name:ident < $($rest:tt)*
40    } => {
41        $crate::__define_tag! {
42            @lt_generics = {};
43            @generics = {};
44            @lt_generics_with_bounds = {};
45            @generics_with_bounds = {};
46            @attrs = { $($attr)* };
47            $vis tag $Name < $($rest)*
48        }
49    };
50    {
51        $(#$attr:tt)*
52        $vis:vis tag $Name:ident : $($rest:tt)*
53    } => {
54        $crate::__define_tag! {
55            @lt_generics = {};
56            @generics = {};
57            @lt_generics_with_bounds = {};
58            @generics_with_bounds = {};
59            @attrs = { $($attr)* };
60            $vis tag $Name<>: $($rest)*
61        }
62    };
63}
64
65#[doc(hidden)]
66#[macro_export]
67macro_rules! __define_tag {
68    // generics
69
70    // read a lifetime arg or type arg without bounds at the end of the arg list
71    {
72        @lt_generics = { $($lt_gen:tt)* };
73        @generics = { $($gen:tt)* };
74        @lt_generics_with_bounds = { $($lt_gen_bounds:tt)* };
75        @generics_with_bounds = { $($gen_bounds:tt)* };
76        @attrs = $attrs:tt;
77        $vis:vis tag $Name:ident<
78            $($lt:lifetime $(: $($lt_b:lifetime $(+)?)*)?)?
79            $($T:ident)?
80        $(,)? > $($rest:tt)*
81    } => {
82        $crate::__define_tag! {
83            @where = {};
84            @lt_generics = { $($lt_gen)* $($lt,)? };
85            @generics = { $($gen)* $($T,)? };
86            @lt_generics_with_bounds = { $($lt_gen_bounds)* $($lt $(: $($lt_b +)*)?,)? };
87            @generics_with_bounds = { $($gen_bounds)* $($T,)? };
88            @attrs = $attrs;
89            $vis tag $Name $($rest)*
90        }
91    };
92    // read a const param at the end of the arg list
93    {
94        @lt_generics = $lt_gen:tt;
95        @generics = { $($gen:tt)* };
96        @lt_generics_with_bounds = $lt_gen_bounds:tt;
97        @generics_with_bounds = { $($gen_bounds:tt)* };
98        @attrs = $attrs:tt;
99        $vis:vis tag $Name:ident<
100            const $T:ident : $T_b:ty
101        $(,)? > $($rest:tt)*
102    } => {
103        $crate::__define_tag! {
104            @where = {}
105            @lt_generics = $lt_gen;
106            @generics = { $($gen)* $($T,)? };
107            @lt_generics_with_bounds = $lt_gen_bounds;
108            @generics_with_bounds = { $($gen_bounds)* $(const $T: $T_b,)? };
109            @attrs = $attrs;
110            $vis tag $Name $($rest)*
111        }
112    };
113    // read a lifetime arg or type arg without bounds
114    {
115        @lt_generics = { $($lt_gen:tt)* };
116        @generics = { $($gen:tt)* };
117        @lt_generics_with_bounds = { $($lt_gen_bounds:tt)* };
118        @generics_with_bounds = { $($gen_bounds:tt)* };
119        @attrs = $attrs:tt;
120        $vis:vis tag $Name:ident<
121            $($lt:lifetime $(: $($lt_b:lifetime $(+)?)*)?)?
122            $($T:ident)?
123        , $($rest:tt)*
124    } => {
125        $crate::__define_tag! {
126            @lt_generics = { $($lt_gen)*  $($lt,)? };
127            @generics = { $($gen)* $($T,)? };
128            @lt_generics_with_bounds = { $($lt_gen_bounds)* $($lt $(: $($lt_b +)*)?,)? };
129            @generics_with_bounds = { $($gen_bounds)* $($T,)? };
130            @attrs = $attrs;
131            $vis tag $Name< $($rest)*
132        }
133    };
134    // read a const param
135    {
136        @lt_generics = $lt_gen:tt;
137        @generics = { $($gen:tt)* };
138        @lt_generics_with_bounds = $lt_gen_bounds:tt;
139        @generics_with_bounds = { $($gen_bounds:tt)* };
140        @attrs = $attrs:tt;
141        $vis:vis tag $Name:ident<
142            const $T:ident : $T_b:ty
143        , $($rest:tt)*
144    } => {
145        $crate::__define_tag! {
146            @lt_generics = $lt_gen;
147            @generics = { $($gen)* $T, };
148            @lt_generics_with_bounds = $lt_gen_bounds;
149            @generics_with_bounds = { $($gen_bounds)* $(const $T: $T_b,)? };
150            @attrs = $attrs;
151            $vis tag $Name< $($rest)*
152        }
153    };
154    // read a type arg with bounds
155    {
156        @lt_generics = $lt_gen:tt;
157        @generics = { $($gen:tt)* };
158        @lt_generics_with_bounds = $lt_gen_bounds:tt;
159        @generics_with_bounds = { $($gen_bounds:tt)* };
160        @attrs = $attrs:tt;
161        $vis:vis tag $Name:ident< $T:ident: $($rest:tt)*
162    } => {
163        $crate::__define_tag! {
164            @lt_generics = $lt_gen;
165            @generics = { $($gen)* $T, };
166            @lt_generics_with_bounds = $lt_gen_bounds;
167            @generics_with_bounds = { $($gen_bounds)* $T: };
168            @attrs = $attrs;
169            $vis tag $Name< : $($rest)*
170        }
171    };
172    // read a type arg bound end at end of arg list
173    {
174        @lt_generics = $lt_gen:tt;
175        @generics = $gen:tt;
176        @lt_generics_with_bounds = $lt_gen_bounds:tt;
177        @generics_with_bounds = { $($gen_bounds:tt)* };
178        @attrs = $attrs:tt;
179        $vis:vis tag $Name:ident< : $(,)? > $($rest:tt)*
180    } => {
181        $crate::__define_tag! {
182            @where = {};
183            @lt_generics = $lt_gen;
184            @generics = $gen;
185            @lt_generics_with_bounds = $lt_gen_bounds;
186            @generics_with_bounds = { $($gen_bounds)* , };
187            @attrs = $attrs;
188            $vis tag $Name $($rest)*
189        }
190    };
191    // read a type arg bound end
192    {
193        @lt_generics = $lt_gen:tt;
194        @generics = $gen:tt;
195        @lt_generics_with_bounds = $lt_gen_bounds:tt;
196        @generics_with_bounds = { $($gen_bounds:tt)* };
197        @attrs = $attrs:tt;
198        $vis:vis tag $Name:ident< : , $($rest:tt)*
199    } => {
200        $crate::__define_tag! {
201            @lt_generics = $lt_gen;
202            @generics = $gen;
203            @lt_generics_with_bounds = $lt_gen_bounds;
204            @generics_with_bounds = { $($gen_bounds)* , };
205            @attrs = $attrs;
206            $vis tag $Name< , $($rest)*
207        }
208    };
209    // read a type arg bound token
210    {
211        @lt_generics = $lt_gen:tt;
212        @generics = $gen:tt;
213        @lt_generics_with_bounds = $lt_gen_bounds:tt;
214        @generics_with_bounds = { $($gen_bounds:tt)* };
215        @attrs = $attrs:tt;
216        $vis:vis tag $Name:ident< : $bound:tt $($rest:tt)*
217    } => {
218        $crate::__define_tag! {
219            @lt_generics = $lt_gen;
220            @generics = $gen;
221            @lt_generics_with_bounds = $lt_gen_bounds;
222            @generics_with_bounds = { $($gen_bounds)* $bound };
223            @attrs = $attrs;
224            $vis tag $Name< : $($rest)*
225        }
226    };
227
228    // where
229
230    // end of where clause (if any)
231    {
232        @where = { $($where:tt)* };
233        @lt_generics = { $($lt_gen:lifetime,)* };
234        @generics = { $($gen:ident,)* };
235        @lt_generics_with_bounds = { $($lt_gen_bounds:tt)* };
236        @generics_with_bounds = { $($gen_bounds:tt)* };
237        @attrs = { $($attr:tt)* };
238        $vis:vis tag $Name:ident : for<$($lt:lifetime),* $(,)?> $T1:ty $(=> $T2:ty)? $(where)? ; $($rest:tt)*
239    } => {
240        $(#$attr)*
241        $vis struct $Name< $($lt_gen_bounds)* $($gen_bounds)* > where $($where)* {
242            _lt: ( $($crate::__m::PhantomData<& $lt_gen ()>,)* ),
243            _p: ( $($crate::__m::PhantomData<$gen>,)* ),
244            _infallible: $crate::__m::Infallible,
245        }
246
247        impl < $($lt_gen_bounds)* $($gen_bounds)* > $crate::ResourceTag for $Name<$($lt_gen,)* $($gen,)*>
248        where
249            $($lt_gen: 'static,)*
250            $($gen: 'static,)*
251            $($where)*
252        {
253            $crate::__define_tag! { @associated_types for<$($lt),*> $T1 $(=> $T2)? }
254        }
255
256        $crate::define_tag! { $($rest)* }
257    };
258
259    // read a where clause bound and comma
260    {
261        @where = { $($where:tt)* };
262        @lt_generics = $lt_gen:tt;
263        @generics = $gen:tt;
264        @lt_generics_with_bounds = $lt_gen_bounds:tt;
265        @generics_with_bounds = $gen_bounds:tt;
266        @attrs = $attrs:tt;
267        $vis:vis tag $Name:ident : for<$($lt:lifetime),* $(,)?> $T1:ty $(=> $T2:ty)?
268        where
269            $T:ty : $bound:path ,
270        $($rest:tt)*
271    } => {
272        $crate::__define_tag! {
273            @where = { $($where)* $T: $bound, };
274            @lt_generics = $lt_gen;
275            @generics = $gen;
276            @lt_generics_with_bounds = $lt_gen_bounds;
277            @generics_with_bounds = $gen_bounds;
278            @attrs = $attrs;
279            $vis tag $Name : for<$($lt),*> $T1 $(=> $T2)? where $($rest)*
280        }
281    };
282    // read a where clause token
283    {
284        @where = { $($where:tt)* };
285        @lt_generics = $lt_gen:tt;
286        @generics = $gen:tt;
287        @lt_generics_with_bounds = $lt_gen_bounds:tt;
288        @generics_with_bounds = $gen_bounds:tt;
289        @attrs = $attrs:tt;
290        $vis:vis tag $Name:ident : for<$($lt:lifetime),* $(,)?> $T1:ty $(=> $T2:ty)? where $where_token:tt
291        $($rest:tt)*
292    } => {
293        $crate::__define_tag! {
294            @where = { $($where)* $where_token };
295            @lt_generics = $lt_gen;
296            @generics = $gen;
297            @lt_generics_with_bounds = $lt_gen_bounds;
298            @generics_with_bounds = $gen_bounds;
299            @attrs = $attrs;
300            $vis tag $Name : for<$($lt),*> $T1 $(=> $T2)? where $($rest)*
301        }
302    };
303
304    // handle a missing for<> qualifier
305    {
306        @where = $where:tt;
307        @lt_generics = $lt_gen:tt;
308        @generics = $gen:tt;
309        @lt_generics_with_bounds = $lt_gen_bounds:tt;
310        @generics_with_bounds = $gen_bounds:tt;
311        @attrs = $attrs:tt;
312        $vis:vis tag $Name:ident : $T1:ty $(=> $T2:ty)?
313        ;
314        $($rest:tt)*
315    } => {
316        $crate::__define_tag! {
317            @where = $where;
318            @lt_generics = $lt_gen;
319            @generics = $gen;
320            @lt_generics_with_bounds = $lt_gen_bounds;
321            @generics_with_bounds = $gen_bounds;
322            @attrs = $attrs;
323            $vis tag $Name : for<> $T1 $(=> $T2)? ; $($rest)*
324        }
325    };
326    {
327        @where = $where:tt;
328        @lt_generics = $lt_gen:tt;
329        @generics = $gen:tt;
330        @lt_generics_with_bounds = $lt_gen_bounds:tt;
331        @generics_with_bounds = $gen_bounds:tt;
332        @attrs = $attrs:tt;
333        $vis:vis tag $Name:ident : $T1:ty $(=> $T2:ty)?
334        where
335        $($rest:tt)*
336    } => {
337        $crate::__define_tag! {
338            @where = $where;
339            @lt_generics = $lt_gen;
340            @generics = $gen;
341            @lt_generics_with_bounds = $lt_gen_bounds;
342            @generics_with_bounds = $gen_bounds;
343            @attrs = $attrs;
344            $vis tag $Name : for<> $T1 $(=> $T2)? where $($rest)*
345        }
346    };
347
348    { @associated_types for<$($lt:lifetime),*> $In:ty => $Out:ty } => {
349        type Arg = $crate::TypeFn![for<$($lt),*> $In];
350        type Out = $crate::TypeFn![for<$($lt),*> $Out];
351    };
352    { @associated_types for<$($lt:lifetime),*> $Out:ty } => {
353        type Arg = ();
354        type Out = $crate::TypeFn![for<$($lt),*> $Out];
355    };
356}