From 5c218bd5301618f279d34f257ff109488e48f715 Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 10 Jun 2026 19:05:51 +0200 Subject: feat(engine): add discriminants to enum variant reflection --- engine-macros/src/reflection/enum_impl.rs | 55 ++++++++++++++++++++++++++----- engine-reflection/src/lib.rs | 11 +++++++ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/engine-macros/src/reflection/enum_impl.rs b/engine-macros/src/reflection/enum_impl.rs index e4743b6..7f7d25e 100644 --- a/engine-macros/src/reflection/enum_impl.rs +++ b/engine-macros/src/reflection/enum_impl.rs @@ -73,16 +73,13 @@ pub fn generate(input: syn::ItemEnum) -> proc_macro2::TokenStream .unwrap(); } + if !has_c_repr && primitive_repr.is_none() { + panic!("Enums must have a C or primitive representation to derive Reflection"); + } + let mod_content = if is_unit_only { quote! {} } else { - if !has_c_repr && primitive_repr.is_none() { - panic!(concat!( - "Non unit-only enums must have a C or ", - "primitive representation to derive Reflection" - )); - } - let variant_fields_structs = input.variants.iter().map(|variant| { let fields = variant.fields.iter().map(|field| { let field_type = &field.ty; @@ -314,10 +311,52 @@ fn generate_variants<'a>( } }; + let enum_ident = &input.ident; + + let discriminant = match variant.fields { + syn::Fields::Unit => { + quote! { + let mut buf = [0u8; std::mem::size_of::()]; + + let discriminant = #enum_ident::#variant_ident; + + unsafe { + std::ptr::copy_nonoverlapping( + (&raw const discriminant).cast::(), + buf.as_mut_ptr(), + std::mem::size_of::<#enum_ident>(), + ); + } + + buf + } + } + _ => { + quote! { + let mut buf = [0u8; std::mem::size_of::()]; + + let discriminant = #mod_name::Discriminant::#variant_ident; + + unsafe { + std::ptr::copy_nonoverlapping( + (&raw const discriminant).cast::(), + buf.as_mut_ptr(), + std::mem::size_of::<#mod_name::Discriminant>(), + ); + } + + buf + } + } + }; + quote! { #engine_crate_path::reflection::EnumVariant { name: #variant_name, - fields: #fields + fields: #fields, + discriminant: #engine_crate_path::reflection::EnumDiscriminant { + buf: { #discriminant } + } } } }) diff --git a/engine-reflection/src/lib.rs b/engine-reflection/src/lib.rs index 0382598..c884edb 100644 --- a/engine-reflection/src/lib.rs +++ b/engine-reflection/src/lib.rs @@ -89,6 +89,8 @@ pub struct EnumVariant /// The fields of this variant. If `None`, this variant is a unit variant. pub fields: Option, + + pub discriminant: EnumDiscriminant, } #[derive(Debug, Clone)] @@ -104,6 +106,15 @@ pub enum EnumVariantFields }, } +/// The discriminant of a enum variant. +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct EnumDiscriminant +{ + /// This buffer is the size of a u128/i128 because they are the largest possible enum + /// discriminant representations. + pub buf: [u8; size_of::()], +} + #[derive(Debug, Clone)] pub struct Field { -- cgit v1.2.3-18-g5258