@@ -38,25 +38,35 @@ fn impl_to_variant(enum_ty: &syn::Ident, _data: &syn::DataEnum) -> syn::Result<T
38
38
}
39
39
40
40
fn impl_from_variant ( enum_ty : & syn:: Ident , data : & syn:: DataEnum ) -> syn:: Result < TokenStream2 > {
41
- // TODO: reject non-unit enum variant
42
41
let as_int = quote ! { n } ;
43
- let arms = data. variants . iter ( ) . map ( |variant| {
44
- let ident = & variant. ident ;
45
- quote ! {
46
- if #as_int == #enum_ty:: #ident as i64 {
47
- return Ok ( #enum_ty:: #ident) ;
42
+ let arms = data
43
+ . variants
44
+ . iter ( )
45
+ . map ( |variant| {
46
+ let ident = & variant. ident ;
47
+ if !matches ! ( variant. fields, syn:: Fields :: Unit ) {
48
+ Err ( syn:: Error :: new (
49
+ ident. span ( ) ,
50
+ "#[derive(ExportEnum)] only support unit variant" ,
51
+ ) )
52
+ } else {
53
+ Ok ( quote ! {
54
+ if #as_int == #enum_ty:: #ident as i64 { Ok ( #enum_ty:: #ident) }
55
+ } )
48
56
}
49
- }
50
- } ) ;
57
+ } )
58
+ . collect :: < Result < Vec < _ > , _ > > ( ) ? ;
51
59
52
60
let impl_block = quote ! {
53
61
impl :: gdnative:: core_types:: FromVariant for #enum_ty {
54
62
#[ inline]
55
63
fn from_variant( variant: & :: gdnative:: core_types:: Variant ) -> Result <Self , :: gdnative:: core_types:: FromVariantError > {
56
64
let #as_int = variant. try_to:: <i64 >( ) ?;
57
- #( #arms) *
58
-
59
- panic!( )
65
+ #( #arms) else *
66
+ // TODO: return FromVariantError
67
+ else {
68
+ Err ( FromVariantError :: Unspecified )
69
+ }
60
70
}
61
71
}
62
72
} ;
@@ -66,10 +76,9 @@ fn impl_from_variant(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result<
66
76
67
77
fn impl_export ( enum_ty : & syn:: Ident , data : & syn:: DataEnum ) -> syn:: Result < TokenStream2 > {
68
78
let mappings = data. variants . iter ( ) . map ( |variant| {
69
- let ident = & variant. ident ;
70
- let key = stringify ! ( ident) ;
71
- let val = quote ! { #enum_ty:: #ident as i64 } ;
72
- quote ! { ( #key. to_string( ) , #val) }
79
+ let key = & variant. ident ;
80
+ let val = quote ! { #enum_ty:: #key as i64 } ;
81
+ quote ! { ( stringify!( #key) . to_string( ) , #val) }
73
82
} ) ;
74
83
let impl_block = quote ! {
75
84
impl :: gdnative:: export:: Export for #enum_ty {
@@ -83,10 +92,55 @@ fn impl_export(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result<TokenS
83
92
let enum_hint = :: gdnative:: export:: hint:: EnumHint :: with_numbers( mappings) ;
84
93
return :: gdnative:: export:: hint:: IntHint :: <i64 >:: Enum ( enum_hint) . export_info( ) ;
85
94
}
86
-
87
95
}
88
96
}
89
97
} ;
90
98
91
99
Ok ( impl_block)
92
100
}
101
+
102
+ #[ cfg( test) ]
103
+ mod tests {
104
+ use super :: * ;
105
+
106
+ #[ test]
107
+ fn deny_non_unit_variant ( ) -> syn:: Result < ( ) > {
108
+ let named_variant = quote ! { NamedVariant { foo: i32 , bar: f32 } } ;
109
+ let unnamed_variant = quote ! { UnnamedVariant ( String ) } ;
110
+ let input = |variant| {
111
+ parse_quote ! {
112
+ pub enum Foo {
113
+ #variant
114
+ }
115
+ }
116
+ } ;
117
+
118
+ assert ! ( derive_export_enum( & input( & named_variant) ) . is_err( ) ) ;
119
+ assert ! ( derive_export_enum( & input( & unnamed_variant) ) . is_err( ) ) ;
120
+
121
+ Ok ( ( ) )
122
+ }
123
+
124
+ #[ test]
125
+ fn deny_struct_derive ( ) -> syn:: Result < ( ) > {
126
+ let input = parse_quote ! {
127
+ struct Foo ;
128
+ } ;
129
+ assert ! ( derive_export_enum( & input) . is_err( ) ) ;
130
+
131
+ Ok ( ( ) )
132
+ }
133
+
134
+ #[ test]
135
+ fn deny_union_derive ( ) -> syn:: Result < ( ) > {
136
+ let input: DeriveInput = parse_quote ! {
137
+ union Foo {
138
+ f1: u32 ,
139
+ f2: f32 ,
140
+ }
141
+ } ;
142
+ assert ! ( derive_export_enum( & input) . is_err( ) ) ;
143
+
144
+ Ok ( ( ) )
145
+ }
146
+ }
0 commit comments