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 } } ) }; } } }