1use util::*;
2use syn::*;
3use quote;
4
5pub(crate) fn impl_enum_as_getters(ast: &DeriveInput) -> quote::Tokens {
6 let ref name = ast.ident;
7
8 let variants =
9 if let Body::Enum(ref e) = ast.body { e }
10 else { unreachable!() };
11
12 macro_rules! getter_filter {
13 () => {
14 variants.iter()
15 .filter(|v| if let VariantData::Tuple(_) = v.data { true } else { false })
16 };
17 }
18
19 let variant_names = getter_filter!()
20 .filter(|v| v.data.fields().len() == 1)
21 .map(|v| v.ident.clone())
22 .collect::<Vec<Ident>>();
23
24 let function_names = getter_filter!()
25 .filter(|v| v.data.fields().len() == 1)
26 .map(|v| format!("as_{}", to_snake_case(&v.ident)).into())
27 .collect::<Vec<Ident>>();
28
29 let function_name_strs = getter_filter!()
30 .filter(|v| v.data.fields().len() == 1)
31 .map(|v| v.ident.to_string().to_lowercase())
32 .collect::<Vec<String>>();
33
34 let variant_types = getter_filter!()
35 .filter(|v| v.data.fields().len() == 1)
36 .map(|v| &v.data.fields()[0].ty)
37 .map(|ty| Ty::Rptr(None, Box::new(MutTy { ty: ty.clone(), mutability: Mutability::Immutable })))
38 .collect::<Vec<Ty>>();
39
40 let getter_names = vec!(name.clone(); variant_types.len());
41
42 let mut tokens = quote! {
43 #[allow(dead_code)]
44 impl #name {
45 #(pub fn #function_names(&self) -> #variant_types {
46 if let &#getter_names::#variant_names(ref v) = self {
47 v
48 }
49 else {
50 panic!(concat!("called as_", #function_name_strs, "() on {:?}"), self);
51 }
52 }
53 )*
54 }
55 };
56
57 let variant_names = getter_filter!()
58 .filter(|v| v.data.fields().len() > 1)
59 .map(|v| v.ident.clone())
60 .collect::<Vec<Ident>>();
61
62 let function_names = getter_filter!()
63 .filter(|v| v.data.fields().len() > 1)
64 .map(|v| format!("as_{}", to_snake_case(&v.ident)).into())
65 .collect::<Vec<Ident>>();
66
67 let function_name_strs = getter_filter!()
68 .filter(|v| v.data.fields().len() > 1)
69 .map(|v| v.ident.to_string().to_lowercase())
70 .collect::<Vec<String>>();
71
72 let variant_types = getter_filter!()
73 .filter(|v| v.data.fields().len() > 1)
74 .map(|v| Ty::Tup(v.data.fields().iter().map(|field| Ty::Rptr(None, Box::new(MutTy { ty: field.ty.clone(), mutability: Mutability::Immutable }))).collect::<Vec<Ty>>()))
75 .collect::<Vec<Ty>>();
76
77 let getter_names_multiple = vec!(name.clone(); variant_types.len());
78
79 let tuple_args = getter_filter!()
80 .filter(|v| v.data.fields().len() > 1)
81 .map(|v| UniqueIdentifierIterator::new().take(v.data.fields().len()))
82 .collect::<Vec<_>>();
83
84 let tuple_args2 = getter_filter!()
85 .filter(|v| v.data.fields().len() > 1)
86 .map(|v| UniqueIdentifierIterator::new().take(v.data.fields().len()))
87 .collect::<Vec<_>>();
88
89 tokens.append(quote! {
90 #[allow(dead_code)]
91 impl #name {
92 #(pub fn #function_names(&self) -> #variant_types {
93 if let &#getter_names_multiple::#variant_names(#(ref #tuple_args),*) = self {
94 (#(#tuple_args2), *)
95 }
96 else {
97 panic!(concat!("called as_", #function_name_strs, "() on {:?}"), self);
98 }
99 }
100 )*
101 }
102 });
103
104 tokens
105}
106
107pub(crate) fn impl_enum_into_getters(ast: &DeriveInput) -> quote::Tokens {
108 let ref name = ast.ident;
109
110 let variants =
111 if let Body::Enum(ref e) = ast.body { e }
112 else { unreachable!() };
113
114 macro_rules! getter_filter {
115 () => {
116 variants.iter()
117 .filter(|v| if let VariantData::Tuple(_) = v.data { true } else { false })
118 };
119 }
120
121 let variant_names = getter_filter!()
122 .filter(|v| v.data.fields().len() == 1)
123 .map(|v| v.ident.clone())
124 .collect::<Vec<Ident>>();
125
126 let function_names = getter_filter!()
127 .filter(|v| v.data.fields().len() == 1)
128 .map(|v| format!("into_{}", to_snake_case(&v.ident)).into())
129 .collect::<Vec<Ident>>();
130
131 let function_name_strs = getter_filter!()
132 .filter(|v| v.data.fields().len() == 1)
133 .map(|v| v.ident.to_string().to_lowercase())
134 .collect::<Vec<String>>();
135
136 let variant_types = getter_filter!()
137 .filter(|v| v.data.fields().len() == 1)
138 .map(|v| v.data.fields()[0].ty.clone())
139 .collect::<Vec<Ty>>();
140
141 let getter_names = vec!(name.clone(); variant_types.len());
142
143 let mut tokens = quote! {
144 #[allow(dead_code)]
145 impl #name {
146 #(pub fn #function_names(self) -> #variant_types {
147 if let #getter_names::#variant_names(v) = self {
148 v
149 }
150 else {
151 panic!(concat!("called into_", #function_name_strs, "() on {:?}"), self);
152 }
153 }
154 )*
155 }
156 };
157
158 let variant_names = getter_filter!()
159 .filter(|v| v.data.fields().len() > 1)
160 .map(|v| v.ident.clone())
161 .collect::<Vec<Ident>>();
162
163 let function_names = getter_filter!()
164 .filter(|v| v.data.fields().len() > 1)
165 .map(|v| format!("into_{}", to_snake_case(&v.ident)).into())
166 .collect::<Vec<Ident>>();
167
168 let function_name_strs = getter_filter!()
169 .filter(|v| v.data.fields().len() > 1)
170 .map(|v| v.ident.to_string().to_lowercase())
171 .collect::<Vec<String>>();
172
173 let variant_types = getter_filter!()
174 .filter(|v| v.data.fields().len() > 1)
175 .map(|v| Ty::Tup(v.data.fields().iter().map(|field| field.ty.clone()).collect::<Vec<Ty>>()))
176 .collect::<Vec<Ty>>();
177
178 let getter_names = vec!(name.clone(); variant_types.len());
179
180 let tuple_args = getter_filter!()
181 .filter(|v| v.data.fields().len() > 1)
182 .map(|v| UniqueIdentifierIterator::new().take(v.data.fields().len()))
183 .collect::<Vec<_>>();
184
185 let tuple_args2 = getter_filter!()
186 .filter(|v| v.data.fields().len() > 1)
187 .map(|v| UniqueIdentifierIterator::new().take(v.data.fields().len()))
188 .collect::<Vec<_>>();
189
190 tokens.append(quote! {
191 #[allow(dead_code)]
192 impl #name {
193 #(pub fn #function_names(self) -> #variant_types {
194 if let #getter_names::#variant_names(#(#tuple_args),*) = self {
195 (#(#tuple_args2), *)
196 }
197 else {
198 panic!(concat!("called into_", #function_name_strs, "() on {:?}"), self);
199 }
200 }
201 )*
202 }
203 });
204
205 tokens
206}
207
208pub(crate) fn impl_enum_to_getters(ast: &DeriveInput) -> quote::Tokens {
209 let ref name = ast.ident;
210
211 let variants =
212 if let Body::Enum(ref e) = ast.body { e }
213 else { unreachable!() };
214
215 macro_rules! getter_filter {
216 () => {
217 variants.iter()
218 .filter(|v| if let VariantData::Tuple(_) = v.data { true } else { false })
219 };
220 }
221
222 let variant_names = getter_filter!()
223 .filter(|v| v.data.fields().len() == 1)
224 .map(|v| v.ident.clone())
225 .collect::<Vec<Ident>>();
226
227 let function_names = getter_filter!()
228 .filter(|v| v.data.fields().len() == 1)
229 .map(|v| format!("to_{}", to_snake_case(&v.ident)).into())
230 .collect::<Vec<Ident>>();
231
232 let function_name_strs = getter_filter!()
233 .filter(|v| v.data.fields().len() == 1)
234 .map(|v| v.ident.to_string().to_lowercase())
235 .collect::<Vec<String>>();
236
237 let variant_types = getter_filter!()
238 .filter(|v| v.data.fields().len() == 1)
239 .map(|v| v.data.fields()[0].ty.clone())
240 .collect::<Vec<Ty>>();
241
242 let getter_names = vec!(name.clone(); variant_types.len());
243
244 let mut tokens = quote! {
245 #[allow(dead_code)]
246 impl #name {
247 #(pub fn #function_names(&self) -> #variant_types {
248 if let &#getter_names::#variant_names(ref v) = self {
249 v.clone()
250 }
251 else {
252 panic!(concat!("called to_", #function_name_strs, "() on {:?}"), self);
253 }
254 }
255 )*
256 }
257 };
258
259 let variant_names = getter_filter!()
260 .filter(|v| v.data.fields().len() > 1)
261 .map(|v| v.ident.clone())
262 .collect::<Vec<Ident>>();
263
264 let function_names = getter_filter!()
265 .filter(|v| v.data.fields().len() > 1)
266 .map(|v| format!("to_{}", to_snake_case(&v.ident)).into())
267 .collect::<Vec<Ident>>();
268
269 let function_name_strs = getter_filter!()
270 .filter(|v| v.data.fields().len() > 1)
271 .map(|v| v.ident.to_string().to_lowercase())
272 .collect::<Vec<String>>();
273
274 let variant_types = getter_filter!()
275 .filter(|v| v.data.fields().len() > 1)
276 .map(|v| Ty::Tup(v.data.fields().iter().map(|field| field.ty.clone()).collect::<Vec<Ty>>()))
277 .collect::<Vec<Ty>>();
278
279 let getter_names = vec!(name.clone(); variant_types.len());
280
281 let tuple_args = getter_filter!()
282 .filter(|v| v.data.fields().len() > 1)
283 .map(|v| UniqueIdentifierIterator::new().take(v.data.fields().len()))
284 .collect::<Vec<_>>();
285
286 let tuple_args2 = getter_filter!()
287 .filter(|v| v.data.fields().len() > 1)
288 .map(|v| UniqueIdentifierIterator::new().take(v.data.fields().len()))
289 .collect::<Vec<_>>();
290
291 tokens.append(quote! {
292 #[allow(dead_code)]
293 impl #name {
294 #(pub fn #function_names(&self) -> #variant_types {
295 if let &#getter_names::#variant_names(#(ref #tuple_args),*) = self {
296 (#(#tuple_args2.clone()), *)
297 }
298 else {
299 panic!(concat!("called to_", #function_name_strs, "() on {:?}"), self);
300 }
301 }
302 )*
303 }
304 });
305
306 tokens
307}