1
- use crate :: fq_std:: FQDefault ;
1
+ use crate :: derive_data:: StructField ;
2
+ use crate :: field_attributes:: DefaultBehavior ;
3
+ use crate :: fq_std:: { FQDefault , FQOption } ;
2
4
use crate :: {
3
5
derive_data:: { EnumVariantFields , ReflectEnum } ,
4
6
utility:: ident_or_index,
5
7
} ;
6
8
use proc_macro2:: Ident ;
7
9
use quote:: { quote, ToTokens } ;
10
+ use syn:: Member ;
8
11
9
12
/// Contains all data needed to construct all variants within an enum.
10
13
pub ( crate ) struct EnumVariantConstructors {
@@ -30,7 +33,7 @@ pub(crate) fn get_variant_constructors(
30
33
let name = ident. to_string ( ) ;
31
34
let variant_constructor = reflect_enum. get_unit ( ident) ;
32
35
33
- let fields = match & variant. fields {
36
+ let fields: & [ StructField ] = match & variant. fields {
34
37
EnumVariantFields :: Unit => & [ ] ,
35
38
EnumVariantFields :: Named ( fields) | EnumVariantFields :: Unnamed ( fields) => {
36
39
fields. as_slice ( )
@@ -39,35 +42,59 @@ pub(crate) fn get_variant_constructors(
39
42
let mut reflect_index: usize = 0 ;
40
43
let constructor_fields = fields. iter ( ) . enumerate ( ) . map ( |( declare_index, field) | {
41
44
let field_ident = ident_or_index ( field. data . ident . as_ref ( ) , declare_index) ;
45
+ let field_ty = & field. data . ty ;
46
+
42
47
let field_value = if field. attrs . ignore . is_ignored ( ) {
43
- quote ! { #FQDefault :: default ( ) }
48
+ match & field. attrs . default {
49
+ DefaultBehavior :: Func ( path) => quote ! { #path( ) } ,
50
+ _ => quote ! { #FQDefault :: default ( ) }
51
+ }
44
52
} else {
45
- let error_repr = field. data . ident . as_ref ( ) . map_or_else (
46
- || format ! ( "at index {reflect_index}" ) ,
47
- |name| format ! ( "`{name}`" ) ,
48
- ) ;
49
- let unwrapper = if can_panic {
50
- let type_err_message = format ! (
51
- "the field {error_repr} should be of type `{}`" ,
52
- field. data. ty. to_token_stream( )
53
- ) ;
54
- quote ! ( . expect( #type_err_message) )
53
+ let ( resolve_error, resolve_missing) = if can_panic {
54
+ let field_ref_str = match & field_ident {
55
+ Member :: Named ( ident) => format ! ( "the field `{ident}`" ) ,
56
+ Member :: Unnamed ( index) => format ! ( "the field at index {}" , index. index)
57
+ } ;
58
+ let ty = field. data . ty . to_token_stream ( ) ;
59
+
60
+ let on_error = format ! ( "{field_ref_str} should be of type `{ty}`" ) ;
61
+ let on_missing = format ! ( "{field_ref_str} is required but could not be found" ) ;
62
+
63
+ ( quote ! ( . expect( #on_error) ) , quote ! ( . expect( #on_missing) ) )
55
64
} else {
56
- quote ! ( ?)
65
+ ( quote ! ( ?) , quote ! ( ? ) )
57
66
} ;
67
+
58
68
let field_accessor = match & field. data . ident {
59
69
Some ( ident) => {
60
70
let name = ident. to_string ( ) ;
61
- quote ! ( . field( #name) )
71
+ quote ! ( #ref_value . field( #name) )
62
72
}
63
- None => quote ! ( . field_at( #reflect_index) ) ,
73
+ None => quote ! ( #ref_value . field_at( #reflect_index) ) ,
64
74
} ;
65
75
reflect_index += 1 ;
66
- let missing_field_err_message = format ! ( "the field {error_repr} was not declared" ) ;
67
- let accessor = quote ! ( #field_accessor . expect( #missing_field_err_message) ) ;
68
- quote ! {
69
- #bevy_reflect_path:: FromReflect :: from_reflect( #ref_value #accessor)
70
- #unwrapper
76
+
77
+ match & field. attrs . default {
78
+ DefaultBehavior :: Func ( path) => quote ! {
79
+ if let #FQOption :: Some ( field) = #field_accessor {
80
+ <#field_ty as #bevy_reflect_path:: FromReflect >:: from_reflect( field)
81
+ #resolve_error
82
+ } else {
83
+ #path( )
84
+ }
85
+ } ,
86
+ DefaultBehavior :: Default => quote ! {
87
+ if let #FQOption :: Some ( field) = #field_accessor {
88
+ <#field_ty as #bevy_reflect_path:: FromReflect >:: from_reflect( field)
89
+ #resolve_error
90
+ } else {
91
+ #FQDefault :: default ( )
92
+ }
93
+ } ,
94
+ DefaultBehavior :: Required => quote ! {
95
+ <#field_ty as #bevy_reflect_path:: FromReflect >:: from_reflect( #field_accessor #resolve_missing)
96
+ #resolve_error
97
+ } ,
71
98
}
72
99
} ;
73
100
quote ! { #field_ident : #field_value }
0 commit comments