enum_methods/
getters.rs

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}