summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-06-10 19:05:51 +0200
committerHampusM <hampus@hampusmat.com>2026-06-10 19:05:51 +0200
commit5c218bd5301618f279d34f257ff109488e48f715 (patch)
treed21162e1cdaae66e71c134b7a9a85b8e41007ece
parent9e3d3be6a9413d76d230bc0ec48f68f9e051caa0 (diff)
feat(engine): add discriminants to enum variant reflection
-rw-r--r--engine-macros/src/reflection/enum_impl.rs55
-rw-r--r--engine-reflection/src/lib.rs11
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::<i128>()];
+
+ let discriminant = #enum_ident::#variant_ident;
+
+ unsafe {
+ std::ptr::copy_nonoverlapping(
+ (&raw const discriminant).cast::<u8>(),
+ buf.as_mut_ptr(),
+ std::mem::size_of::<#enum_ident>(),
+ );
+ }
+
+ buf
+ }
+ }
+ _ => {
+ quote! {
+ let mut buf = [0u8; std::mem::size_of::<i128>()];
+
+ let discriminant = #mod_name::Discriminant::#variant_ident;
+
+ unsafe {
+ std::ptr::copy_nonoverlapping(
+ (&raw const discriminant).cast::<u8>(),
+ 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<EnumVariantFields>,
+
+ 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::<u128>()],
+}
+
#[derive(Debug, Clone)]
pub struct Field
{