darling_core/codegen/
from_derive_impl.rs
1use proc_macro2::TokenStream;
2use quote::{quote, quote_spanned, ToTokens};
3use syn::Ident;
4
5use crate::{
6 ast::Data,
7 codegen::{ExtractAttribute, OuterFromImpl, TraitImpl},
8 options::{DeriveInputShapeSet, ForwardedField},
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 ForwardedField>,
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 ToTokens for FromDeriveInputImpl<'_> {
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.data.as_ref().map(|i| {
60 let ForwardedField { ident, with } = i;
61 let path = match with {
62 Some(p) => quote!(#p),
63 None => quote_spanned!(ident.span()=> ::darling::ast::Data::try_from),
64 };
65 quote_spanned!(ident.span()=> #ident: #path(&#input.data)?,)
66 });
67
68 let supports = self.supports.map(|i| {
69 quote! {
70 #i
71 __errors.handle(__validate_body(&#input.data));
72 }
73 });
74
75 let inits = self.base.initializers();
76 let default = if self.from_ident {
77 quote!(let __default: Self = ::darling::export::From::from(#input.ident.clone());)
78 } else {
79 self.base.fallback_decl()
80 };
81
82 let grab_attrs = self.extractor();
83
84 let declare_errors = self.base.declare_errors();
85 let require_fields = self.base.require_fields();
86 let check_errors = self.base.check_errors();
87
88 self.wrap(
89 quote! {
90 fn from_derive_input(#input: &::darling::export::syn::DeriveInput) -> ::darling::Result<Self> {
91 #declare_errors
92
93 #grab_attrs
94
95 #supports
96
97 #require_fields
98
99 #check_errors
100
101 #default
102
103 ::darling::export::Ok(#ty_ident {
104 #passed_ident
105 #passed_generics
106 #passed_vis
107 #passed_attrs
108 #passed_body
109 #inits
110 }) #post_transform
111 }
112 },
113 tokens,
114 );
115 }
116}
117
118impl ExtractAttribute for FromDeriveInputImpl<'_> {
119 fn attr_names(&self) -> &PathList {
120 self.attr_names
121 }
122
123 fn forward_attrs(&self) -> &ForwardAttrs<'_> {
124 &self.forward_attrs
125 }
126
127 fn param_name(&self) -> TokenStream {
128 quote!(__di)
129 }
130
131 fn core_loop(&self) -> TokenStream {
132 self.base.core_loop()
133 }
134
135 fn local_declarations(&self) -> TokenStream {
136 self.base.local_declarations()
137 }
138}
139
140impl<'a> OuterFromImpl<'a> for FromDeriveInputImpl<'a> {
141 fn trait_path(&self) -> syn::Path {
142 path!(::darling::FromDeriveInput)
143 }
144
145 fn trait_bound(&self) -> syn::Path {
146 path!(::darling::FromMeta)
147 }
148
149 fn base(&'a self) -> &'a TraitImpl<'a> {
150 &self.base
151 }
152}