summaryrefslogtreecommitdiff
path: root/engine-macros/src/reflection.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine-macros/src/reflection.rs')
-rw-r--r--engine-macros/src/reflection.rs73
1 files changed, 73 insertions, 0 deletions
diff --git a/engine-macros/src/reflection.rs b/engine-macros/src/reflection.rs
new file mode 100644
index 0000000..2180084
--- /dev/null
+++ b/engine-macros/src/reflection.rs
@@ -0,0 +1,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
+}