dnspod_lib/macros/
mod.rs

1#![doc = include_str!("README.md")]
2
3/// 混编 `#[..]` 与 `@[..]` 整流成 `#[..]` 在前, `@[..]` 在后
4/// 
5#[doc = include_str!("README.md")]
6#[macro_export]
7macro_rules! custom_meta_struct {
8    ($($tt: tt)*) => {
9        $crate::step1! {
10            $($tt)*
11        }
12    }
13}
14
15#[macro_export]
16macro_rules! step1 {
17    () => {};
18    (
19        #[$meta: meta]
20        $($tail: tt)*
21    ) => {
22        $crate::step1! {
23            [ #[$meta] ],
24            $($tail)*
25        }
26    };
27    (
28        @[$($my_meta: tt)*]
29        $($tail: tt)*
30    ) => {
31        $crate::step1! {
32            [ @[$($my_meta)*] ],
33            $($tail)*
34        }
35    };
36
37    (
38        [$($cus_meta: tt)*],
39        @[$($my_meta: tt)*]
40        $($tail: tt)*
41    ) => {
42        $crate::step1! {
43            [ $($cus_meta)* @[$($my_meta)*] ],
44            $($tail)*
45        }
46    };
47    (
48        [$($cus_meta: tt)*],
49        #[$meta: meta]
50        $($tail: tt)*
51    ) => {
52        $crate::step1! {
53            [ $($cus_meta)* #[$meta] ],
54            $($tail)*
55        }
56    };
57    (
58        [$($cus_meta: tt)*],
59        ,
60        $($tail: tt)*
61    ) => {
62        $crate::step2! {
63            (, $($cus_meta)*),
64            $($tail)*
65        }
66    };
67    (
68        [$($cus_meta: tt)*],
69        $($tail: tt)*
70    ) => {
71        $crate::step2! {
72            (, $($cus_meta)*),
73            $($tail)*
74        }
75    };
76
77    (
78        $path: path
79    ) => {
80        $crate::step2! {
81            ($path, ),
82        }
83    };
84
85    (
86        $path: path,
87        $($tail: tt)*
88    ) => {
89        $crate::step2! {
90            ($path, ),
91            $($tail)*
92        }
93    };
94
95    (
96        ($($header: tt)*)
97        ,
98        $($tail: tt)*
99    ) => {
100        $crate::step2! {
101            ($($header)*),
102            $($tail)*
103        }
104    };
105
106    (
107        ($($header: tt)*)
108        $($tail: tt)*
109    ) => {
110        $crate::step2! {
111            ($($header)*),
112            $($tail)*
113        }
114    };
115}
116
117#[macro_export]
118macro_rules! step2 {
119    () => {};
120
121    (
122        $(#[$meta: meta])*,
123        $($tt: tt)*
124    ) => {
125        $crate::step2! {
126            (, $(#[$meta])* ),
127            $($tt)*
128        }
129    };
130
131    (
132        (#[$meta: meta] $($tt: tt)*),
133        $($tail: tt)*
134    ) => {
135        $crate::new_struct! {
136            ( , #[$meta] $($tt)* ),
137            [],
138            $($tail)*
139        }
140    };
141    (
142        (@[$($my_meta: tt)*] $($tt: tt)*),
143        $($tail: tt)*
144    ) => {
145        $crate::new_struct! {
146            ( , @[$($my_meta)*] $($tt)* ),
147            [],
148            $($tail)*
149        }
150    };
151
152    (
153        ($($cb: path $(,)?)? ),
154        $($tail: tt)*
155    ) => {
156        $crate::new_struct! {
157            ( $($cb)?, ),
158            [],
159            $($tail)*
160        }
161    };
162    (
163        ($($cb: path)? , #[$meta: meta] $($common_meta: tt)*),
164        $($tail: tt)*
165    ) => {
166        $crate::new_struct! {
167            ( $($cb)?, #[$meta] $($common_meta)* ),
168            [],
169            $($tail)*
170        }
171    };
172    (
173        ($($cb: path)? , @[$($cus_meta: tt)*] $($common_meta: tt)*),
174        $($tail: tt)*
175    ) => {
176        $crate::new_struct! {
177            ( $($cb)?, @[$($cus_meta)*] $($common_meta)* ),
178            [],
179            $($tail)*
180        }
181    };
182
183    (
184        ($($tt: tt)*) $(,)?
185    ) => {};
186}
187
188#[macro_export]
189macro_rules! custom_meta_struct_impl {
190    (
191        ($($cb: tt)*),
192        [$($meta: tt)*],
193        [$($my_meta: tt)*],
194        [$($strct: tt)*],
195        // struct 部分不存在的情况
196    ) => {
197        $crate::new_struct! {
198            ( $($cb)* ),
199            [ $($strct)* ],
200        }
201    };
202    // 拆分组装车间 1
203    (
204        ($($cb: tt)*),
205        [$($meta: tt)*],
206        [$($my_meta: tt)*],
207        [$($strct: tt)*],
208        # $tt: tt
209        $($tail: tt)*
210    ) => {
211        $crate::custom_meta_struct_impl! {
212            ($($cb)*),
213            [$($meta)* # $tt], 
214            [$($my_meta)*], 
215            [$($strct)*],
216            $($tail)*
217        }
218    };
219    // 拆分组装车间 2
220    (
221        ($($cb: tt)*),
222        [$($meta: tt)*],
223        [$($my_meta: tt)*],
224        [$($strct: tt)*],
225        @ $tt: tt
226        $($tail: tt)*
227    ) => {
228        $crate::custom_meta_struct_impl! {
229            ($($cb)*),
230            [$($meta)*], 
231            [$($my_meta)* @ $tt], 
232            [$($strct)*],
233            $($tail)*
234        }
235    };
236
237    // 组装 struct
238    (
239        ($($cb: tt)*),
240        [$($meta: tt)*],
241        [$($my_meta: tt)*],
242        [$($strct: tt)*],
243        $vis: vis struct $name: ident $body: tt
244        $($tail: tt)*
245    ) => {
246        $crate::new_struct! {
247            ($($cb)*),
248            [
249                $($strct)*
250                $($meta)*
251                $($my_meta)*
252                $vis struct $name $body
253            ],
254            $($tail)*
255        }
256    };
257
258    // 组装 enum
259    (
260        ($($cb: tt)*),
261        [$($meta: tt)*],
262        [$($my_meta: tt)*],
263        [$($strct: tt)*],
264        $vis: vis enum $name: ident $body: tt
265        $($tail: tt)*
266    ) => {
267        $crate::new_struct! {
268            ($($cb)*),
269            [
270                $($strct)*
271                $($meta)*
272                $($my_meta)*
273                $vis enum $name $body
274            ],
275            $($tail)*
276        }
277    };
278}
279
280#[macro_export]
281macro_rules! new_struct {
282    (
283        ($($cb: tt)*),
284        [$($strct: tt)*],
285    ) => {
286        $crate::finally! {
287            ($($cb)*),
288            [$($strct)*],
289        }
290    };
291
292    (
293        ($($cb: path)?, $($common_meta: tt)*),
294        [$($strct: tt)*],
295        $tt: tt
296        $($tail: tt)*
297    ) => {
298        $crate::custom_meta_struct_impl! {
299            ($($cb)?, $($common_meta)*),
300            [],
301            [],
302            [$($strct)*],
303            $($common_meta)*
304            $tt
305            $($tail)*
306        }
307    };
308}
309
310#[macro_export]
311macro_rules! finally {
312    (
313        ($cb: path, $($common_meta: tt)*),
314        [$($strct: tt)*] $(,)?
315    ) => {
316        $cb! {
317            $($strct)*
318        }
319    };
320
321    (
322        (, $($common_meta: tt)*),
323        [$($strct: tt)*] $(,)?
324    ) => {
325        $($strct)*
326    };
327}
328
329// ---------------------------------------------------------------- //
330
331
332#[cfg(test)]
333mod tests {
334    custom_meta_struct! {}
335    custom_meta_struct! {
336        ()
337    }
338    custom_meta_struct! {
339        (),
340    }
341
342    macro_rules! fuck {
343        ($($tt: tt)*) => {};
344    }
345    custom_meta_struct! {
346        fuck
347    }
348    custom_meta_struct! {
349        fuck,
350    }
351
352    custom_meta_struct! {
353        #[derive(Debug)]
354        ,
355    }
356
357    custom_meta_struct! {
358        #[derive(Debug)]
359        #[derive(Clone)]
360        ,
361    }
362
363    custom_meta_struct! {
364        #[derive(Debug)]
365        #[derive(Clone)]
366        ,
367
368        struct Hello;
369        struct World;
370    }
371
372    custom_meta_struct! {
373        (#[derive(Debug)]),
374    }
375    custom_meta_struct! {
376        (@[derive(Debug)])
377    }
378
379    custom_meta_struct! {
380        (
381            #[derive(Clone)]
382            #[derive(Debug)]
383        ),
384        struct TestA;
385    }
386
387    macro_rules! define_structs {
388        (
389            $(
390                $(#[$meta: meta])*
391                $(@[$($my_meta: tt)*])*
392                $vis: vis struct $name: ident $body: tt
393            )*
394        ) => {};
395    }
396
397    custom_meta_struct! {
398        define_structs,
399        struct A;
400        struct B;
401    }
402    custom_meta_struct! {
403        (
404            define_structs, 
405            #[derive(Debug, Clone)]
406            @[url = "https://hangj.cnblogs.com"]
407        ),
408
409        struct A;
410        struct B{}
411        @[fuck]
412        struct C;
413    }
414    custom_meta_struct! {
415        define_structs,
416
417        #[derive(Debug)]
418        struct A;
419    }
420    custom_meta_struct! {
421        define_structs,
422        struct A;
423        struct B{}
424    }
425    custom_meta_struct! {
426        define_structs,
427        @[derive(Debug)]
428        struct A;
429        struct B{}
430    }
431    custom_meta_struct! {
432        define_structs,
433
434        @[derive(Debug)]
435        #[derive(Debug)]
436        struct A;
437        struct B{}
438
439        @[公众号 = RustHub]
440        #[derive(Debug)]
441        @[公众号 = RustHub]
442        struct C {
443            v: String,
444        }
445    }
446}
447
448
449#[cfg(test)]
450mod test2 {
451    macro_rules! structs_to_string {
452        (
453            $(
454                $(#[$meta: meta])*
455                $(@[$($my_meta: tt)*])*
456                $vis: vis struct $name: ident $body: tt
457            )*
458        ) => {
459            stringify!(
460                $(
461                    $(#[$meta])*
462                    $(@[$($my_meta)*])*
463                    $vis struct $name $body
464                )*
465            )
466            .split_whitespace()
467            .collect::<Vec<_>>()
468            .join(" ")
469        };
470    }
471
472    #[test]
473    fn test() {
474        {
475            crate::custom_meta_struct! {
476                #[derive(Debug)]
477                ,
478                #[derive(Clone)]
479                struct A;
480            }
481            assert_eq!(format!("{:?}", A.clone()), "A");
482        }
483
484        {
485            crate::custom_meta_struct! {
486                #[derive(Debug)]
487                ,
488                #[derive(Clone)]
489                struct A;
490                struct B;
491            }
492            assert_eq!(format!("{:?}", A.clone()), "A");
493            assert_eq!(format!("{:?}", B), "B");
494        }
495
496        {
497            crate::custom_meta_struct! {
498                (
499                    #[derive(Debug)]
500                    #[derive(Clone)]
501                ),
502                struct A;
503                struct B;
504            }
505
506            assert_eq!(format!("{:?}", A.clone()), "A");
507            assert_eq!(format!("{:?}", B.clone()), "B");
508        }
509
510        assert_eq!(
511            {
512                crate::custom_meta_struct! {
513                    structs_to_string,
514                }
515            },
516            ""
517        );
518        assert_eq!(
519            {
520                crate::custom_meta_struct! {
521                    (structs_to_string),
522                    struct A;
523                }
524            },
525            "struct A ;"
526        );
527        assert_eq!(
528            {
529                crate::custom_meta_struct! {
530                    (structs_to_string, ),
531                    struct A;
532                    #[derive(Debug)]
533                    struct B;
534                }
535            },
536            "struct A ; #[derive(Debug)] struct B ;"
537        );
538
539        assert_eq!(
540            {
541                crate::custom_meta_struct! {
542                    (
543                        structs_to_string,
544                        #[derive(Debug)]
545                    ),
546                    struct A;
547                    struct B;
548                }
549            },
550            "#[derive(Debug)] struct A ; #[derive(Debug)] struct B ;"
551        );
552
553        assert_eq!(
554            {
555                crate::custom_meta_struct! {
556                    (
557                        structs_to_string,
558                        #[derive(Debug)]
559                        @[hello world]
560                        #[derive(Hash)]
561                    ),
562                    struct A;
563                    #[derive(Clone)]
564                    struct B;
565                }
566            },
567            "#[derive(Debug)] #[derive(Hash)] @ [hello world] struct A ; #[derive(Debug)] #[derive(Hash)] #[derive(Clone)] @ [hello world] struct B ;"
568        );
569    }
570}
571