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