1 use proc_macro2::TokenStream;
2 use quote::ToTokens;
3 use syn::{self, Ident};
4 
5 use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl};
6 use options::ForwardAttrs;
7 use util::IdentList;
8 
9 /// `impl FromField` generator. This is used for parsing an individual
10 /// field and its attributes.
11 pub struct FromFieldImpl<'a> {
12     pub ident: Option<&'a Ident>,
13     pub vis: Option<&'a Ident>,
14     pub ty: Option<&'a Ident>,
15     pub attrs: Option<&'a Ident>,
16     pub base: TraitImpl<'a>,
17     pub attr_names: &'a IdentList,
18     pub forward_attrs: Option<&'a ForwardAttrs>,
19     pub from_ident: bool,
20 }
21 
22 impl<'a> ToTokens for FromFieldImpl<'a> {
to_tokens(&self, tokens: &mut TokenStream)23     fn to_tokens(&self, tokens: &mut TokenStream) {
24         let input = self.param_name();
25 
26         let error_declaration = self.base.declare_errors();
27         let require_fields = self.base.require_fields();
28         let error_check = self.base.check_errors();
29 
30         let initializers = self.base.initializers();
31 
32         let default = if self.from_ident {
33             quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());)
34         } else {
35             self.base.fallback_decl()
36         };
37 
38         let passed_ident = self.ident
39             .as_ref()
40             .map(|i| quote!(#i: #input.ident.clone(),));
41         let passed_vis = self.vis.as_ref().map(|i| quote!(#i: #input.vis.clone(),));
42         let passed_ty = self.ty.as_ref().map(|i| quote!(#i: #input.ty.clone(),));
43         let passed_attrs = self.attrs.as_ref().map(|i| quote!(#i: __fwd_attrs,));
44 
45         // Determine which attributes to forward (if any).
46         let grab_attrs = self.extractor();
47         let map = self.base.map_fn();
48 
49         self.wrap(
50             quote!{
51                 fn from_field(#input: &::syn::Field) -> ::darling::Result<Self> {
52                     #error_declaration
53 
54                     #grab_attrs
55 
56                     #require_fields
57 
58                     #error_check
59 
60                     #default
61 
62                     ::darling::export::Ok(Self {
63                         #passed_ident
64                         #passed_ty
65                         #passed_vis
66                         #passed_attrs
67                         #initializers
68                     }) #map
69 
70                 }
71             },
72             tokens,
73         );
74     }
75 }
76 
77 impl<'a> ExtractAttribute for FromFieldImpl<'a> {
attr_names(&self) -> &IdentList78     fn attr_names(&self) -> &IdentList {
79         &self.attr_names
80     }
81 
forwarded_attrs(&self) -> Option<&ForwardAttrs>82     fn forwarded_attrs(&self) -> Option<&ForwardAttrs> {
83         self.forward_attrs
84     }
85 
param_name(&self) -> TokenStream86     fn param_name(&self) -> TokenStream {
87         quote!(__field)
88     }
89 
core_loop(&self) -> TokenStream90     fn core_loop(&self) -> TokenStream {
91         self.base.core_loop()
92     }
93 
local_declarations(&self) -> TokenStream94     fn local_declarations(&self) -> TokenStream {
95         self.base.local_declarations()
96     }
97 
immutable_declarations(&self) -> TokenStream98     fn immutable_declarations(&self) -> TokenStream {
99         self.base.immutable_declarations()
100     }
101 }
102 
103 impl<'a> OuterFromImpl<'a> for FromFieldImpl<'a> {
trait_path(&self) -> syn::Path104     fn trait_path(&self) -> syn::Path {
105         path!(::darling::FromField)
106     }
107 
trait_bound(&self) -> syn::Path108     fn trait_bound(&self) -> syn::Path {
109         path!(::darling::FromMeta)
110     }
111 
base(&'a self) -> &'a TraitImpl<'a>112     fn base(&'a self) -> &'a TraitImpl<'a> {
113         &self.base
114     }
115 }
116