1 use proc_macro2::TokenStream;
2 use quote::ToTokens;
3 use syn::{self, Ident};
4 
5 use ast::Data;
6 use codegen::{ExtractAttribute, OuterFromImpl, TraitImpl};
7 use options::{ForwardAttrs, Shape};
8 use util::PathList;
9 
10 pub struct FromDeriveInputImpl<'a> {
11     pub ident: Option<&'a Ident>,
12     pub generics: Option<&'a Ident>,
13     pub vis: Option<&'a Ident>,
14     pub attrs: Option<&'a Ident>,
15     pub data: Option<&'a Ident>,
16     pub base: TraitImpl<'a>,
17     pub attr_names: &'a PathList,
18     pub forward_attrs: Option<&'a ForwardAttrs>,
19     pub from_ident: bool,
20     pub supports: Option<&'a Shape>,
21 }
22 
23 impl<'a> ToTokens for FromDeriveInputImpl<'a> {
to_tokens(&self, tokens: &mut TokenStream)24     fn to_tokens(&self, tokens: &mut TokenStream) {
25         let ty_ident = self.base.ident;
26         let input = self.param_name();
27         let map = self.base.map_fn();
28 
29         if let Data::Struct(ref data) = self.base.data {
30             if data.is_newtype() {
31                 self.wrap(
32                     quote!{
33                         fn from_derive_input(#input: &::syn::DeriveInput) -> ::darling::Result<Self> {
34                             ::darling::export::Ok(
35                                 #ty_ident(::darling::FromDeriveInput::from_derive_input(#input)?)
36                             ) #map
37                         }
38                     },
39                     tokens,
40                 );
41 
42                 return;
43             }
44         }
45 
46         let passed_ident = self.ident
47             .as_ref()
48             .map(|i| quote!(#i: #input.ident.clone(),));
49         let passed_vis = self.vis.as_ref().map(|i| quote!(#i: #input.vis.clone(),));
50         let passed_generics = self.generics
51             .as_ref()
52             .map(|i| quote!(#i: ::darling::FromGenerics::from_generics(&#input.generics)?,));
53         let passed_attrs = self.attrs.as_ref().map(|i| quote!(#i: __fwd_attrs,));
54         let passed_body = self.data
55             .as_ref()
56             .map(|i| quote!(#i: ::darling::ast::Data::try_from(&#input.data)?,));
57 
58         let supports = self.supports.map(|i| {
59             quote!{
60                 #i
61                 __validate_body(&#input.data)?;
62             }
63         });
64 
65         let inits = self.base.initializers();
66         let default = if self.from_ident {
67             quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());)
68         } else {
69             self.base.fallback_decl()
70         };
71 
72         let grab_attrs = self.extractor();
73 
74         let declare_errors = self.base.declare_errors();
75         let require_fields = self.base.require_fields();
76         let check_errors = self.base.check_errors();
77 
78         self.wrap(
79             quote! {
80                 fn from_derive_input(#input: &::syn::DeriveInput) -> ::darling::Result<Self> {
81                     #declare_errors
82 
83                     #grab_attrs
84 
85                     #supports
86 
87                     #require_fields
88 
89                     #check_errors
90 
91                     #default
92 
93                     ::darling::export::Ok(#ty_ident {
94                         #passed_ident
95                         #passed_generics
96                         #passed_vis
97                         #passed_attrs
98                         #passed_body
99                         #inits
100                     }) #map
101                 }
102             },
103             tokens,
104         );
105     }
106 }
107 
108 impl<'a> ExtractAttribute for FromDeriveInputImpl<'a> {
attr_names(&self) -> &PathList109     fn attr_names(&self) -> &PathList {
110         &self.attr_names
111     }
112 
forwarded_attrs(&self) -> Option<&ForwardAttrs>113     fn forwarded_attrs(&self) -> Option<&ForwardAttrs> {
114         self.forward_attrs
115     }
116 
param_name(&self) -> TokenStream117     fn param_name(&self) -> TokenStream {
118         quote!(__di)
119     }
120 
core_loop(&self) -> TokenStream121     fn core_loop(&self) -> TokenStream {
122         self.base.core_loop()
123     }
124 
local_declarations(&self) -> TokenStream125     fn local_declarations(&self) -> TokenStream {
126         self.base.local_declarations()
127     }
128 
immutable_declarations(&self) -> TokenStream129     fn immutable_declarations(&self) -> TokenStream {
130         self.base.immutable_declarations()
131     }
132 }
133 
134 impl<'a> OuterFromImpl<'a> for FromDeriveInputImpl<'a> {
trait_path(&self) -> syn::Path135     fn trait_path(&self) -> syn::Path {
136         path!(::darling::FromDeriveInput)
137     }
138 
trait_bound(&self) -> syn::Path139     fn trait_bound(&self) -> syn::Path {
140         path!(::darling::FromMeta)
141     }
142 
base(&'a self) -> &'a TraitImpl<'a>143     fn base(&'a self) -> &'a TraitImpl<'a> {
144         &self.base
145     }
146 }
147