• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use proc_macro2::TokenStream;
2 use quote::{quote, ToTokens};
3 use syn::Ident;
4 
5 use crate::{
6     codegen::{ExtractAttribute, OuterFromImpl, TraitImpl},
7     util::PathList,
8 };
9 
10 use super::ForwardAttrs;
11 
12 /// `impl FromField` generator. This is used for parsing an individual
13 /// field and its attributes.
14 pub struct FromFieldImpl<'a> {
15     pub ident: Option<&'a Ident>,
16     pub vis: Option<&'a Ident>,
17     pub ty: Option<&'a Ident>,
18     pub base: TraitImpl<'a>,
19     pub attr_names: &'a PathList,
20     pub forward_attrs: ForwardAttrs<'a>,
21     pub from_ident: bool,
22 }
23 
24 impl<'a> ToTokens for FromFieldImpl<'a> {
to_tokens(&self, tokens: &mut TokenStream)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.forward_attrs.as_initializer();
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 
80 impl<'a> ExtractAttribute for FromFieldImpl<'a> {
attr_names(&self) -> &PathList81     fn attr_names(&self) -> &PathList {
82         self.attr_names
83     }
84 
forward_attrs(&self) -> &super::ForwardAttrs<'_>85     fn forward_attrs(&self) -> &super::ForwardAttrs<'_> {
86         &self.forward_attrs
87     }
88 
param_name(&self) -> TokenStream89     fn param_name(&self) -> TokenStream {
90         quote!(__field)
91     }
92 
core_loop(&self) -> TokenStream93     fn core_loop(&self) -> TokenStream {
94         self.base.core_loop()
95     }
96 
local_declarations(&self) -> TokenStream97     fn local_declarations(&self) -> TokenStream {
98         self.base.local_declarations()
99     }
100 }
101 
102 impl<'a> OuterFromImpl<'a> for FromFieldImpl<'a> {
trait_path(&self) -> syn::Path103     fn trait_path(&self) -> syn::Path {
104         path!(::darling::FromField)
105     }
106 
trait_bound(&self) -> syn::Path107     fn trait_bound(&self) -> syn::Path {
108         path!(::darling::FromMeta)
109     }
110 
base(&'a self) -> &'a TraitImpl<'a>111     fn base(&'a self) -> &'a TraitImpl<'a> {
112         &self.base
113     }
114 }
115