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