diff options
Diffstat (limited to 'engine-macros/src/reflection.rs')
| -rw-r--r-- | engine-macros/src/reflection.rs | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/engine-macros/src/reflection.rs b/engine-macros/src/reflection.rs new file mode 100644 index 0000000..ad1df04 --- /dev/null +++ b/engine-macros/src/reflection.rs @@ -0,0 +1,75 @@ +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}"); + } + }; + + assert!( + !options.impl_with_generics.is_empty() || generic_params.is_empty(), + 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>))]" + ) + ); + + assert!( + options.impl_with_generics.is_empty() || !generic_params.is_empty(), + "Specifying 'impl_with_generics' for non-generic types is not allowed" + ); + + options +} |
