diff options
Diffstat (limited to 'engine-macros/src')
| -rw-r--r-- | engine-macros/src/reflection/enum_impl.rs | 80 |
1 files changed, 79 insertions, 1 deletions
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::<Self>() + .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) + } }, } } }) |
