@@ -38,25 +38,35 @@ fn impl_to_variant(enum_ty: &syn::Ident, _data: &syn::DataEnum) -> syn::Result<T
3838}
3939
4040fn impl_from_variant ( enum_ty : & syn:: Ident , data : & syn:: DataEnum ) -> syn:: Result < TokenStream2 > {
41- // TODO: reject non-unit enum variant
4241 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+ } )
4856 }
49- }
50- } ) ;
57+ } )
58+ . collect :: < Result < Vec < _ > , _ > > ( ) ? ;
5159
5260 let impl_block = quote ! {
5361 impl :: gdnative:: core_types:: FromVariant for #enum_ty {
5462 #[ inline]
5563 fn from_variant( variant: & :: gdnative:: core_types:: Variant ) -> Result <Self , :: gdnative:: core_types:: FromVariantError > {
5664 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+ }
6070 }
6171 }
6272 } ;
@@ -66,10 +76,9 @@ fn impl_from_variant(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result<
6676
6777fn impl_export ( enum_ty : & syn:: Ident , data : & syn:: DataEnum ) -> syn:: Result < TokenStream2 > {
6878 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) }
7382 } ) ;
7483 let impl_block = quote ! {
7584 impl :: gdnative:: export:: Export for #enum_ty {
@@ -83,10 +92,55 @@ fn impl_export(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result<TokenS
8392 let enum_hint = :: gdnative:: export:: hint:: EnumHint :: with_numbers( mappings) ;
8493 return :: gdnative:: export:: hint:: IntHint :: <i64 >:: Enum ( enum_hint) . export_info( ) ;
8594 }
86-
8795 }
8896 }
8997 } ;
9098
9199 Ok ( impl_block)
92100}
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