Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test(ExportEnum): correctly deny invalid input
Browse files Browse the repository at this point in the history
Bogay committed Aug 3, 2022
1 parent 3ddc845 commit 7b8deb9
Showing 1 changed file with 70 additions and 16 deletions.
86 changes: 70 additions & 16 deletions gdnative-derive/src/export_enum.rs
Original file line number Diff line number Diff line change
@@ -38,25 +38,35 @@ fn impl_to_variant(enum_ty: &syn::Ident, _data: &syn::DataEnum) -> syn::Result<T
}

fn impl_from_variant(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result<TokenStream2> {
// TODO: reject non-unit enum variant
let as_int = quote! { n };
let arms = data.variants.iter().map(|variant| {
let ident = &variant.ident;
quote! {
if #as_int == #enum_ty::#ident as i64 {
return Ok(#enum_ty::#ident);
let arms = data
.variants
.iter()
.map(|variant| {
let ident = &variant.ident;
if !matches!(variant.fields, syn::Fields::Unit) {
Err(syn::Error::new(
ident.span(),
"#[derive(ExportEnum)] only support unit variant",
))
} else {
Ok(quote! {
if #as_int == #enum_ty::#ident as i64 { Ok(#enum_ty::#ident) }
})
}
}
});
})
.collect::<Result<Vec<_>, _>>()?;

let impl_block = quote! {
impl ::gdnative::core_types::FromVariant for #enum_ty {
#[inline]
fn from_variant(variant: &::gdnative::core_types::Variant) -> Result<Self, ::gdnative::core_types::FromVariantError> {
let #as_int = variant.try_to::<i64>()?;
#(#arms)*

panic!()
#(#arms)else *
// TODO: return FromVariantError
else {
Err(FromVariantError::Unspecified)
}
}
}
};
@@ -66,10 +76,9 @@ fn impl_from_variant(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result<

fn impl_export(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result<TokenStream2> {
let mappings = data.variants.iter().map(|variant| {
let ident = &variant.ident;
let key = stringify!(ident);
let val = quote! { #enum_ty::#ident as i64 };
quote! { (#key.to_string(), #val) }
let key = &variant.ident;
let val = quote! { #enum_ty::#key as i64 };
quote! { (stringify!(#key).to_string(), #val) }
});
let impl_block = quote! {
impl ::gdnative::export::Export for #enum_ty {
@@ -83,10 +92,55 @@ fn impl_export(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result<TokenS
let enum_hint = ::gdnative::export::hint::EnumHint::with_numbers(mappings);
return ::gdnative::export::hint::IntHint::<i64>::Enum(enum_hint).export_info();
}

}
}
};

Ok(impl_block)
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn deny_non_unit_variant() -> syn::Result<()> {
let named_variant = quote! { NamedVariant { foo: i32, bar: f32 } };
let unnamed_variant = quote! { UnnamedVariant(String) };
let input = |variant| {
parse_quote! {
pub enum Foo {
#variant
}
}
};

assert!(derive_export_enum(&input(&named_variant)).is_err());
assert!(derive_export_enum(&input(&unnamed_variant)).is_err());

Ok(())
}

#[test]
fn deny_struct_derive() -> syn::Result<()> {
let input = parse_quote! {
struct Foo;
};
assert!(derive_export_enum(&input).is_err());

Ok(())
}

#[test]
fn deny_union_derive() -> syn::Result<()> {
let input: DeriveInput = parse_quote! {
union Foo {
f1: u32,
f2: f32,
}
};
assert!(derive_export_enum(&input).is_err());

Ok(())
}
}

0 comments on commit 7b8deb9

Please sign in to comment.