ctor_proc_macro/
lib.rs
1#![doc = include_str!("../README.md")]
2
3use std::iter::FromIterator;
4
5use proc_macro::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
6
7#[allow(missing_docs)]
8#[proc_macro_attribute]
9pub fn ctor(attribute: TokenStream, item: TokenStream) -> TokenStream {
10 generate("ctor", "ctor", attribute, item)
11}
12
13#[allow(unknown_lints, tail_expr_drop_order)]
20fn generate(
21 macro_type: &str,
22 macro_crate: &str,
23 attribute: TokenStream,
24 item: TokenStream,
25) -> TokenStream {
26 let mut inner = TokenStream::new();
27
28 let mut crate_path = None;
30 let mut tokens = attribute.clone().into_iter().peekable();
31
32 while let Some(token) = tokens.next() {
33 if let TokenTree::Ident(ident) = &token {
34 if ident.to_string() == "crate_path" {
35 #[allow(unknown_lints, tail_expr_drop_order)]
37 if let Some(TokenTree::Punct(punct)) = tokens.next() {
38 if punct.as_char() == '=' {
39 let mut path = TokenStream::new();
41 while let Some(token) = tokens.peek() {
42 match token {
43 TokenTree::Punct(p) if p.as_char() == ',' => {
44 tokens.next();
45 break;
46 }
47 _ => {
48 path.extend(std::iter::once(tokens.next().unwrap()));
49 }
50 }
51 }
52 crate_path = Some(path);
53 break;
54 }
55 }
56 }
57 }
58 }
59
60 if attribute.is_empty() {
61 inner.extend([
63 TokenTree::Punct(Punct::new('#', Spacing::Alone)),
64 TokenTree::Group(Group::new(
65 Delimiter::Bracket,
66 TokenStream::from_iter([TokenTree::Ident(Ident::new(
67 macro_type,
68 Span::call_site(),
69 ))]),
70 )),
71 ]);
72 } else {
73 inner.extend([
74 TokenTree::Punct(Punct::new('#', Spacing::Alone)),
75 TokenTree::Group(Group::new(
76 Delimiter::Bracket,
77 TokenStream::from_iter([
78 TokenTree::Ident(Ident::new(macro_type, Span::call_site())),
79 TokenTree::Group(Group::new(Delimiter::Parenthesis, attribute)),
80 ]),
81 )),
82 ]);
83 }
84
85 inner.extend(item);
86
87 let mut invoke = crate_path.unwrap_or_else(|| {
88 TokenStream::from_iter([
89 TokenTree::Punct(Punct::new(':', Spacing::Joint)),
90 TokenTree::Punct(Punct::new(':', Spacing::Alone)),
91 TokenTree::Ident(Ident::new(macro_crate, Span::call_site())),
92 ])
93 });
94
95 invoke.extend([
96 TokenTree::Punct(Punct::new(':', Spacing::Joint)),
97 TokenTree::Punct(Punct::new(':', Spacing::Alone)),
98 TokenTree::Ident(Ident::new("__support", Span::call_site())),
99 TokenTree::Punct(Punct::new(':', Spacing::Joint)),
100 TokenTree::Punct(Punct::new(':', Spacing::Alone)),
101 TokenTree::Ident(Ident::new(
102 &format!("{}_parse", macro_type),
103 Span::call_site(),
104 )),
105 TokenTree::Punct(Punct::new('!', Spacing::Alone)),
106 TokenTree::Group(Group::new(Delimiter::Parenthesis, inner)),
107 TokenTree::Punct(Punct::new(';', Spacing::Alone)),
108 ]);
109
110 invoke
111}