1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use quote::Tokens;
mod default_expr;
mod error;
mod field;
mod from_meta_impl;
mod from_derive_impl;
mod from_field;
mod from_type_param;
mod from_variant_impl;
mod outer_from_impl;
mod trait_impl;
mod variant;
mod variant_data;
pub use self::default_expr::DefaultExpression;
pub use self::field::Field;
pub use self::from_meta_impl::FromMetaImpl;
pub use self::from_derive_impl::FromDeriveInputImpl;
pub use self::from_field::FromFieldImpl;
pub use self::from_type_param::FromTypeParamImpl;
pub use self::from_variant_impl::FromVariantImpl;
pub use self::outer_from_impl::OuterFromImpl;
pub use self::trait_impl::TraitImpl;
pub use self::variant::Variant;
pub use self::variant_data::FieldsGen;
use options::ForwardAttrs;
pub trait ExtractAttribute {
fn local_declarations(&self) -> Tokens;
fn immutable_declarations(&self) -> Tokens;
fn attr_names(&self) -> &[&str];
fn forwarded_attrs(&self) -> Option<&ForwardAttrs>;
fn param_name(&self) -> Tokens;
fn core_loop(&self) -> Tokens;
fn declarations(&self) -> Tokens {
if !self.attr_names().is_empty() {
self.local_declarations()
} else {
self.immutable_declarations()
}
}
fn extractor(&self) -> Tokens {
let declarations = self.declarations();
let will_parse_any = !self.attr_names().is_empty();
let will_fwd_any = self.forwarded_attrs()
.map(|fa| !fa.is_empty())
.unwrap_or_default();
if !(will_parse_any || will_fwd_any) {
return quote! {
#declarations
};
}
let input = self.param_name();
let parse_handled = if will_parse_any {
let attr_names = self.attr_names();
let core_loop = self.core_loop();
quote!(
#(#attr_names)|* => {
if let Some(::syn::Meta::List(ref __data)) = __attr.interpret_meta() {
let __items = &__data.nested;
#core_loop
} else {
continue
}
}
)
} else {
quote!()
};
let forward_unhandled = if will_fwd_any {
forwards_to_local(self.forwarded_attrs().unwrap())
} else {
quote!(_ => continue)
};
quote!(
#declarations
let mut __fwd_attrs: ::darling::export::Vec<::syn::Attribute> = vec![];
for __attr in &#input.attrs {
match __attr.path.segments.iter().map(|s| s.ident.as_ref()).collect::<Vec<&str>>().join("::").as_str() {
#parse_handled
#forward_unhandled
}
}
)
}
}
fn forwards_to_local(behavior: &ForwardAttrs) -> Tokens {
let push_command = quote!(__fwd_attrs.push(__attr.clone()));
match *behavior {
ForwardAttrs::All => quote!(_ => #push_command),
ForwardAttrs::Only(ref idents) => {
let names = idents.as_strs();
quote!(
#(#names)|* => #push_command,
_ => continue,
)
}
}
}