diff options
Diffstat (limited to 'engine-macros/src/reflection.rs')
| -rw-r--r-- | engine-macros/src/reflection.rs | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/engine-macros/src/reflection.rs b/engine-macros/src/reflection.rs index 5d40e0c..2180084 100644 --- a/engine-macros/src/reflection.rs +++ b/engine-macros/src/reflection.rs @@ -1,6 +1,9 @@ +use crate::reflection::options_attr::OptionsAttr; + mod default_value; mod enum_impl; mod field; +mod options_attr; mod struct_impl; mod visibility; @@ -8,9 +11,63 @@ 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), - syn::Item::Enum(input) => enum_impl::generate(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 +} |
