diff options
| -rw-r--r-- | engine-macros/src/reflection/enum_impl.rs | 129 | ||||
| -rw-r--r-- | engine-macros/src/reflection/struct_impl.rs | 21 | ||||
| -rw-r--r-- | engine-macros/src/util.rs | 24 |
3 files changed, 114 insertions, 60 deletions
diff --git a/engine-macros/src/reflection/enum_impl.rs b/engine-macros/src/reflection/enum_impl.rs index 1760f40..a01ed8b 100644 --- a/engine-macros/src/reflection/enum_impl.rs +++ b/engine-macros/src/reflection/enum_impl.rs @@ -1,7 +1,7 @@ use quote::{format_ident, quote, ToTokens}; use crate::reflection::field::{generate as generate_field, ReflectionFieldGenOptions}; -use crate::util::find_engine_crate_path; +use crate::util::{find_engine_crate_path, syn_path, SynPathExt}; const PRIMITIVE_REPRS: &[&'static str] = &[ "u8", "u16", "u32", "u64", "u128", "usize", "i8", "i16", "i32", "i64", "i128", @@ -14,7 +14,20 @@ pub fn generate(input: syn::ItemEnum) -> proc_macro2::TokenStream let input_ident = &input.ident; - let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl(); + let mut generics = input.generics; + + for type_param in generics.type_params_mut() { + type_param + .bounds + .push(syn::TypeParamBound::Trait(syn::TraitBound { + paren_token: None, + modifier: syn::TraitBoundModifier::None, + lifetimes: None, + path: engine_crate_path.join(syn_path!(reflection::Reflection)), + })); + } + + let (impl_generics, type_generics, where_clause) = generics.split_for_impl(); let variant_lookup_match_arms = input.variants.iter().enumerate().map(|(index, variant)| { @@ -80,22 +93,22 @@ pub fn generate(input: syn::ItemEnum) -> proc_macro2::TokenStream let mod_content = if is_unit_only { quote! {} } else { - let variant_fields_structs = input.variants.iter().map(|variant| { - let fields = variant.fields.iter().map(|field| { - let field_type = &field.ty; - - if let Some(field_ident) = &field.ident { - quote! { pub #field_ident: #field_type } - } else { - quote! { pub #field_type } - } - }); + let variant_fields_structs = + input.variants.iter().map(|variant| { + let fields = variant.fields.iter().map(|field| { + let field_type = &field.ty; + + if let Some(field_ident) = &field.ident { + quote! { pub #field_ident: #field_type } + } else { + quote! { pub #field_type } + } + }); - let ident = format_ident!("VariantFields{}", variant.ident); + let ident = format_ident!("VariantFields{}", variant.ident); - let generics_phantom_data_elems = - input.generics.params.iter().filter_map(|generic_param| { - match generic_param { + let generics_phantom_data_elems = generics.params.iter().filter_map( + |generic_param| match generic_param { syn::GenericParam::Type(type_param) => { Some(type_param.ident.clone().into_token_stream()) } @@ -103,38 +116,38 @@ pub fn generate(input: syn::ItemEnum) -> proc_macro2::TokenStream unimplemented!(); } syn::GenericParam::Const(_const_param) => None, - } - }); + }, + ); - let generics_phantom_data = quote! { - std::marker::PhantomData<(#(#generics_phantom_data_elems),*)> - }; + let generics_phantom_data = quote! { + std::marker::PhantomData<(#(#generics_phantom_data_elems),*)> + }; - match variant.fields { - syn::Fields::Named(_) => quote! { - #[repr(C)] - pub struct #ident #impl_generics - #where_clause - { - #(#fields,)* - _pd: #generics_phantom_data - } - }, - syn::Fields::Unnamed(_) => quote! { - #[repr(C)] - pub struct #ident #impl_generics ( - #(#fields,)* - #generics_phantom_data - ) - #where_clause; - }, - syn::Fields::Unit => quote! { - #[repr(C)] - pub struct #ident #impl_generics (#generics_phantom_data) - #where_clause; - }, - } - }); + match variant.fields { + syn::Fields::Named(_) => quote! { + #[repr(C)] + pub struct #ident #impl_generics + #where_clause + { + #(#fields,)* + _pd: #generics_phantom_data + } + }, + syn::Fields::Unnamed(_) => quote! { + #[repr(C)] + pub struct #ident #impl_generics ( + #(#fields,)* + #generics_phantom_data + ) + #where_clause; + }, + syn::Fields::Unit => quote! { + #[repr(C)] + pub struct #ident #impl_generics (#generics_phantom_data) + #where_clause; + }, + } + }); let fields_union_fields = input.variants.iter().map(|variant| { let variant_ident = &variant.ident; @@ -197,7 +210,13 @@ pub fn generate(input: syn::ItemEnum) -> proc_macro2::TokenStream } }; - let variants = generate_variants(&input, is_unit_only, &engine_crate_path); + let variants = generate_variants( + input_ident, + &input.variants, + &generics, + is_unit_only, + &engine_crate_path, + ); quote! { #[doc(hidden)] @@ -240,16 +259,18 @@ pub fn generate(input: syn::ItemEnum) -> proc_macro2::TokenStream } fn generate_variants<'a>( - input: &'a syn::ItemEnum, + input_ident: &proc_macro2::Ident, + input_variants: &'a syn::punctuated::Punctuated<syn::Variant, syn::Token![,]>, + input_generics: &'a syn::Generics, is_unit_only: bool, engine_crate_path: &'a syn::Path, ) -> impl Iterator<Item = proc_macro2::TokenStream> + use<'a> { - let mod_name = format_ident!("__engine_private_{}", input.ident); + let mod_name = format_ident!("__engine_private_{input_ident}"); - let (_, type_generics, _) = input.generics.split_for_impl(); + let (_, type_generics, _) = input_generics.split_for_impl(); - input.variants.iter().map(move |variant| { + input_variants.iter().map(move |variant| { let variant_name = syn::LitStr::new(&variant.ident.to_string(), variant.ident.span()); @@ -288,8 +309,7 @@ fn generate_variants<'a>( unreachable!(); } }, - type_reflection_optional: input - .generics + type_reflection_optional: input_generics .params .is_empty(), }, @@ -337,8 +357,7 @@ fn generate_variants<'a>( } } }, - type_reflection_optional: input - .generics + type_reflection_optional: input_generics .params .is_empty(), }, diff --git a/engine-macros/src/reflection/struct_impl.rs b/engine-macros/src/reflection/struct_impl.rs index 2a271e0..b1adea5 100644 --- a/engine-macros/src/reflection/struct_impl.rs +++ b/engine-macros/src/reflection/struct_impl.rs @@ -1,7 +1,7 @@ use quote::quote; use crate::reflection::field::{generate as generate_field, ReflectionFieldGenOptions}; -use crate::util::find_engine_crate_path; +use crate::util::{find_engine_crate_path, syn_path, SynPathExt}; pub fn generate(input: syn::ItemStruct) -> proc_macro2::TokenStream { @@ -9,7 +9,22 @@ pub fn generate(input: syn::ItemStruct) -> proc_macro2::TokenStream let input_ident = input.ident; - let (impl_generics, type_generics, where_clause) = input.generics.split_for_impl(); + let type_reflection_optional = input.generics.params.is_empty(); + + let mut generics = input.generics; + + for type_param in generics.type_params_mut() { + type_param + .bounds + .push(syn::TypeParamBound::Trait(syn::TraitBound { + paren_token: None, + modifier: syn::TraitBoundModifier::None, + lifetimes: None, + path: engine_crate_path.join(syn_path!(reflection::Reflection)), + })); + } + + let (impl_generics, type_generics, where_clause) = generics.split_for_impl(); let fields = input .fields @@ -29,7 +44,7 @@ pub fn generate(input: syn::ItemStruct) -> proc_macro2::TokenStream quote! { std::mem::offset_of!(Self, #field_index) } } }, - type_reflection_optional: input.generics.params.is_empty(), + type_reflection_optional, }, ) }); diff --git a/engine-macros/src/util.rs b/engine-macros/src/util.rs index 515b066..327c517 100644 --- a/engine-macros/src/util.rs +++ b/engine-macros/src/util.rs @@ -7,8 +7,8 @@ macro_rules! syn_path { ::syn::Path { leading_colon: None, segments: ::syn::punctuated::Punctuated::from_iter([ - syn_path_segment!($first_segment), - $(syn_path_segment!($segment),)* + $crate::util::syn_path_segment!($first_segment), + $($crate::util::syn_path_segment!($segment),)* ]) } }; @@ -26,6 +26,9 @@ macro_rules! syn_path_segment { }; } +pub(crate) use syn_path; +pub(crate) use syn_path_segment; + pub fn find_engine_crate_path() -> Option<syn::Path> { let cargo_crate_name = std::env::var("CARGO_CRATE_NAME").ok()?; @@ -63,3 +66,20 @@ pub fn syn_path_to_string(path: &syn::Path) -> String output } + +pub trait SynPathExt +{ + fn join(&self, tail: Self) -> Self; +} + +impl SynPathExt for syn::Path +{ + fn join(&self, tail: Self) -> Self + { + let mut new = self.clone(); + + new.segments.extend(tail.segments); + + new + } +} |
