From 548cfe53130537dfee33d143e8a563879e30e1a2 Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 8 Jul 2026 00:42:44 +0200 Subject: feat(engine): add try_get_field_mut fn to enum variant reflection --- engine-macros/src/reflection/enum_impl.rs | 80 ++++++++++++++++++++++++++++++- 1 file changed, 79 insertions(+), 1 deletion(-) (limited to 'engine-macros/src') diff --git a/engine-macros/src/reflection/enum_impl.rs b/engine-macros/src/reflection/enum_impl.rs index 4e27c2b..b637d9f 100644 --- a/engine-macros/src/reflection/enum_impl.rs +++ b/engine-macros/src/reflection/enum_impl.rs @@ -273,6 +273,61 @@ fn generate_variants<'a>( } }; + let variant_ident = &variant.ident; + + let variant_pattern = match &variant.fields { + syn::Fields::Unit => quote! { Self::#variant_ident }, + syn::Fields::Named(syn::FieldsNamed { named: named_fields, .. }) => { + let field_idents = named_fields.iter().map(|field| { + let Some(field_ident) = &field.ident else { + unreachable!(); + }; + + field_ident + }); + + quote! { Self::#variant_ident { #(#field_idents),* } } + } + syn::Fields::Unnamed(syn::FieldsUnnamed { + unnamed: unnamed_fields, .. + }) => { + let field_idents = unnamed_fields + .iter() + .enumerate() + .map(|(field_index, _)| format_ident!("field_{field_index}")); + + quote! { Self::#variant_ident(#(#field_idents),*) } + } + }; + + let field_index_match_arms = match &variant.fields { + syn::Fields::Unit => quote! {}, + syn::Fields::Named(syn::FieldsNamed { named: named_fields, .. }) => { + let match_arms = + named_fields.iter().enumerate().map(|(field_index, field)| { + let Some(field_ident) = &field.ident else { + unreachable!(); + }; + + quote! { #field_index => { #field_ident } } + }); + + quote! { #(#match_arms)* } + } + syn::Fields::Unnamed(syn::FieldsUnnamed { + unnamed: unnamed_fields, .. + }) => { + let match_arms = + unnamed_fields.iter().enumerate().map(|(field_index, _)| { + let field_ident = format_ident!("field_{field_index}"); + + quote! { #field_index => { #field_ident } } + }); + + quote! { #(#match_arms)* } + } + }; + quote! { #engine_crate_path::reflection::EnumVariant { name: #variant_name, @@ -296,7 +351,30 @@ fn generate_variants<'a>( *dst = created; Ok(()) - } + }, + try_get_field_mut: |target, field_index| { { + #![allow(unreachable_code)] + + use std::any::Any; + use #engine_crate_path::reflection::EnumVariantGetFieldError; + + let target = target + .downcast_mut::() + .ok_or(EnumVariantGetFieldError::WrongTargetType)?; + + let #variant_pattern = target else { + return Err(EnumVariantGetFieldError::WrongTargetVariant); + }; + + let field: &mut dyn Any = match field_index { + #field_index_match_arms + _ => { + return Err(EnumVariantGetFieldError::FieldIndexOutOfBounds); + } + }; + + Ok(field) + } }, } } }) -- cgit v1.2.3-18-g5258