1 | #![cfg_attr (not(feature = "default" ), allow(dead_code), allow(unused_mut))] |
2 | |
3 | use proc_macro2::{Span, TokenStream}; |
4 | use quote::{quote, ToTokens}; |
5 | use syn::{ |
6 | parse_quote, punctuated::Punctuated, spanned::Spanned, Attribute, Data, |
7 | DeriveInput, Error, Field, Fields, FieldsNamed, FieldsUnnamed, GenericParam, |
8 | Generics, Ident, ImplGenerics, Index, Meta, NestedMeta, Result, Token, Type, |
9 | TypeGenerics, TypeParamBound, Variant, WhereClause, |
10 | }; |
11 | |
12 | #[derive (Clone, Copy, Default)] |
13 | pub struct DeterministicState; |
14 | |
15 | impl std::hash::BuildHasher for DeterministicState { |
16 | type Hasher = std::collections::hash_map::DefaultHasher; |
17 | |
18 | fn build_hasher(&self) -> Self::Hasher { |
19 | Self::Hasher::default() |
20 | } |
21 | } |
22 | |
23 | pub type HashMap<K, V> = std::collections::HashMap<K, V, DeterministicState>; |
24 | pub type HashSet<K> = std::collections::HashSet<K, DeterministicState>; |
25 | |
26 | #[derive (Clone, Copy, Debug, Eq, PartialEq, Hash)] |
27 | pub enum RefType { |
28 | No, |
29 | Ref, |
30 | Mut, |
31 | } |
32 | |
33 | impl RefType { |
34 | pub fn lifetime(self) -> TokenStream { |
35 | match self { |
36 | RefType::No => quote!(), |
37 | _ => quote!('__deriveMoreLifetime), |
38 | } |
39 | } |
40 | |
41 | pub fn reference(self) -> TokenStream { |
42 | match self { |
43 | RefType::No => quote!(), |
44 | RefType::Ref => quote!(&), |
45 | RefType::Mut => quote!(&mut), |
46 | } |
47 | } |
48 | |
49 | pub fn mutability(self) -> TokenStream { |
50 | match self { |
51 | RefType::Mut => quote!(mut), |
52 | _ => quote!(), |
53 | } |
54 | } |
55 | |
56 | pub fn pattern_ref(self) -> TokenStream { |
57 | match self { |
58 | RefType::Ref => quote!(ref), |
59 | RefType::Mut => quote!(ref mut), |
60 | RefType::No => quote!(), |
61 | } |
62 | } |
63 | |
64 | pub fn reference_with_lifetime(self) -> TokenStream { |
65 | if !self.is_ref() { |
66 | return quote!(); |
67 | } |
68 | let lifetime = self.lifetime(); |
69 | let mutability = self.mutability(); |
70 | quote!(&#lifetime #mutability) |
71 | } |
72 | |
73 | pub fn is_ref(self) -> bool { |
74 | match self { |
75 | RefType::No => false, |
76 | _ => true, |
77 | } |
78 | } |
79 | |
80 | pub fn from_attr_name(name: &str) -> Self { |
81 | match name { |
82 | "owned" => RefType::No, |
83 | "ref" => RefType::Ref, |
84 | "ref_mut" => RefType::Mut, |
85 | _ => panic!("' {}' is not a RefType" , name), |
86 | } |
87 | } |
88 | } |
89 | |
90 | pub fn numbered_vars(count: usize, prefix: &str) -> Vec<Ident> { |
91 | (0..count) |
92 | .map(|i: usize| Ident::new(&format!("__ {}{}" , prefix, i), Span::call_site())) |
93 | .collect() |
94 | } |
95 | |
96 | pub fn field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident> { |
97 | fieldsimpl Iterator |
98 | .iter() |
99 | .map(|f: &&Field| { |
100 | f.ident |
101 | .as_ref() |
102 | .expect(msg:"Tried to get field names of a tuple struct" ) |
103 | }) |
104 | .collect() |
105 | } |
106 | |
107 | pub fn get_field_types_iter<'a>( |
108 | fields: &'a [&'a Field], |
109 | ) -> Box<dyn Iterator<Item = &'a Type> + 'a> { |
110 | Box::new(fields.iter().map(|f: &&Field| &f.ty)) |
111 | } |
112 | |
113 | pub fn get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type> { |
114 | get_field_types_iter(fields).collect() |
115 | } |
116 | |
117 | pub fn add_extra_type_param_bound_op_output<'a>( |
118 | generics: &'a Generics, |
119 | trait_ident: &'a Ident, |
120 | ) -> Generics { |
121 | let mut generics: Generics = generics.clone(); |
122 | for type_param: &mut TypeParam in &mut generics.type_params_mut() { |
123 | let type_ident: &Ident = &type_param.ident; |
124 | let bound: TypeParamBound = parse_quote! { |
125 | ::core::ops::#trait_ident<Output=#type_ident> |
126 | }; |
127 | type_param.bounds.push(bound) |
128 | } |
129 | |
130 | generics |
131 | } |
132 | |
133 | pub fn add_extra_ty_param_bound_op<'a>( |
134 | generics: &'a Generics, |
135 | trait_ident: &'a Ident, |
136 | ) -> Generics { |
137 | add_extra_ty_param_bound(generics, "e!(::core::ops::#trait_ident)) |
138 | } |
139 | |
140 | pub fn add_extra_ty_param_bound<'a>( |
141 | generics: &'a Generics, |
142 | bound: &'a TokenStream, |
143 | ) -> Generics { |
144 | let mut generics: Generics = generics.clone(); |
145 | let bound: TypeParamBound = parse_quote! { #bound }; |
146 | for type_param: &mut TypeParam in &mut generics.type_params_mut() { |
147 | type_param.bounds.push(bound.clone()) |
148 | } |
149 | |
150 | generics |
151 | } |
152 | |
153 | pub fn add_extra_ty_param_bound_ref<'a>( |
154 | generics: &'a Generics, |
155 | bound: &'a TokenStream, |
156 | ref_type: RefType, |
157 | ) -> Generics { |
158 | match ref_type { |
159 | RefType::No => add_extra_ty_param_bound(generics, bound), |
160 | _ => { |
161 | let generics: Generics = generics.clone(); |
162 | let idents: impl Iterator = generics.type_params().map(|x: &TypeParam| &x.ident); |
163 | let ref_with_lifetime: TokenStream = ref_type.reference_with_lifetime(); |
164 | add_extra_where_clauses( |
165 | &generics, |
166 | type_where_clauses:quote!( |
167 | where #(#ref_with_lifetime #idents: #bound),* |
168 | ), |
169 | ) |
170 | } |
171 | } |
172 | } |
173 | |
174 | pub fn add_extra_generic_param( |
175 | generics: &Generics, |
176 | generic_param: TokenStream, |
177 | ) -> Generics { |
178 | let generic_param: GenericParam = parse_quote! { #generic_param }; |
179 | let mut generics: Generics = generics.clone(); |
180 | generics.params.push(generic_param); |
181 | |
182 | generics |
183 | } |
184 | |
185 | pub fn add_extra_generic_type_param( |
186 | generics: &Generics, |
187 | generic_param: TokenStream, |
188 | ) -> Generics { |
189 | let generic_param: GenericParam = parse_quote! { #generic_param }; |
190 | let lifetimes: Vec<GenericParam> = |
191 | generics.lifetimes().map(|x: &LifetimeDef| x.clone().into()).collect(); |
192 | let type_params: Vec<GenericParam> = |
193 | generics.type_params().map(|x: &TypeParam| x.clone().into()).collect(); |
194 | let const_params: Vec<GenericParam> = |
195 | generics.const_params().map(|x: &ConstParam| x.clone().into()).collect(); |
196 | let mut generics: Generics = generics.clone(); |
197 | generics.params = Default::default(); |
198 | generics.params.extend(iter:lifetimes); |
199 | generics.params.extend(iter:type_params); |
200 | generics.params.push(generic_param); |
201 | generics.params.extend(iter:const_params); |
202 | |
203 | generics |
204 | } |
205 | |
206 | pub fn add_extra_where_clauses( |
207 | generics: &Generics, |
208 | type_where_clauses: TokenStream, |
209 | ) -> Generics { |
210 | let mut type_where_clauses: WhereClause = parse_quote! { #type_where_clauses }; |
211 | let mut new_generics: Generics = generics.clone(); |
212 | if let Some(old_where: WhereClause) = new_generics.where_clause { |
213 | type_where_clauses.predicates.extend(iter:old_where.predicates) |
214 | } |
215 | new_generics.where_clause = Some(type_where_clauses); |
216 | |
217 | new_generics |
218 | } |
219 | |
220 | pub fn add_where_clauses_for_new_ident<'a>( |
221 | generics: &'a Generics, |
222 | fields: &[&'a Field], |
223 | type_ident: &Ident, |
224 | type_where_clauses: TokenStream, |
225 | sized: bool, |
226 | ) -> Generics { |
227 | let generic_param: TokenStream = if fields.len() > 1 { |
228 | quote!(#type_ident: ::core::marker::Copy) |
229 | } else if sized { |
230 | quote!(#type_ident) |
231 | } else { |
232 | quote!(#type_ident: ?::core::marker::Sized) |
233 | }; |
234 | |
235 | let generics: Generics = add_extra_where_clauses(generics, type_where_clauses); |
236 | add_extra_generic_type_param(&generics, generic_param) |
237 | } |
238 | |
239 | pub fn unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field> { |
240 | fields.unnamed.iter().collect() |
241 | } |
242 | |
243 | pub fn named_to_vec(fields: &FieldsNamed) -> Vec<&Field> { |
244 | fields.named.iter().collect() |
245 | } |
246 | |
247 | fn panic_one_field(trait_name: &str, trait_attr: &str) -> ! { |
248 | panic!( |
249 | "derive( {}) only works when forwarding to a single field. Try putting #[ {}] or #[ {}(ignore)] on the fields in the struct" , |
250 | trait_name, trait_attr, trait_attr, |
251 | ) |
252 | } |
253 | |
254 | #[derive (Copy, Clone, Debug, PartialEq, Eq)] |
255 | pub enum DeriveType { |
256 | Unnamed, |
257 | Named, |
258 | Enum, |
259 | } |
260 | |
261 | pub struct State<'input> { |
262 | pub input: &'input DeriveInput, |
263 | pub trait_name: &'static str, |
264 | pub trait_ident: Ident, |
265 | pub method_ident: Ident, |
266 | pub trait_module: TokenStream, |
267 | pub trait_path: TokenStream, |
268 | pub trait_path_params: Vec<TokenStream>, |
269 | pub trait_attr: String, |
270 | pub derive_type: DeriveType, |
271 | pub fields: Vec<&'input Field>, |
272 | pub variants: Vec<&'input Variant>, |
273 | pub variant_states: Vec<State<'input>>, |
274 | pub variant: Option<&'input Variant>, |
275 | pub generics: Generics, |
276 | pub default_info: FullMetaInfo, |
277 | full_meta_infos: Vec<FullMetaInfo>, |
278 | } |
279 | |
280 | #[derive (Default, Clone)] |
281 | pub struct AttrParams { |
282 | pub enum_: Vec<&'static str>, |
283 | pub variant: Vec<&'static str>, |
284 | pub struct_: Vec<&'static str>, |
285 | pub field: Vec<&'static str>, |
286 | } |
287 | |
288 | impl AttrParams { |
289 | pub fn new(params: Vec<&'static str>) -> AttrParams { |
290 | AttrParams { |
291 | enum_: params.clone(), |
292 | struct_: params.clone(), |
293 | variant: params.clone(), |
294 | field: params, |
295 | } |
296 | } |
297 | pub fn struct_(params: Vec<&'static str>) -> AttrParams { |
298 | AttrParams { |
299 | enum_: vec![], |
300 | struct_: params, |
301 | variant: vec![], |
302 | field: vec![], |
303 | } |
304 | } |
305 | |
306 | pub fn ignore_and_forward() -> AttrParams { |
307 | AttrParams::new(params:vec!["ignore" , "forward" ]) |
308 | } |
309 | } |
310 | |
311 | impl<'input> State<'input> { |
312 | pub fn new<'arg_input>( |
313 | input: &'arg_input DeriveInput, |
314 | trait_name: &'static str, |
315 | trait_module: TokenStream, |
316 | trait_attr: String, |
317 | ) -> Result<State<'arg_input>> { |
318 | State::new_impl( |
319 | input, |
320 | trait_name, |
321 | trait_module, |
322 | trait_attr, |
323 | AttrParams::default(), |
324 | true, |
325 | ) |
326 | } |
327 | |
328 | pub fn with_field_ignore<'arg_input>( |
329 | input: &'arg_input DeriveInput, |
330 | trait_name: &'static str, |
331 | trait_module: TokenStream, |
332 | trait_attr: String, |
333 | ) -> Result<State<'arg_input>> { |
334 | State::new_impl( |
335 | input, |
336 | trait_name, |
337 | trait_module, |
338 | trait_attr, |
339 | AttrParams::new(vec!["ignore" ]), |
340 | true, |
341 | ) |
342 | } |
343 | |
344 | pub fn with_field_ignore_and_forward<'arg_input>( |
345 | input: &'arg_input DeriveInput, |
346 | trait_name: &'static str, |
347 | trait_module: TokenStream, |
348 | trait_attr: String, |
349 | ) -> Result<State<'arg_input>> { |
350 | State::new_impl( |
351 | input, |
352 | trait_name, |
353 | trait_module, |
354 | trait_attr, |
355 | AttrParams::new(vec!["ignore" , "forward" ]), |
356 | true, |
357 | ) |
358 | } |
359 | |
360 | pub fn with_field_ignore_and_refs<'arg_input>( |
361 | input: &'arg_input DeriveInput, |
362 | trait_name: &'static str, |
363 | trait_module: TokenStream, |
364 | trait_attr: String, |
365 | ) -> Result<State<'arg_input>> { |
366 | State::new_impl( |
367 | input, |
368 | trait_name, |
369 | trait_module, |
370 | trait_attr, |
371 | AttrParams::new(vec!["ignore" , "owned" , "ref" , "ref_mut" ]), |
372 | true, |
373 | ) |
374 | } |
375 | |
376 | pub fn with_attr_params<'arg_input>( |
377 | input: &'arg_input DeriveInput, |
378 | trait_name: &'static str, |
379 | trait_module: TokenStream, |
380 | trait_attr: String, |
381 | allowed_attr_params: AttrParams, |
382 | ) -> Result<State<'arg_input>> { |
383 | State::new_impl( |
384 | input, |
385 | trait_name, |
386 | trait_module, |
387 | trait_attr, |
388 | allowed_attr_params, |
389 | true, |
390 | ) |
391 | } |
392 | |
393 | pub fn with_type_bound<'arg_input>( |
394 | input: &'arg_input DeriveInput, |
395 | trait_name: &'static str, |
396 | trait_module: TokenStream, |
397 | trait_attr: String, |
398 | allowed_attr_params: AttrParams, |
399 | add_type_bound: bool, |
400 | ) -> Result<State<'arg_input>> { |
401 | Self::new_impl( |
402 | input, |
403 | trait_name, |
404 | trait_module, |
405 | trait_attr, |
406 | allowed_attr_params, |
407 | add_type_bound, |
408 | ) |
409 | } |
410 | |
411 | fn new_impl<'arg_input>( |
412 | input: &'arg_input DeriveInput, |
413 | trait_name: &'static str, |
414 | trait_module: TokenStream, |
415 | trait_attr: String, |
416 | allowed_attr_params: AttrParams, |
417 | add_type_bound: bool, |
418 | ) -> Result<State<'arg_input>> { |
419 | let trait_name = trait_name.trim_end_matches("ToInner" ); |
420 | let trait_ident = Ident::new(trait_name, Span::call_site()); |
421 | let method_ident = Ident::new(&trait_attr, Span::call_site()); |
422 | let trait_path = quote!(#trait_module::#trait_ident); |
423 | let (derive_type, fields, variants): (_, Vec<_>, Vec<_>) = match input.data { |
424 | Data::Struct(ref data_struct) => match data_struct.fields { |
425 | Fields::Unnamed(ref fields) => { |
426 | (DeriveType::Unnamed, unnamed_to_vec(fields), vec![]) |
427 | } |
428 | |
429 | Fields::Named(ref fields) => { |
430 | (DeriveType::Named, named_to_vec(fields), vec![]) |
431 | } |
432 | Fields::Unit => (DeriveType::Named, vec![], vec![]), |
433 | }, |
434 | Data::Enum(ref data_enum) => ( |
435 | DeriveType::Enum, |
436 | vec![], |
437 | data_enum.variants.iter().collect(), |
438 | ), |
439 | Data::Union(_) => { |
440 | panic!("cannot derive( {}) for union" , trait_name) |
441 | } |
442 | }; |
443 | let attrs: Vec<_> = if derive_type == DeriveType::Enum { |
444 | variants.iter().map(|v| &v.attrs).collect() |
445 | } else { |
446 | fields.iter().map(|f| &f.attrs).collect() |
447 | }; |
448 | |
449 | let (allowed_attr_params_outer, allowed_attr_params_inner) = |
450 | if derive_type == DeriveType::Enum { |
451 | (&allowed_attr_params.enum_, &allowed_attr_params.variant) |
452 | } else { |
453 | (&allowed_attr_params.struct_, &allowed_attr_params.field) |
454 | }; |
455 | |
456 | let struct_meta_info = |
457 | get_meta_info(&trait_attr, &input.attrs, allowed_attr_params_outer)?; |
458 | let meta_infos: Result<Vec<_>> = attrs |
459 | .iter() |
460 | .map(|attrs| get_meta_info(&trait_attr, attrs, allowed_attr_params_inner)) |
461 | .collect(); |
462 | let meta_infos = meta_infos?; |
463 | let first_match = meta_infos |
464 | .iter() |
465 | .filter_map(|info| info.enabled.map(|_| info)) |
466 | .next(); |
467 | |
468 | // Default to enabled true, except when first attribute has explicit |
469 | // enabling. |
470 | // |
471 | // Except for derive Error. |
472 | // |
473 | // The way `else` case works is that if any field have any valid |
474 | // attribute specified, then all fields without any attributes |
475 | // specified are filtered out from `State::enabled_fields`. |
476 | // |
477 | // However, derive Error *infers* fields and there are cases when |
478 | // one of the fields may have an attribute specified, but another field |
479 | // would be inferred. So, for derive Error macro we default enabled |
480 | // to true unconditionally (i.e., even if some fields have attributes |
481 | // specified). |
482 | let default_enabled = if trait_name == "Error" { |
483 | true |
484 | } else { |
485 | first_match.map_or(true, |info| !info.enabled.unwrap()) |
486 | }; |
487 | |
488 | let defaults = struct_meta_info.into_full(FullMetaInfo { |
489 | enabled: default_enabled, |
490 | forward: false, |
491 | // Default to owned true, except when first attribute has one of owned, |
492 | // ref or ref_mut |
493 | // - not a single attribute means default true |
494 | // - an attribute, but non of owned, ref or ref_mut means default true |
495 | // - an attribute, and owned, ref or ref_mut means default false |
496 | owned: first_match.map_or(true, |info| { |
497 | info.owned.is_none() && info.ref_.is_none() || info.ref_mut.is_none() |
498 | }), |
499 | ref_: false, |
500 | ref_mut: false, |
501 | info: MetaInfo::default(), |
502 | }); |
503 | |
504 | let full_meta_infos: Vec<_> = meta_infos |
505 | .into_iter() |
506 | .map(|info| info.into_full(defaults.clone())) |
507 | .collect(); |
508 | |
509 | let variant_states: Result<Vec<_>> = if derive_type == DeriveType::Enum { |
510 | variants |
511 | .iter() |
512 | .zip(full_meta_infos.iter().cloned()) |
513 | .map(|(variant, info)| { |
514 | State::from_variant( |
515 | input, |
516 | trait_name, |
517 | trait_module.clone(), |
518 | trait_attr.clone(), |
519 | allowed_attr_params.clone(), |
520 | variant, |
521 | info, |
522 | ) |
523 | }) |
524 | .collect() |
525 | } else { |
526 | Ok(vec![]) |
527 | }; |
528 | |
529 | let generics = if add_type_bound { |
530 | add_extra_ty_param_bound(&input.generics, &trait_path) |
531 | } else { |
532 | input.generics.clone() |
533 | }; |
534 | |
535 | Ok(State { |
536 | input, |
537 | trait_name, |
538 | trait_ident, |
539 | method_ident, |
540 | trait_module, |
541 | trait_path, |
542 | trait_path_params: vec![], |
543 | trait_attr, |
544 | // input, |
545 | fields, |
546 | variants, |
547 | variant_states: variant_states?, |
548 | variant: None, |
549 | derive_type, |
550 | generics, |
551 | full_meta_infos, |
552 | default_info: defaults, |
553 | }) |
554 | } |
555 | |
556 | pub fn from_variant<'arg_input>( |
557 | input: &'arg_input DeriveInput, |
558 | trait_name: &'static str, |
559 | trait_module: TokenStream, |
560 | trait_attr: String, |
561 | allowed_attr_params: AttrParams, |
562 | variant: &'arg_input Variant, |
563 | default_info: FullMetaInfo, |
564 | ) -> Result<State<'arg_input>> { |
565 | let trait_name = trait_name.trim_end_matches("ToInner" ); |
566 | let trait_ident = Ident::new(trait_name, Span::call_site()); |
567 | let method_ident = Ident::new(&trait_attr, Span::call_site()); |
568 | let trait_path = quote!(#trait_module::#trait_ident); |
569 | let (derive_type, fields): (_, Vec<_>) = match variant.fields { |
570 | Fields::Unnamed(ref fields) => { |
571 | (DeriveType::Unnamed, unnamed_to_vec(fields)) |
572 | } |
573 | |
574 | Fields::Named(ref fields) => (DeriveType::Named, named_to_vec(fields)), |
575 | Fields::Unit => (DeriveType::Named, vec![]), |
576 | }; |
577 | |
578 | let meta_infos: Result<Vec<_>> = fields |
579 | .iter() |
580 | .map(|f| &f.attrs) |
581 | .map(|attrs| get_meta_info(&trait_attr, attrs, &allowed_attr_params.field)) |
582 | .collect(); |
583 | let meta_infos = meta_infos?; |
584 | let full_meta_infos: Vec<_> = meta_infos |
585 | .into_iter() |
586 | .map(|info| info.into_full(default_info.clone())) |
587 | .collect(); |
588 | |
589 | let generics = add_extra_ty_param_bound(&input.generics, &trait_path); |
590 | |
591 | Ok(State { |
592 | input, |
593 | trait_name, |
594 | trait_module, |
595 | trait_path, |
596 | trait_path_params: vec![], |
597 | trait_attr, |
598 | trait_ident, |
599 | method_ident, |
600 | // input, |
601 | fields, |
602 | variants: vec![], |
603 | variant_states: vec![], |
604 | variant: Some(variant), |
605 | derive_type, |
606 | generics, |
607 | full_meta_infos, |
608 | default_info, |
609 | }) |
610 | } |
611 | pub fn add_trait_path_type_param(&mut self, param: TokenStream) { |
612 | self.trait_path_params.push(param); |
613 | } |
614 | |
615 | pub fn assert_single_enabled_field<'state>( |
616 | &'state self, |
617 | ) -> SingleFieldData<'input, 'state> { |
618 | if self.derive_type == DeriveType::Enum { |
619 | panic_one_field(self.trait_name, &self.trait_attr); |
620 | } |
621 | let data = self.enabled_fields_data(); |
622 | if data.fields.len() != 1 { |
623 | panic_one_field(self.trait_name, &self.trait_attr); |
624 | }; |
625 | SingleFieldData { |
626 | input_type: data.input_type, |
627 | field: data.fields[0], |
628 | field_type: data.field_types[0], |
629 | member: data.members[0].clone(), |
630 | info: data.infos[0].clone(), |
631 | field_ident: data.field_idents[0].clone(), |
632 | trait_path: data.trait_path, |
633 | trait_path_with_params: data.trait_path_with_params.clone(), |
634 | casted_trait: data.casted_traits[0].clone(), |
635 | impl_generics: data.impl_generics.clone(), |
636 | ty_generics: data.ty_generics.clone(), |
637 | where_clause: data.where_clause, |
638 | multi_field_data: data, |
639 | } |
640 | } |
641 | |
642 | pub fn enabled_fields_data<'state>(&'state self) -> MultiFieldData<'input, 'state> { |
643 | if self.derive_type == DeriveType::Enum { |
644 | panic!("cannot derive( {}) for enum" , self.trait_name) |
645 | } |
646 | let fields = self.enabled_fields(); |
647 | let field_idents = self.enabled_fields_idents(); |
648 | let field_indexes = self.enabled_fields_indexes(); |
649 | let field_types: Vec<_> = fields.iter().map(|f| &f.ty).collect(); |
650 | let members: Vec<_> = field_idents |
651 | .iter() |
652 | .map(|ident| quote!(self.#ident)) |
653 | .collect(); |
654 | let trait_path = &self.trait_path; |
655 | let trait_path_with_params = if !self.trait_path_params.is_empty() { |
656 | let params = self.trait_path_params.iter(); |
657 | quote!(#trait_path<#(#params),*>) |
658 | } else { |
659 | self.trait_path.clone() |
660 | }; |
661 | |
662 | let casted_traits: Vec<_> = field_types |
663 | .iter() |
664 | .map(|field_type| quote!(<#field_type as #trait_path_with_params>)) |
665 | .collect(); |
666 | let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl(); |
667 | let input_type = &self.input.ident; |
668 | let (variant_name, variant_type) = self.variant.map_or_else( |
669 | || (None, quote!(#input_type)), |
670 | |v| { |
671 | let variant_name = &v.ident; |
672 | (Some(variant_name), quote!(#input_type::#variant_name)) |
673 | }, |
674 | ); |
675 | MultiFieldData { |
676 | input_type, |
677 | variant_type, |
678 | variant_name, |
679 | variant_info: self.default_info.clone(), |
680 | fields, |
681 | field_types, |
682 | field_indexes, |
683 | members, |
684 | infos: self.enabled_infos(), |
685 | field_idents, |
686 | method_ident: &self.method_ident, |
687 | trait_path, |
688 | trait_path_with_params, |
689 | casted_traits, |
690 | impl_generics, |
691 | ty_generics, |
692 | where_clause, |
693 | state: self, |
694 | } |
695 | } |
696 | |
697 | pub fn enabled_variant_data<'state>( |
698 | &'state self, |
699 | ) -> MultiVariantData<'input, 'state> { |
700 | if self.derive_type != DeriveType::Enum { |
701 | panic!("can only derive( {}) for enum" , self.trait_name) |
702 | } |
703 | let variants = self.enabled_variants(); |
704 | let trait_path = &self.trait_path; |
705 | let (impl_generics, ty_generics, where_clause) = self.generics.split_for_impl(); |
706 | MultiVariantData { |
707 | input_type: &self.input.ident, |
708 | variants, |
709 | variant_states: self.enabled_variant_states(), |
710 | infos: self.enabled_infos(), |
711 | trait_path, |
712 | impl_generics, |
713 | ty_generics, |
714 | where_clause, |
715 | } |
716 | } |
717 | |
718 | fn enabled_variants(&self) -> Vec<&'input Variant> { |
719 | self.variants |
720 | .iter() |
721 | .zip(self.full_meta_infos.iter().map(|info| info.enabled)) |
722 | .filter(|(_, ig)| *ig) |
723 | .map(|(v, _)| *v) |
724 | .collect() |
725 | } |
726 | |
727 | fn enabled_variant_states(&self) -> Vec<&State<'input>> { |
728 | self.variant_states |
729 | .iter() |
730 | .zip(self.full_meta_infos.iter().map(|info| info.enabled)) |
731 | .filter(|(_, ig)| *ig) |
732 | .map(|(v, _)| v) |
733 | .collect() |
734 | } |
735 | |
736 | pub fn enabled_fields(&self) -> Vec<&'input Field> { |
737 | self.fields |
738 | .iter() |
739 | .zip(self.full_meta_infos.iter().map(|info| info.enabled)) |
740 | .filter(|(_, ig)| *ig) |
741 | .map(|(f, _)| *f) |
742 | .collect() |
743 | } |
744 | |
745 | fn field_idents(&self) -> Vec<TokenStream> { |
746 | if self.derive_type == DeriveType::Named { |
747 | self.fields |
748 | .iter() |
749 | .map(|f| { |
750 | f.ident |
751 | .as_ref() |
752 | .expect("Tried to get field names of a tuple struct" ) |
753 | .to_token_stream() |
754 | }) |
755 | .collect() |
756 | } else { |
757 | let count = self.fields.len(); |
758 | (0..count) |
759 | .map(|i| Index::from(i).to_token_stream()) |
760 | .collect() |
761 | } |
762 | } |
763 | |
764 | fn enabled_fields_idents(&self) -> Vec<TokenStream> { |
765 | self.field_idents() |
766 | .into_iter() |
767 | .zip(self.full_meta_infos.iter().map(|info| info.enabled)) |
768 | .filter(|(_, ig)| *ig) |
769 | .map(|(f, _)| f) |
770 | .collect() |
771 | } |
772 | |
773 | fn enabled_fields_indexes(&self) -> Vec<usize> { |
774 | self.full_meta_infos |
775 | .iter() |
776 | .map(|info| info.enabled) |
777 | .enumerate() |
778 | .filter(|(_, ig)| *ig) |
779 | .map(|(i, _)| i) |
780 | .collect() |
781 | } |
782 | fn enabled_infos(&self) -> Vec<FullMetaInfo> { |
783 | self.full_meta_infos |
784 | .iter() |
785 | .filter(|info| info.enabled) |
786 | .cloned() |
787 | .collect() |
788 | } |
789 | } |
790 | |
791 | #[derive (Clone)] |
792 | pub struct SingleFieldData<'input, 'state> { |
793 | pub input_type: &'input Ident, |
794 | pub field: &'input Field, |
795 | pub field_type: &'input Type, |
796 | pub field_ident: TokenStream, |
797 | pub member: TokenStream, |
798 | pub info: FullMetaInfo, |
799 | pub trait_path: &'state TokenStream, |
800 | pub trait_path_with_params: TokenStream, |
801 | pub casted_trait: TokenStream, |
802 | pub impl_generics: ImplGenerics<'state>, |
803 | pub ty_generics: TypeGenerics<'state>, |
804 | pub where_clause: Option<&'state WhereClause>, |
805 | multi_field_data: MultiFieldData<'input, 'state>, |
806 | } |
807 | |
808 | #[derive (Clone)] |
809 | pub struct MultiFieldData<'input, 'state> { |
810 | pub input_type: &'input Ident, |
811 | pub variant_type: TokenStream, |
812 | pub variant_name: Option<&'input Ident>, |
813 | pub variant_info: FullMetaInfo, |
814 | pub fields: Vec<&'input Field>, |
815 | pub field_types: Vec<&'input Type>, |
816 | pub field_idents: Vec<TokenStream>, |
817 | pub field_indexes: Vec<usize>, |
818 | pub members: Vec<TokenStream>, |
819 | pub infos: Vec<FullMetaInfo>, |
820 | pub method_ident: &'state Ident, |
821 | pub trait_path: &'state TokenStream, |
822 | pub trait_path_with_params: TokenStream, |
823 | pub casted_traits: Vec<TokenStream>, |
824 | pub impl_generics: ImplGenerics<'state>, |
825 | pub ty_generics: TypeGenerics<'state>, |
826 | pub where_clause: Option<&'state WhereClause>, |
827 | pub state: &'state State<'input>, |
828 | } |
829 | |
830 | pub struct MultiVariantData<'input, 'state> { |
831 | pub input_type: &'input Ident, |
832 | pub variants: Vec<&'input Variant>, |
833 | pub variant_states: Vec<&'state State<'input>>, |
834 | pub infos: Vec<FullMetaInfo>, |
835 | pub trait_path: &'state TokenStream, |
836 | pub impl_generics: ImplGenerics<'state>, |
837 | pub ty_generics: TypeGenerics<'state>, |
838 | pub where_clause: Option<&'state WhereClause>, |
839 | } |
840 | |
841 | impl<'input, 'state> MultiFieldData<'input, 'state> { |
842 | pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream { |
843 | let MultiFieldData { |
844 | variant_type, |
845 | field_idents, |
846 | .. |
847 | } = self; |
848 | if self.state.derive_type == DeriveType::Named { |
849 | quote!(#variant_type{#(#field_idents: #initializers),*}) |
850 | } else { |
851 | quote!(#variant_type(#(#initializers),*)) |
852 | } |
853 | } |
854 | pub fn matcher<T: ToTokens>( |
855 | &self, |
856 | indexes: &[usize], |
857 | bindings: &[T], |
858 | ) -> TokenStream { |
859 | let MultiFieldData { variant_type, .. } = self; |
860 | let full_bindings = (0..self.state.fields.len()).map(|i| { |
861 | indexes.iter().position(|index| i == *index).map_or_else( |
862 | || quote!(_), |
863 | |found_index| bindings[found_index].to_token_stream(), |
864 | ) |
865 | }); |
866 | if self.state.derive_type == DeriveType::Named { |
867 | let field_idents = self.state.field_idents(); |
868 | quote!(#variant_type{#(#field_idents: #full_bindings),*}) |
869 | } else { |
870 | quote!(#variant_type(#(#full_bindings),*)) |
871 | } |
872 | } |
873 | } |
874 | |
875 | impl<'input, 'state> SingleFieldData<'input, 'state> { |
876 | pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream { |
877 | self.multi_field_data.initializer(initializers) |
878 | } |
879 | } |
880 | |
881 | fn get_meta_info( |
882 | trait_attr: &str, |
883 | attrs: &[Attribute], |
884 | allowed_attr_params: &[&str], |
885 | ) -> Result<MetaInfo> { |
886 | let mut it = attrs |
887 | .iter() |
888 | .filter_map(|m| m.parse_meta().ok()) |
889 | .filter(|m| { |
890 | m.path() |
891 | .segments |
892 | .first() |
893 | .map(|p| p.ident == trait_attr) |
894 | .unwrap_or_default() |
895 | }); |
896 | |
897 | let mut info = MetaInfo::default(); |
898 | |
899 | let meta = if let Some(meta) = it.next() { |
900 | meta |
901 | } else { |
902 | return Ok(info); |
903 | }; |
904 | |
905 | if allowed_attr_params.is_empty() { |
906 | return Err(Error::new(meta.span(), "Attribute is not allowed here" )); |
907 | } |
908 | |
909 | info.enabled = Some(true); |
910 | |
911 | if let Some(another_meta) = it.next() { |
912 | return Err(Error::new( |
913 | another_meta.span(), |
914 | "Only a single attribute is allowed" , |
915 | )); |
916 | } |
917 | |
918 | let list = match meta.clone() { |
919 | Meta::Path(_) => { |
920 | if allowed_attr_params.contains(&"ignore" ) { |
921 | return Ok(info); |
922 | } else { |
923 | return Err(Error::new( |
924 | meta.span(), |
925 | format!( |
926 | "Empty attribute is not allowed, add one of the following parameters: {}" , |
927 | allowed_attr_params.join(", " ), |
928 | ), |
929 | )); |
930 | } |
931 | } |
932 | Meta::List(list) => list, |
933 | Meta::NameValue(val) => { |
934 | return Err(Error::new( |
935 | val.span(), |
936 | "Attribute doesn't support name-value format here" , |
937 | )); |
938 | } |
939 | }; |
940 | |
941 | parse_punctuated_nested_meta(&mut info, &list.nested, allowed_attr_params, None)?; |
942 | |
943 | Ok(info) |
944 | } |
945 | |
946 | fn parse_punctuated_nested_meta( |
947 | info: &mut MetaInfo, |
948 | meta: &Punctuated<NestedMeta, Token![,]>, |
949 | allowed_attr_params: &[&str], |
950 | wrapper_name: Option<&str>, |
951 | ) -> Result<()> { |
952 | for meta in meta.iter() { |
953 | let meta = match meta { |
954 | NestedMeta::Meta(meta) => meta, |
955 | NestedMeta::Lit(lit) => { |
956 | return Err(Error::new( |
957 | lit.span(), |
958 | "Attribute doesn't support literals here" , |
959 | )) |
960 | } |
961 | }; |
962 | |
963 | match meta { |
964 | Meta::List(list) if list.path.is_ident("not" ) => { |
965 | if wrapper_name.is_some() { |
966 | // Only single top-level `not` attribute is allowed. |
967 | return Err(Error::new( |
968 | list.span(), |
969 | "Attribute doesn't support multiple multiple or nested `not` parameters" , |
970 | )); |
971 | } |
972 | parse_punctuated_nested_meta( |
973 | info, |
974 | &list.nested, |
975 | allowed_attr_params, |
976 | Some("not" ), |
977 | )?; |
978 | } |
979 | |
980 | Meta::List(list) => { |
981 | let path = &list.path; |
982 | if !allowed_attr_params.iter().any(|param| path.is_ident(param)) { |
983 | return Err(Error::new( |
984 | meta.span(), |
985 | format!( |
986 | "Attribute nested parameter not supported. \ |
987 | Supported attribute parameters are: {}" , |
988 | allowed_attr_params.join(", " ), |
989 | ), |
990 | )); |
991 | } |
992 | |
993 | let mut parse_nested = true; |
994 | |
995 | let attr_name = path.get_ident().unwrap().to_string(); |
996 | match (wrapper_name, attr_name.as_str()) { |
997 | (None, "owned" ) => info.owned = Some(true), |
998 | (None, "ref" ) => info.ref_ = Some(true), |
999 | (None, "ref_mut" ) => info.ref_mut = Some(true), |
1000 | |
1001 | #[cfg (any(feature = "from" , feature = "into" ))] |
1002 | (None, "types" ) |
1003 | | (Some("owned" ), "types" ) |
1004 | | (Some("ref" ), "types" ) |
1005 | | (Some("ref_mut" ), "types" ) => { |
1006 | parse_nested = false; |
1007 | for meta in &list.nested { |
1008 | let typ: syn::Type = match meta { |
1009 | NestedMeta::Meta(meta) => { |
1010 | let path = if let Meta::Path(p) = meta { |
1011 | p |
1012 | } else { |
1013 | return Err(Error::new( |
1014 | meta.span(), |
1015 | format!( |
1016 | "Attribute doesn't support type {}" , |
1017 | quote! { #meta }, |
1018 | ), |
1019 | )); |
1020 | }; |
1021 | syn::TypePath { |
1022 | qself: None, |
1023 | path: path.clone(), |
1024 | } |
1025 | .into() |
1026 | } |
1027 | NestedMeta::Lit(syn::Lit::Str(s)) => s.parse()?, |
1028 | NestedMeta::Lit(lit) => return Err(Error::new( |
1029 | lit.span(), |
1030 | "Attribute doesn't support nested literals here" , |
1031 | )), |
1032 | }; |
1033 | |
1034 | for ref_type in wrapper_name |
1035 | .map(|n| vec![RefType::from_attr_name(n)]) |
1036 | .unwrap_or_else(|| { |
1037 | vec![RefType::No, RefType::Ref, RefType::Mut] |
1038 | }) |
1039 | { |
1040 | if info |
1041 | .types |
1042 | .entry(ref_type) |
1043 | .or_default() |
1044 | .replace(typ.clone()) |
1045 | .is_some() |
1046 | { |
1047 | return Err(Error::new( |
1048 | typ.span(), |
1049 | format!( |
1050 | "Duplicate type ` {}` specified" , |
1051 | quote! { #path }, |
1052 | ), |
1053 | )); |
1054 | } |
1055 | } |
1056 | } |
1057 | } |
1058 | |
1059 | _ => { |
1060 | return Err(Error::new( |
1061 | list.span(), |
1062 | format!( |
1063 | "Attribute doesn't support nested parameter ` {}` here" , |
1064 | quote! { #path }, |
1065 | ), |
1066 | )) |
1067 | } |
1068 | }; |
1069 | |
1070 | if parse_nested { |
1071 | parse_punctuated_nested_meta( |
1072 | info, |
1073 | &list.nested, |
1074 | allowed_attr_params, |
1075 | Some(&attr_name), |
1076 | )?; |
1077 | } |
1078 | } |
1079 | |
1080 | Meta::Path(path) => { |
1081 | if !allowed_attr_params.iter().any(|param| path.is_ident(param)) { |
1082 | return Err(Error::new( |
1083 | meta.span(), |
1084 | format!( |
1085 | "Attribute parameter not supported. \ |
1086 | Supported attribute parameters are: {}" , |
1087 | allowed_attr_params.join(", " ), |
1088 | ), |
1089 | )); |
1090 | } |
1091 | |
1092 | let attr_name = path.get_ident().unwrap().to_string(); |
1093 | match (wrapper_name, attr_name.as_str()) { |
1094 | (None, "ignore" ) => info.enabled = Some(false), |
1095 | (None, "forward" ) => info.forward = Some(true), |
1096 | (Some("not" ), "forward" ) => info.forward = Some(false), |
1097 | (None, "owned" ) => info.owned = Some(true), |
1098 | (None, "ref" ) => info.ref_ = Some(true), |
1099 | (None, "ref_mut" ) => info.ref_mut = Some(true), |
1100 | (None, "source" ) => info.source = Some(true), |
1101 | (Some("not" ), "source" ) => info.source = Some(false), |
1102 | (None, "backtrace" ) => info.backtrace = Some(true), |
1103 | (Some("not" ), "backtrace" ) => info.backtrace = Some(false), |
1104 | _ => { |
1105 | return Err(Error::new( |
1106 | path.span(), |
1107 | format!( |
1108 | "Attribute doesn't support parameter ` {}` here" , |
1109 | quote! { #path } |
1110 | ), |
1111 | )) |
1112 | } |
1113 | } |
1114 | } |
1115 | |
1116 | Meta::NameValue(val) => { |
1117 | return Err(Error::new( |
1118 | val.span(), |
1119 | "Attribute doesn't support name-value parameters here" , |
1120 | )) |
1121 | } |
1122 | } |
1123 | } |
1124 | |
1125 | Ok(()) |
1126 | } |
1127 | |
1128 | #[derive (Clone, Debug, Default)] |
1129 | pub struct FullMetaInfo { |
1130 | pub enabled: bool, |
1131 | pub forward: bool, |
1132 | pub owned: bool, |
1133 | pub ref_: bool, |
1134 | pub ref_mut: bool, |
1135 | pub info: MetaInfo, |
1136 | } |
1137 | |
1138 | #[derive (Clone, Debug, Default)] |
1139 | pub struct MetaInfo { |
1140 | pub enabled: Option<bool>, |
1141 | pub forward: Option<bool>, |
1142 | pub owned: Option<bool>, |
1143 | pub ref_: Option<bool>, |
1144 | pub ref_mut: Option<bool>, |
1145 | pub source: Option<bool>, |
1146 | pub backtrace: Option<bool>, |
1147 | #[cfg (any(feature = "from" , feature = "into" ))] |
1148 | pub types: HashMap<RefType, HashSet<syn::Type>>, |
1149 | } |
1150 | |
1151 | impl MetaInfo { |
1152 | fn into_full(self, defaults: FullMetaInfo) -> FullMetaInfo { |
1153 | FullMetaInfo { |
1154 | enabled: self.enabled.unwrap_or(default:defaults.enabled), |
1155 | forward: self.forward.unwrap_or(default:defaults.forward), |
1156 | owned: self.owned.unwrap_or(default:defaults.owned), |
1157 | ref_: self.ref_.unwrap_or(default:defaults.ref_), |
1158 | ref_mut: self.ref_mut.unwrap_or(default:defaults.ref_mut), |
1159 | info: self, |
1160 | } |
1161 | } |
1162 | } |
1163 | |
1164 | impl FullMetaInfo { |
1165 | pub fn ref_types(&self) -> Vec<RefType> { |
1166 | let mut ref_types: Vec = vec![]; |
1167 | if self.owned { |
1168 | ref_types.push(RefType::No); |
1169 | } |
1170 | if self.ref_ { |
1171 | ref_types.push(RefType::Ref); |
1172 | } |
1173 | if self.ref_mut { |
1174 | ref_types.push(RefType::Mut); |
1175 | } |
1176 | ref_types |
1177 | } |
1178 | |
1179 | #[cfg (any(feature = "from" , feature = "into" ))] |
1180 | pub fn additional_types(&self, ref_type: RefType) -> HashSet<syn::Type> { |
1181 | self.info.types.get(&ref_type).cloned().unwrap_or_default() |
1182 | } |
1183 | } |
1184 | |
1185 | pub fn get_if_type_parameter_used_in_type( |
1186 | type_parameters: &HashSet<syn::Ident>, |
1187 | ty: &syn::Type, |
1188 | ) -> Option<syn::Type> { |
1189 | if is_type_parameter_used_in_type(type_parameters, ty) { |
1190 | match ty { |
1191 | syn::Type::Reference(syn::TypeReference { elem: ty: &Box, .. }) => { |
1192 | Some((&**ty).clone()) |
1193 | } |
1194 | ty: &Type => Some(ty.clone()), |
1195 | } |
1196 | } else { |
1197 | None |
1198 | } |
1199 | } |
1200 | |
1201 | pub fn is_type_parameter_used_in_type( |
1202 | type_parameters: &HashSet<syn::Ident>, |
1203 | ty: &syn::Type, |
1204 | ) -> bool { |
1205 | match ty { |
1206 | syn::Type::Path(ty) => { |
1207 | if let Some(qself) = &ty.qself { |
1208 | if is_type_parameter_used_in_type(type_parameters, &qself.ty) { |
1209 | return true; |
1210 | } |
1211 | } |
1212 | |
1213 | if let Some(segment) = ty.path.segments.first() { |
1214 | if type_parameters.contains(&segment.ident) { |
1215 | return true; |
1216 | } |
1217 | } |
1218 | |
1219 | ty.path.segments.iter().any(|segment| { |
1220 | if let syn::PathArguments::AngleBracketed(arguments) = |
1221 | &segment.arguments |
1222 | { |
1223 | arguments.args.iter().any(|argument| match argument { |
1224 | syn::GenericArgument::Type(ty) => { |
1225 | is_type_parameter_used_in_type(type_parameters, ty) |
1226 | } |
1227 | syn::GenericArgument::Constraint(constraint) => { |
1228 | type_parameters.contains(&constraint.ident) |
1229 | } |
1230 | _ => false, |
1231 | }) |
1232 | } else { |
1233 | false |
1234 | } |
1235 | }) |
1236 | } |
1237 | |
1238 | syn::Type::Reference(ty) => { |
1239 | is_type_parameter_used_in_type(type_parameters, &ty.elem) |
1240 | } |
1241 | |
1242 | _ => false, |
1243 | } |
1244 | } |
1245 | |