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
use proc_macro2::Span;
use syn::{AttributeArgs, NestedMeta};
pub(crate) struct Args {
pub(crate) path: syn::LitStr,
pub(crate) guards: Vec<syn::Path>,
pub(crate) wrappers: Vec<syn::Path>,
}
impl Args {
pub(crate) fn new(args: AttributeArgs) -> syn::Result<Self> {
let mut path = None;
let mut guards = Vec::new();
let mut wrappers = Vec::new();
for arg in args {
match arg {
NestedMeta::Lit(syn::Lit::Str(lit)) => match path {
None => {
path = Some(lit);
}
_ => {
return Err(syn::Error::new_spanned(
lit,
"Multiple paths specified! Should be only one!",
));
}
},
NestedMeta::Meta(syn::Meta::List(nv)) => {
if nv.path.is_ident("guard") {
for guard in nv.nested {
if let syn::NestedMeta::Meta(syn::Meta::Path(path)) = guard {
guards.push(path);
} else {
return Err(syn::Error::new_spanned(
nv.path,
"Attribute guard expects a path!",
));
}
}
} else if nv.path.is_ident("wrap") {
for wrapper in nv.nested {
if let syn::NestedMeta::Meta(syn::Meta::Path(path)) = wrapper {
wrappers.push(path);
} else {
return Err(syn::Error::new_spanned(
nv.path,
"Attribute wrap expects type",
));
}
}
}
}
NestedMeta::Meta(syn::Meta::NameValue(nv)) => {
if nv.path.is_ident("path") {
if let syn::Lit::Str(lit) = nv.lit {
path = Some(lit);
} else {
return Err(syn::Error::new_spanned(
nv.lit,
"Path expects literal string.",
));
}
} else {
return Err(syn::Error::new_spanned(
nv.path,
"Unknown attribute key is specified.",
));
}
}
arg => {
return Err(syn::Error::new_spanned(arg, "Unknown attribute."));
}
}
}
Ok(Args {
path: path.unwrap_or_else(|| syn::LitStr::new("/", proc_macro2::Span::call_site())),
guards,
wrappers,
})
}
}
impl Default for Args {
fn default() -> Self {
Self {
path: syn::LitStr::new("", Span::call_site()),
guards: Vec::new(),
wrappers: Vec::new(),
}
}
}