1extern crate proc_macro;
16
17use proc_macro2::{TokenTree, TokenStream, Delimiter, Group};
18
19#[derive(Debug, Clone, Default)]
20struct TypeStruct {
21 pub signature: Vec<TokenTree>,
22 pub group: Vec<TokenTree>,
23}
24
25#[proc_macro]
26pub fn general_structs(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
27 let ast = TokenStream::from(item);
28
29 let mut metadata = Vec::<TokenTree>::new();
30 let mut types = Vec::<TypeStruct>::new();
31 let mut general_body = TokenTree::from(Group::new(Delimiter::Brace, TokenStream::new()));
32
33 let mut mut_types = Vec::<TypeStruct>::new();
34
35 let mut bracket_stack = 0;
36 let mut is_struct = false;
37 let mut is_mut_struct = false;
38 let mut is_body_general_group = false;
39
40 let mut current_type_struct = TypeStruct::default();
41 for token in ast.into_iter() {
42 if let TokenTree::Ident(ident) = &token {
43 if ident.to_string() == "struct" {
44 is_struct = true;
45 continue;
46 }
47 }
48
49 if is_struct {
50 if let TokenTree::Punct(punct) = &token {
51 if punct.as_char() == '<' {
52 bracket_stack += 1;
53 } else if punct.as_char() == '>'{
54 bracket_stack -= 1;
55 } else if punct.as_char() == '+' && bracket_stack == 0 {
56 types.push(current_type_struct);
57 current_type_struct = TypeStruct::default();
58 continue;
59 }
60 } else if let TokenTree::Group(group) = &token {
61 if let Delimiter::Brace = group.delimiter() {
62 types.push(current_type_struct);
63 current_type_struct = TypeStruct::default();
64 is_struct = false;
65 is_body_general_group = true;
66 }
67 }
68
69 if is_struct {
70 current_type_struct.signature.push(token.clone());
71 } else {
72 current_type_struct = TypeStruct::default();
73 }
74 }
75
76 if is_body_general_group {
77 if let TokenTree::Group(group) = &token {
78 general_body = TokenTree::Group(group.clone());
79 is_body_general_group = false;
80 continue;
81 }
82 }
83
84 if let TokenTree::Ident(_) = &token {
85 if !is_struct && !is_body_general_group {
86 is_mut_struct = true;
87 }
88 }
89
90 if is_mut_struct {
91 if let TokenTree::Punct(punct) = &token {
92 if punct.as_char() == '<' {
93 bracket_stack += 1;
94 } else if punct.as_char() == '>'{
95 bracket_stack -= 1;
96 } else if punct.as_char() == '+' && bracket_stack == 0 {
97 types.push(current_type_struct);
98 current_type_struct = TypeStruct::default();
99 continue;
100 }
101 } else if let TokenTree::Group(group) = &token {
102 if let Delimiter::Brace = group.delimiter() {
103 current_type_struct.group.push(TokenTree::Group(group.clone()));
104 mut_types.push(current_type_struct);
105
106 current_type_struct = TypeStruct::default();
107 continue;
108 }
109 }
110
111 current_type_struct.signature.push(token.clone());
112 }
113
114 if !is_struct && !is_mut_struct && !is_body_general_group {
115 metadata.push(token.clone());
116 continue;
117 }
118 }
119
120 let mut res = String::new();
121
122 for type_struct in types.iter() {
123 res.push_str(format!("{} ", TokenStream::from_iter(metadata.clone())).as_str());
124
125 let type_name = TokenStream::from_iter(type_struct.signature.clone()).to_string();
126 res.push_str(format!("struct {} {{", type_name).as_str());
127
128 if let TokenTree::Group(general_group) = &general_body {
129 res.push_str(format!("{}", general_group.stream().to_string()).as_str());
130
131 for type_mut_struct in mut_types.iter() {
132 let mut_type_name = TokenStream::from_iter(type_mut_struct.signature.clone()).to_string();
133 if mut_type_name == type_name {
134 if let TokenTree::Group(add_group) = &type_mut_struct.group[0] {
135 res.push_str(format!("{}", add_group.stream().to_string()).as_str());
136 }
137 }
138 }
139 }
140
141 res.push_str(format!("}} ").as_str());
142 }
143
144 res.as_str().parse().unwrap()
145}