1#![doc = include_str!("README.md")]
2
3#[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 ) => {
197 $crate::new_struct! {
198 ( $($cb)* ),
199 [ $($strct)* ],
200 }
201 };
202 (
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 (
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 (
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 (
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#[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