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