1use std::vec::Vec;
30use std::string::String;
31use proc_macro::{self, TokenStream};
32use quote::quote;
33use syn::parse_macro_input;
34use syn::DeriveInput;
35use syn::FieldsNamed;
36use proc_macro2::Span;
37use syn::Fields;
38use syn::Data;
39use syn::Type;
40use syn::PathArguments;
41use syn::GenericArgument;
42use syn::Ident;
43use syn::Visibility;
44
45fn expand_type_name(t: &syn::Type) -> String
46{
47 let mut s = String::new();
48
49 match t
50 {
51 Type::Path(p) =>
52 {
53 for v in &p.path.segments
54 {
55 s.push_str(&v.ident.to_string());
56 s.push_str("::");
57 }
58 return String::from(&s[0..s.len() - 2]);
59 }
60 _ => panic!("Invalid generic type name for ComponentPool")
61 }
62}
63
64#[proc_macro_derive(ComponentManager)]
65pub fn component_manager(input: TokenStream) -> TokenStream
66{
67 let DeriveInput { ident, data, .. } = parse_macro_input!(input);
68 let mut v = Vec::new();
69
70 match data
71 {
72 Data::Struct(s) => match s.fields
73 {
74 Fields::Named(FieldsNamed { named, .. }) =>
75 {
76 for f in &named
77 {
78 match &f.ty
79 {
80 Type::Path(p) =>
81 {
82 let last = &p.path.segments.last().unwrap();
83 if let PathArguments::AngleBracketed(b) = &last.arguments
84 {
85 if let Some(v1) = b.args.first()
86 {
87 if let GenericArgument::Type(t) = v1
88 {
89 let name = expand_type_name(&t);
90 if let Some(useless) = &f.ident
91 {
92 v.push((useless.clone(), name));
93 }
94 else
95 {
96 panic!("How is it possible that you get no identifier???!!!")
97 }
98 }
99 else
100 {
101 panic!("Could not identify type of component for field {:?}", f.ident);
102 }
103 }
104 else
105 {
106 panic!("Could not identify type of component for field {:?}", f.ident);
107 }
108 }
109 },
110 _ => panic!("Could not identify type of component for field {:?}", f.ident),
111 }
112 }
113 },
114 _ => panic!("Your component list must not be empty")
115 },
116 _ => panic!("ComponentManager cannot be implemented on non-structs")
117 };
118 let mut impl_base_tokens = Vec::new();
119 for (field_name, _) in &v
120 {
121 impl_base_tokens.push(
122 quote!
123 {
124 #field_name: ComponentPool::new()
125 }
126 );
127 };
128 let mut impls_tokens = Vec::new();
129 for (field_name, component_type) in &v
130 {
131 let mut s = component_type.clone();
132 s.push_str("Manager");
133 let new_ident = syn::parse_str::<Type>(&s).unwrap();
134 let new_ident1 = syn::parse_str::<Type>(&component_type).unwrap();
135 let mgr_impl_tokens = quote!
136 {
137 impl #new_ident for #ident
138 {
139 fn get(&mut self, id: usize) -> &mut #new_ident1
140 {
141 return self.#field_name.get(id);
142 }
143
144 fn get_pool(&mut self) -> &mut ComponentPool<#new_ident1>
145 {
146 return &mut self.#field_name;
147 }
148 }
149 };
150 impls_tokens.push(mgr_impl_tokens);
151 }
152 let output = quote!
153 {
154 impl #ident
155 {
156 pub fn new() -> #ident
157 {
158 return #ident
159 {
160 #(#impl_base_tokens,)*
161 };
162 }
163 }
164
165 #(#impls_tokens)*
166 };
167 return output.into();
168}
169
170#[proc_macro_derive(Component)]
171pub fn component(input: TokenStream) -> TokenStream
172{
173 let DeriveInput { ident, vis, .. } = parse_macro_input!(input);
174
175 let mut s = ident.to_string();
176 s.push_str("Manager");
177 let new_ident = Ident::new(&s, Span::call_site());
178 let vis = match vis
179 {
180 Visibility::Public(_) => Some(Ident::new("pub", Span::call_site())),
181 _ => None
182 };
183 let output = quote!
184 {
185 #vis trait #new_ident
186 {
187 fn get(&mut self, id: usize) -> &mut #ident;
188 fn get_pool(&mut self) -> &mut ComponentPool<#ident>;
189 }
190 };
191 return output.into();
192}