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.rs97
1 files changed, 97 insertions, 0 deletions
diff --git a/engine-macros/src/reflection/struct_impl.rs b/engine-macros/src/reflection/struct_impl.rs
new file mode 100644
index 0000000..58046fe
--- /dev/null
+++ b/engine-macros/src/reflection/struct_impl.rs
@@ -0,0 +1,97 @@
+use quote::quote;
+
+use crate::reflection::default_value::gen_get_default_value_fn;
+use crate::reflection::field::{generate as generate_field, ReflectionFieldGenOptions};
+use crate::reflection::options_attr::OptionsAttr;
+use crate::util::find_engine_crate_path;
+
+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);
+ }
+
+ let impls = options
+ .impl_with_generics
+ .into_iter()
+ .map(|generic_args| gen_impl(&input, Some(&generic_args), &engine_crate_path));
+
+ quote! {
+ #(#impls)*
+ }
+}
+
+fn gen_impl(
+ input: &syn::ItemStruct,
+ generic_args: Option<&syn::AngleBracketedGenericArguments>,
+ engine_crate_path: &syn::Path,
+) -> proc_macro2::TokenStream
+{
+ let fields = input.fields.iter().enumerate().map(|(field_index, field)| {
+ generate_field(
+ &field,
+ field_index,
+ &engine_crate_path,
+ ReflectionFieldGenOptions {
+ field_vis_override: None,
+ gen_get_byte_offset: &|field| {
+ if let Some(field_ident) = &field.ident {
+ quote! { std::mem::offset_of!(Self, #field_ident) }
+ } else {
+ quote! { std::mem::offset_of!(Self, #field_index) }
+ }
+ },
+ },
+ )
+ });
+
+ let get_default_value_fn = gen_get_default_value_fn(&input.ident, generic_args);
+
+ let input_ident = &input.ident;
+
+ let generics_type_aliases = input
+ .generics
+ .type_params()
+ .zip(
+ generic_args
+ .iter()
+ .map(|generic_args| &generic_args.args)
+ .flatten()
+ .flat_map(|generic_arg| match generic_arg {
+ syn::GenericArgument::Type(ty) => Some(ty),
+ _ => None,
+ }),
+ )
+ .map(|(type_param, generic_arg_type)| {
+ let type_param_ident = &type_param.ident;
+
+ quote! {
+ type #type_param_ident = #generic_arg_type;
+ }
+ });
+
+ quote! {
+ unsafe impl #engine_crate_path::reflection::Reflection for
+ #input_ident #generic_args
+ {
+ const TYPE_REFLECTION: &#engine_crate_path::reflection::Type =
+ &const {
+ #(#generics_type_aliases)*
+
+ #engine_crate_path::reflection::Type::Struct(
+ #engine_crate_path::reflection::Struct {
+ fields: &[
+ #(#fields),*
+ ],
+ get_default_value: || {
+ #get_default_value_fn
+ }
+ }
+ )
+ };
+ }
+ }
+}