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
|
use crate::reflection::options_attr::OptionsAttr;
mod default_value;
mod enum_impl;
mod field;
mod options_attr;
mod struct_impl;
mod visibility;
pub fn derive(input: proc_macro2::TokenStream) -> proc_macro2::TokenStream
{
let input = syn::parse2::<syn::Item>(input).unwrap();
let options = get_options(&input);
match input {
syn::Item::Struct(input) => struct_impl::generate(input, options),
syn::Item::Enum(input) => enum_impl::generate(input, options),
_ => panic!("Invalid input"),
}
}
pub fn get_options(input: &syn::Item) -> OptionsAttr
{
let (attrs, generic_params) = match &input {
syn::Item::Struct(input) => (input.attrs.as_slice(), &input.generics.params),
syn::Item::Enum(input) => (input.attrs.as_slice(), &input.generics.params),
_ => (
const { &[] }.as_slice(),
&syn::punctuated::Punctuated::<syn::GenericParam, syn::Token![,]>::new(),
),
};
if attrs
.iter()
.filter(|attr| attr.path().is_ident("reflection"))
.count()
> 1
{
panic!("Multiple 'reflection' attributes are not allowed");
}
let options = match attrs
.iter()
.find_map(|attr| {
if attr.path().is_ident("reflection") {
return Some(attr.parse_args::<OptionsAttr>());
}
None
})
.transpose()
{
Ok(attr) => attr.unwrap_or_default(),
Err(err) => {
panic!("{err}");
}
};
if options.impl_with_generics.is_empty() && !generic_params.is_empty() {
panic!(concat!(
"Generic types deriving Reflection must specify which ",
"generics to use in the generated impl(s) using the 'reflection' attribute\n",
"For example: #[reflection(impl_with_generics(<u32, String>, <u8, u16>))]"
));
}
if !options.impl_with_generics.is_empty() && generic_params.is_empty() {
panic!("Specifying 'impl_with_generics' for non-generic types is not allowed");
}
options
}
|