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