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 
build_hasher(&self) -> Self::Hasher18     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 {
lifetime(self) -> TokenStream34     pub fn lifetime(self) -> TokenStream {
35         match self {
36             RefType::No => quote!(),
37             _ => quote!('__deriveMoreLifetime),
38         }
39     }
40 
reference(self) -> TokenStream41     pub fn reference(self) -> TokenStream {
42         match self {
43             RefType::No => quote!(),
44             RefType::Ref => quote!(&),
45             RefType::Mut => quote!(&mut),
46         }
47     }
48 
mutability(self) -> TokenStream49     pub fn mutability(self) -> TokenStream {
50         match self {
51             RefType::Mut => quote!(mut),
52             _ => quote!(),
53         }
54     }
55 
pattern_ref(self) -> TokenStream56     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 
reference_with_lifetime(self) -> TokenStream64     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 
is_ref(self) -> bool73     pub fn is_ref(self) -> bool {
74         match self {
75             RefType::No => false,
76             _ => true,
77         }
78     }
79 
from_attr_name(name: &str) -> Self80     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 
numbered_vars(count: usize, prefix: &str) -> Vec<Ident>90 pub fn numbered_vars(count: usize, prefix: &str) -> Vec<Ident> {
91     (0..count)
92         .map(|i| Ident::new(&format!("__{}{}", prefix, i), Span::call_site()))
93         .collect()
94 }
95 
field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident>96 pub fn field_idents<'a>(fields: &'a [&'a Field]) -> Vec<&'a Ident> {
97     fields
98         .iter()
99         .map(|f| {
100             f.ident
101                 .as_ref()
102                 .expect("Tried to get field names of a tuple struct")
103         })
104         .collect()
105 }
106 
get_field_types_iter<'a>( fields: &'a [&'a Field], ) -> Box<dyn Iterator<Item = &'a Type> + 'a>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| &f.ty))
111 }
112 
get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type>113 pub fn get_field_types<'a>(fields: &'a [&'a Field]) -> Vec<&'a Type> {
114     get_field_types_iter(fields).collect()
115 }
116 
add_extra_type_param_bound_op_output<'a>( generics: &'a Generics, trait_ident: &'a Ident, ) -> Generics117 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.clone();
122     for type_param in &mut generics.type_params_mut() {
123         let type_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 
add_extra_ty_param_bound_op<'a>( generics: &'a Generics, trait_ident: &'a Ident, ) -> Generics133 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, &quote!(::core::ops::#trait_ident))
138 }
139 
add_extra_ty_param_bound<'a>( generics: &'a Generics, bound: &'a TokenStream, ) -> Generics140 pub fn add_extra_ty_param_bound<'a>(
141     generics: &'a Generics,
142     bound: &'a TokenStream,
143 ) -> Generics {
144     let mut generics = generics.clone();
145     let bound: TypeParamBound = parse_quote! { #bound };
146     for type_param in &mut generics.type_params_mut() {
147         type_param.bounds.push(bound.clone())
148     }
149 
150     generics
151 }
152 
add_extra_ty_param_bound_ref<'a>( generics: &'a Generics, bound: &'a TokenStream, ref_type: RefType, ) -> Generics153 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.clone();
162             let idents = generics.type_params().map(|x| &x.ident);
163             let ref_with_lifetime = ref_type.reference_with_lifetime();
164             add_extra_where_clauses(
165                 &generics,
166                 quote!(
167                     where #(#ref_with_lifetime #idents: #bound),*
168                 ),
169             )
170         }
171     }
172 }
173 
add_extra_generic_param( generics: &Generics, generic_param: TokenStream, ) -> Generics174 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.clone();
180     generics.params.push(generic_param);
181 
182     generics
183 }
184 
add_extra_generic_type_param( generics: &Generics, generic_param: TokenStream, ) -> Generics185 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| x.clone().into()).collect();
192     let type_params: Vec<GenericParam> =
193         generics.type_params().map(|x| x.clone().into()).collect();
194     let const_params: Vec<GenericParam> =
195         generics.const_params().map(|x| x.clone().into()).collect();
196     let mut generics = generics.clone();
197     generics.params = Default::default();
198     generics.params.extend(lifetimes);
199     generics.params.extend(type_params);
200     generics.params.push(generic_param);
201     generics.params.extend(const_params);
202 
203     generics
204 }
205 
add_extra_where_clauses( generics: &Generics, type_where_clauses: TokenStream, ) -> Generics206 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.clone();
212     if let Some(old_where) = new_generics.where_clause {
213         type_where_clauses.predicates.extend(old_where.predicates)
214     }
215     new_generics.where_clause = Some(type_where_clauses);
216 
217     new_generics
218 }
219 
add_where_clauses_for_new_ident<'a>( generics: &'a Generics, fields: &[&'a Field], type_ident: &Ident, type_where_clauses: TokenStream, sized: bool, ) -> Generics220 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 = 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 = add_extra_where_clauses(generics, type_where_clauses);
236     add_extra_generic_type_param(&generics, generic_param)
237 }
238 
unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field>239 pub fn unnamed_to_vec(fields: &FieldsUnnamed) -> Vec<&Field> {
240     fields.unnamed.iter().collect()
241 }
242 
named_to_vec(fields: &FieldsNamed) -> Vec<&Field>243 pub fn named_to_vec(fields: &FieldsNamed) -> Vec<&Field> {
244     fields.named.iter().collect()
245 }
246 
panic_one_field(trait_name: &str, trait_attr: &str) -> !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 {
new(params: Vec<&'static str>) -> AttrParams289     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     }
struct_(params: Vec<&'static str>) -> AttrParams297     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 
ignore_and_forward() -> AttrParams306     pub fn ignore_and_forward() -> AttrParams {
307         AttrParams::new(vec!["ignore", "forward"])
308     }
309 }
310 
311 impl<'input> State<'input> {
new<'arg_input>( input: &'arg_input DeriveInput, trait_name: &'static str, trait_module: TokenStream, trait_attr: String, ) -> Result<State<'arg_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 
with_field_ignore<'arg_input>( input: &'arg_input DeriveInput, trait_name: &'static str, trait_module: TokenStream, trait_attr: String, ) -> Result<State<'arg_input>>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 
with_field_ignore_and_forward<'arg_input>( input: &'arg_input DeriveInput, trait_name: &'static str, trait_module: TokenStream, trait_attr: String, ) -> Result<State<'arg_input>>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 
with_field_ignore_and_refs<'arg_input>( input: &'arg_input DeriveInput, trait_name: &'static str, trait_module: TokenStream, trait_attr: String, ) -> Result<State<'arg_input>>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 
with_attr_params<'arg_input>( input: &'arg_input DeriveInput, trait_name: &'static str, trait_module: TokenStream, trait_attr: String, allowed_attr_params: AttrParams, ) -> Result<State<'arg_input>>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 
with_type_bound<'arg_input>( input: &'arg_input DeriveInput, trait_name: &'static str, trait_module: TokenStream, trait_attr: String, allowed_attr_params: AttrParams, add_type_bound: bool, ) -> Result<State<'arg_input>>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 
new_impl<'arg_input>( input: &'arg_input DeriveInput, trait_name: &'static str, trait_module: TokenStream, trait_attr: String, allowed_attr_params: AttrParams, add_type_bound: bool, ) -> Result<State<'arg_input>>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 
from_variant<'arg_input>( input: &'arg_input DeriveInput, trait_name: &'static str, trait_module: TokenStream, trait_attr: String, allowed_attr_params: AttrParams, variant: &'arg_input Variant, default_info: FullMetaInfo, ) -> Result<State<'arg_input>>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     }
add_trait_path_type_param(&mut self, param: TokenStream)611     pub fn add_trait_path_type_param(&mut self, param: TokenStream) {
612         self.trait_path_params.push(param);
613     }
614 
assert_single_enabled_field<'state>( &'state self, ) -> SingleFieldData<'input, 'state>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 
enabled_fields_data<'state>(&'state self) -> MultiFieldData<'input, 'state>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 
enabled_variant_data<'state>( &'state self, ) -> MultiVariantData<'input, 'state>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 
enabled_variants(&self) -> Vec<&'input Variant>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 
enabled_variant_states(&self) -> Vec<&State<'input>>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 
enabled_fields(&self) -> Vec<&'input Field>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 
field_idents(&self) -> Vec<TokenStream>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 
enabled_fields_idents(&self) -> Vec<TokenStream>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 
enabled_fields_indexes(&self) -> Vec<usize>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     }
enabled_infos(&self) -> Vec<FullMetaInfo>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> {
initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream842     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     }
matcher<T: ToTokens>( &self, indexes: &[usize], bindings: &[T], ) -> TokenStream854     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> {
initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream876     pub fn initializer<T: ToTokens>(&self, initializers: &[T]) -> TokenStream {
877         self.multi_field_data.initializer(initializers)
878     }
879 }
880 
get_meta_info( trait_attr: &str, attrs: &[Attribute], allowed_attr_params: &[&str], ) -> Result<MetaInfo>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 
parse_punctuated_nested_meta( info: &mut MetaInfo, meta: &Punctuated<NestedMeta, Token![,]>, allowed_attr_params: &[&str], wrapper_name: Option<&str>, ) -> Result<()>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 {
into_full(self, defaults: FullMetaInfo) -> FullMetaInfo1152     fn into_full(self, defaults: FullMetaInfo) -> FullMetaInfo {
1153         FullMetaInfo {
1154             enabled: self.enabled.unwrap_or(defaults.enabled),
1155             forward: self.forward.unwrap_or(defaults.forward),
1156             owned: self.owned.unwrap_or(defaults.owned),
1157             ref_: self.ref_.unwrap_or(defaults.ref_),
1158             ref_mut: self.ref_mut.unwrap_or(defaults.ref_mut),
1159             info: self,
1160         }
1161     }
1162 }
1163 
1164 impl FullMetaInfo {
ref_types(&self) -> Vec<RefType>1165     pub fn ref_types(&self) -> Vec<RefType> {
1166         let mut ref_types = 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"))]
additional_types(&self, ref_type: RefType) -> HashSet<syn::Type>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 
get_if_type_parameter_used_in_type( type_parameters: &HashSet<syn::Ident>, ty: &syn::Type, ) -> Option<syn::Type>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, .. }) => {
1192                 Some((&**ty).clone())
1193             }
1194             ty => Some(ty.clone()),
1195         }
1196     } else {
1197         None
1198     }
1199 }
1200 
is_type_parameter_used_in_type( type_parameters: &HashSet<syn::Ident>, ty: &syn::Type, ) -> bool1201 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