Skip to content

Commit 3e6defc

Browse files
committed
test(ExportEnum): correctly deny invalid input
1 parent 7a9e667 commit 3e6defc

File tree

1 file changed

+70
-16
lines changed

1 file changed

+70
-16
lines changed

gdnative-derive/src/export_enum.rs

+70-16
Original file line numberDiff line numberDiff line change
@@ -38,25 +38,35 @@ fn impl_to_variant(enum_ty: &syn::Ident, _data: &syn::DataEnum) -> syn::Result<T
3838
}
3939

4040
fn 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

6777
fn 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

Comments
 (0)