summaryrefslogtreecommitdiff
path: root/engine-macros/src/reflection/struct_impl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine-macros/src/reflection/struct_impl.rs')
-rw-r--r--engine-macros/src/reflection/struct_impl.rs165
1 files changed, 94 insertions, 71 deletions
diff --git a/engine-macros/src/reflection/struct_impl.rs b/engine-macros/src/reflection/struct_impl.rs
index 0ba426d..27d62ba 100644
--- a/engine-macros/src/reflection/struct_impl.rs
+++ b/engine-macros/src/reflection/struct_impl.rs
@@ -1,3 +1,4 @@
+use proc_macro2::TokenStream;
use quote::{format_ident, quote};
use crate::reflection::default_value::gen_get_default_value_fn;
@@ -5,19 +6,21 @@ use crate::reflection::field::{generate as generate_field, ReflectionFieldGenOpt
use crate::reflection::options_attr::OptionsAttr;
use crate::util::find_engine_crate_path;
-pub fn generate(input: syn::ItemStruct, options: OptionsAttr)
- -> proc_macro2::TokenStream
+pub fn generate(
+ input: &syn::ItemStruct,
+ options: &OptionsAttr,
+) -> proc_macro2::TokenStream
{
let engine_crate_path = find_engine_crate_path().unwrap();
if input.generics.params.is_empty() {
- return gen_impl(&input, None, &engine_crate_path);
+ return gen_impl(input, None, &engine_crate_path);
}
let impls = options
.impl_with_generics
- .into_iter()
- .map(|generic_args| gen_impl(&input, Some(&generic_args), &engine_crate_path));
+ .iter()
+ .map(|generic_args| gen_impl(input, Some(generic_args), &engine_crate_path));
quote! {
#(#impls)*
@@ -32,10 +35,10 @@ fn gen_impl(
{
let fields = input.fields.iter().enumerate().map(|(field_index, field)| {
generate_field(
- &field,
+ field,
field_index,
- &engine_crate_path,
- ReflectionFieldGenOptions {
+ engine_crate_path,
+ &ReflectionFieldGenOptions {
field_vis_override: None,
gen_get_byte_offset: &|field| {
if let Some(field_ident) = &field.ident {
@@ -58,9 +61,8 @@ fn gen_impl(
.zip(
generic_args
.iter()
- .map(|generic_args| &generic_args.args)
- .flatten()
- .flat_map(|generic_arg| match generic_arg {
+ .flat_map(|generic_args| &generic_args.args)
+ .filter_map(|generic_arg| match generic_arg {
syn::GenericArgument::Type(ty) => Some(ty),
_ => None,
}),
@@ -68,11 +70,52 @@ fn gen_impl(
.map(|(type_param, generic_arg_type)| {
let type_param_ident = &type_param.ident;
- quote! {
- type #type_param_ident = #generic_arg_type;
- }
+ quote! { type #type_param_ident = #generic_arg_type; }
});
+ let TryGetFieldFns {
+ immutable: try_get_field_immutable_fn,
+ mutable: try_get_field_mutable_fn,
+ } = gen_try_get_field_functions(input);
+
+ quote! {
+ unsafe impl #engine_crate_path::reflection::Reflection for
+ #input_ident #generic_args
+ {
+ const TYPE_REFLECTION: &#engine_crate_path::reflection::Type =
+ &const {
+ use std::any::Any;
+
+ use #engine_crate_path::reflection::GetError;
+
+ #(#generics_type_aliases)*
+
+ #engine_crate_path::reflection::Type::Struct(
+ #engine_crate_path::reflection::Struct {
+ fields: &[
+ #(#fields),*
+ ],
+ get_default_value: || {
+ #get_default_value_fn
+ },
+ cast_dyn_any: |ptr| ptr.cast::<Self>(),
+ try_get_field: #try_get_field_immutable_fn,
+ try_get_field_mut: #try_get_field_mutable_fn,
+ }
+ )
+ };
+ }
+ }
+}
+
+struct TryGetFieldFns
+{
+ immutable: TokenStream,
+ mutable: TokenStream,
+}
+
+fn gen_try_get_field_functions(input: &syn::ItemStruct) -> TryGetFieldFns
+{
let struct_pattern = match &input.fields {
syn::Fields::Unit => quote! { Self },
syn::Fields::Named(syn::FieldsNamed { named: named_fields, .. }) => {
@@ -121,66 +164,46 @@ fn gen_impl(
}
};
- quote! {
- unsafe impl #engine_crate_path::reflection::Reflection for
- #input_ident #generic_args
- {
- const TYPE_REFLECTION: &#engine_crate_path::reflection::Type =
- &const {
- use std::any::Any;
+ TryGetFieldFns {
+ immutable: quote! {
+ |target, field_index| { {
+ #![allow(unreachable_code)]
- use #engine_crate_path::reflection::GetError;
+ let target = target
+ .downcast_ref::<Self>()
+ .ok_or(GetError::WrongTargetType)?;
- #(#generics_type_aliases)*
+ let #struct_pattern = target;
- #engine_crate_path::reflection::Type::Struct(
- #engine_crate_path::reflection::Struct {
- fields: &[
- #(#fields),*
- ],
- get_default_value: || {
- #get_default_value_fn
- },
- cast_dyn_any: |ptr| ptr.cast::<Self>(),
- try_get_field: |target, field_index| { {
- #![allow(unreachable_code)]
-
- let target = target
- .downcast_ref::<Self>()
- .ok_or(GetError::WrongTargetType)?;
-
- let #struct_pattern = target;
-
- let field: &dyn Any = match field_index {
- #field_index_match_arms
- _ => {
- return Err(GetError::IndexOutOfBounds);
- }
- };
-
- Ok(field)
- } },
- try_get_field_mut: |target, field_index| { {
- #![allow(unreachable_code)]
-
- let target = target
- .downcast_mut::<Self>()
- .ok_or(GetError::WrongTargetType)?;
-
- let #struct_pattern = target;
-
- let field: &mut dyn Any = match field_index {
- #field_index_match_arms
- _ => {
- return Err(GetError::IndexOutOfBounds);
- }
- };
-
- Ok(field)
- } },
- }
- )
+ let field: &dyn Any = match field_index {
+ #field_index_match_arms
+ _ => {
+ return Err(GetError::IndexOutOfBounds);
+ }
};
- }
+
+ Ok(field)
+ } }
+ },
+ mutable: quote! {
+ |target, field_index| { {
+ #![allow(unreachable_code)]
+
+ let target = target
+ .downcast_mut::<Self>()
+ .ok_or(GetError::WrongTargetType)?;
+
+ let #struct_pattern = target;
+
+ let field: &mut dyn Any = match field_index {
+ #field_index_match_arms
+ _ => {
+ return Err(GetError::IndexOutOfBounds);
+ }
+ };
+
+ Ok(field)
+ } }
+ },
}
}