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
use proc_macro::{Span, TokenStream};
use syn::{parse_macro_input, Attribute, Result};
mod fast;
mod verbose;
#[proc_macro_derive(CheckVerbose, attributes(range, filter, fallback))]
pub fn derive_range_checker_verbose(input: TokenStream) -> TokenStream {
verbose::derive_range_checker(parse_macro_input!(input))
.unwrap_or_else(|err| err.to_compile_error())
.into()
}
#[proc_macro_derive(Check, attributes(range, filter, fallback))]
pub fn derive_range_checker(input: TokenStream) -> TokenStream {
fast::derive_range_checker(parse_macro_input!(input))
.unwrap_or_else(|err| err.to_compile_error())
.into()
}
pub(crate) fn extract_attributes(
attrs: Vec<Attribute>,
) -> Result<(
Vec<syn::ExprRange>,
Vec<syn::ExprClosure>,
Vec<syn::Lit>,
Vec<syn::ExprClosure>,
)> {
let mut range_attrs = vec![];
let mut filter_attrs = vec![];
let mut fallback_lit_attrs = vec![];
let mut fallback_closure_attrs = vec![];
for attr in attrs {
match attr
.path
.get_ident()
.map(|ident| ident.to_string())
.unwrap_or_default()
.as_str()
{
"range" => range_attrs.push(attr.parse_args::<syn::ExprRange>()?),
"filter" => filter_attrs.push(attr.parse_args::<syn::ExprClosure>()?),
"fallback" => {
if fallback_lit_attrs.len() + fallback_closure_attrs.len() != 0 {
return Err(syn::Error::new(
Span::call_site().into(),
"multiple fallback attributes is not allowed",
));
}
let lit = attr.parse_args::<syn::Lit>();
let closure = attr.parse_args::<syn::ExprClosure>();
if let Err(mut e_closure) = closure {
if let Err(e_lit) = lit {
e_closure.combine(e_lit);
return Err(e_closure);
} else if let Ok(lit) = lit {
fallback_lit_attrs.push(lit);
}
} else if let Ok(closure) = closure {
fallback_closure_attrs.push(closure);
}
}
_ => unreachable!(),
}
}
Ok((
range_attrs,
filter_attrs,
fallback_lit_attrs,
fallback_closure_attrs,
))
}