diff options
| author | HampusM <hampus@hampusmat.com> | 2026-07-05 00:40:35 +0200 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-07-05 00:40:35 +0200 |
| commit | d10552031890ec09937d1b7a0dea1e68b0daf79a (patch) | |
| tree | d19ccf66e6fbb5246cacee0b553794113295eee8 /engine-macros/src/reflection/enum_impl.rs | |
| parent | 7f529801932fa98967b4dc959d4e9bb79511ff79 (diff) | |
feat(engine): add try_write_new_to fn to enum variant reflection
Diffstat (limited to 'engine-macros/src/reflection/enum_impl.rs')
| -rw-r--r-- | engine-macros/src/reflection/enum_impl.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/engine-macros/src/reflection/enum_impl.rs b/engine-macros/src/reflection/enum_impl.rs index ea83681..baf1732 100644 --- a/engine-macros/src/reflection/enum_impl.rs +++ b/engine-macros/src/reflection/enum_impl.rs @@ -331,12 +331,102 @@ fn generate_variants<'a>( } }; + let variant_field_vars = variant.fields.iter().enumerate().map( + |(variant_field_index, variant_field)| { + let var_ident = match variant_field.ident.as_ref() { + Some(field_ident) => format_ident!("field_{field_ident}"), + None => format_ident!("field_{}", variant_field_index), + }; + + let field_type = &variant_field.ty; + + quote! { + let #var_ident = fields + .next() + .ok_or(EnumVariantWriteNewToError::TooFewFields)? + .downcast::<#field_type>() + .map_err(|_| EnumVariantWriteNewToError::WrongFieldType)?; + } + }, + ); + + let variant_construction = + match &variant.fields { + syn::Fields::Unit => { + let variant_ident = &variant.ident; + + quote! { + Self::#variant_ident + } + } + syn::Fields::Named(named_fields) => { + let variant_ident = &variant.ident; + + let fields = named_fields.named.iter().map(|field| { + let Some(field_ident) = field.ident.as_ref() else { + unreachable!(); + }; + + let field_var_ident = format_ident!("field_{field_ident}"); + + quote! { + #field_ident: *#field_var_ident + } + }); + + quote! { + Self::#variant_ident { + #(#fields),* + } + } + } + syn::Fields::Unnamed(unnamed_fields) => { + let variant_ident = &variant.ident; + + let fields = unnamed_fields.unnamed.iter().enumerate().map( + |(field_index, _)| { + let field_var_ident = format_ident!("field_{field_index}"); + + quote! { + *#field_var_ident + } + }, + ); + + quote! { + Self::#variant_ident( + #(#fields),* + ) + } + } + }; + quote! { #engine_crate_path::reflection::EnumVariant { name: #variant_name, fields: #fields, discriminant: #engine_crate_path::reflection::EnumDiscriminant { buf: { #discriminant } + }, + try_write_new_to: |dst, fields| { + use std::any::Any; + use #engine_crate_path::reflection::EnumVariantWriteNewToError; + + let dst = dst + .downcast_mut() + .ok_or(EnumVariantWriteNewToError::WrongDstType)?; + + #(#variant_field_vars)*; + + let created = #variant_construction; + + if fields.next().is_some() { + return Err(EnumVariantWriteNewToError::TooManyFields); + } + + *dst = created; + + Ok(()) } } } |
