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.rs68
1 files changed, 68 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..b1adea5
--- /dev/null
+++ b/engine-macros/src/reflection/struct_impl.rs
@@ -0,0 +1,68 @@
+use quote::quote;
+
+use crate::reflection::field::{generate as generate_field, ReflectionFieldGenOptions};
+use crate::util::{find_engine_crate_path, syn_path, SynPathExt};
+
+pub fn generate(input: syn::ItemStruct) -> proc_macro2::TokenStream
+{
+ let engine_crate_path = find_engine_crate_path().unwrap();
+
+ let input_ident = input.ident;
+
+ 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
+ .into_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) }
+ }
+ },
+ type_reflection_optional,
+ },
+ )
+ });
+
+ quote! {
+ unsafe impl #impl_generics #engine_crate_path::reflection::Reflection for
+ #input_ident #type_generics #where_clause
+ {
+ const TYPE_REFLECTION: &#engine_crate_path::reflection::Type =
+ &const {
+ #engine_crate_path::reflection::Type::Struct(
+ #engine_crate_path::reflection::Struct {
+ fields: &[
+ #(#fields),*
+ ]
+ }
+ )
+ };
+ }
+ }
+}