• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use proc_macro2::TokenStream;
2 use quote::{quote, ToTokens};
3 
4 use crate::{
5     ast::Data,
6     codegen::{ExtractAttribute, OuterFromImpl, TraitImpl},
7     util::PathList,
8 };
9 
10 use super::ForwardAttrs;
11 
12 pub struct FromAttributesImpl<'a> {
13     pub base: TraitImpl<'a>,
14     pub attr_names: &'a PathList,
15     pub forward_attrs: ForwardAttrs<'a>,
16 }
17 
18 impl ToTokens for FromAttributesImpl<'_> {
to_tokens(&self, tokens: &mut TokenStream)19     fn to_tokens(&self, tokens: &mut TokenStream) {
20         let ty_ident = self.base.ident;
21         let input = self.param_name();
22         let post_transform = self.base.post_transform_call();
23 
24         if let Data::Struct(ref data) = self.base.data {
25             if data.is_newtype() {
26                 self.wrap(
27                     quote! {
28                         fn from_attributes(#input: &[::darling::export::syn::Attribute]) -> ::darling::Result<Self> {
29                             ::darling::export::Ok(
30                                 #ty_ident(::darling::FromAttributes::from_attributes(#input)?)
31                             ) #post_transform
32                         }
33                     },
34                     tokens,
35                 );
36 
37                 return;
38             }
39         }
40 
41         let passed_attrs = self.forward_attrs.as_initializer();
42         let inits = self.base.initializers();
43         let default = self.base.fallback_decl();
44 
45         let grab_attrs = self.extractor();
46 
47         let declare_errors = self.base.declare_errors();
48         let require_fields = self.base.require_fields();
49         let check_errors = self.base.check_errors();
50 
51         self.wrap(
52             quote! {
53                 fn from_attributes(#input: &[::darling::export::syn::Attribute]) -> ::darling::Result<Self> {
54                     #declare_errors
55 
56                     #grab_attrs
57 
58                     #require_fields
59 
60                     #check_errors
61 
62                     #default
63 
64                     ::darling::export::Ok(#ty_ident {
65                         #passed_attrs
66                         #inits
67                     }) #post_transform
68                 }
69             },
70             tokens,
71         );
72     }
73 }
74 
75 impl<'a> ExtractAttribute for FromAttributesImpl<'a> {
local_declarations(&self) -> TokenStream76     fn local_declarations(&self) -> TokenStream {
77         self.base.local_declarations()
78     }
79 
attr_names(&self) -> &PathList80     fn attr_names(&self) -> &PathList {
81         self.attr_names
82     }
83 
forward_attrs(&self) -> &super::ForwardAttrs<'_>84     fn forward_attrs(&self) -> &super::ForwardAttrs<'_> {
85         &self.forward_attrs
86     }
87 
param_name(&self) -> TokenStream88     fn param_name(&self) -> TokenStream {
89         quote!(__di)
90     }
91 
attrs_accessor(&self) -> TokenStream92     fn attrs_accessor(&self) -> TokenStream {
93         self.param_name()
94     }
95 
core_loop(&self) -> TokenStream96     fn core_loop(&self) -> TokenStream {
97         self.base.core_loop()
98     }
99 }
100 
101 impl<'a> OuterFromImpl<'a> for FromAttributesImpl<'a> {
trait_path(&self) -> syn::Path102     fn trait_path(&self) -> syn::Path {
103         path!(::darling::FromAttributes)
104     }
105 
trait_bound(&self) -> syn::Path106     fn trait_bound(&self) -> syn::Path {
107         path!(::darling::FromMeta)
108     }
109 
base(&'a self) -> &'a TraitImpl<'a>110     fn base(&'a self) -> &'a TraitImpl<'a> {
111         &self.base
112     }
113 }
114