diff --git a/gdnative-core/src/export/property/hint.rs b/gdnative-core/src/export/property/hint.rs index b1ffbc787..bacf626ac 100644 --- a/gdnative-core/src/export/property/hint.rs +++ b/gdnative-core/src/export/property/hint.rs @@ -1,6 +1,6 @@ //! Strongly typed property hints. -use std::fmt::{self, Write}; +use std::fmt::{self, Display, Write}; use std::ops::RangeInclusive; use crate::core_types::GodotString; @@ -116,21 +116,21 @@ where /// ``` #[derive(Clone, Eq, PartialEq, Debug, Default)] pub struct EnumHint { - values: Vec<(String, Option)>, + values: Vec, } impl EnumHint { #[inline] pub fn new(values: Vec) -> Self { - let values = values.into_iter().map(|v| (v, None)).collect(); + let values = values.into_iter().map(EnumHintEntry::new).collect(); EnumHint { values } } #[inline] - pub fn with_numbers(values: Vec<(String, i64)>) -> Self { + pub fn with_values(values: Vec<(String, i64)>) -> Self { let values = values .into_iter() - .map(|(key, val)| (key, Some(val))) + .map(|(key, value)| EnumHintEntry::with_value(key, value)) .collect(); EnumHint { values } } @@ -140,28 +140,52 @@ impl EnumHint { let mut s = String::new(); let mut iter = self.values.iter(); - let write_item = |s: &mut String, item: &(String, Option)| match item { - (key, Some(val)) => { - write!(s, "{key}:{val}") - } - (key, None) => { - write!(s, "{key}") - } - }; if let Some(first) = iter.next() { - write_item(&mut s, first).unwrap(); + write!(s, "{first}").unwrap(); } for rest in iter { write!(s, ",").unwrap(); - write_item(&mut s, rest).unwrap(); + write!(s, "{rest}").unwrap(); } s.into() } } +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct EnumHintEntry { + key: String, + value: Option, +} + +impl EnumHintEntry { + #[inline] + pub fn new(key: String) -> Self { + Self { key, value: None } + } + + #[inline] + pub fn with_value(key: String, value: i64) -> Self { + Self { + key, + value: Some(value), + } + } +} + +impl Display for EnumHintEntry { + #[inline] + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.key)?; + if let Some(value) = self.value { + write!(f, ":{}", value)?; + } + Ok(()) + } +} + /// Possible hints for integers. #[derive(Clone, Debug)] #[non_exhaustive] @@ -495,6 +519,6 @@ godot_test!(test_enum_hint_without_mapping { }); godot_test!(test_enum_hint_with_mapping { - let hint = EnumHint::with_numbers(vec![("Foo".into(), 42), ("Bar".into(), 67)]); + let hint = EnumHint::with_values(vec![("Foo".into(), 42), ("Bar".into(), 67)]); assert_eq!(hint.to_godot_hint_string().to_string(), "Foo:42,Bar:67".to_string(),); }); diff --git a/gdnative-derive/src/export.rs b/gdnative-derive/src/export.rs index 7e11b5b38..11dae0bde 100644 --- a/gdnative-derive/src/export.rs +++ b/gdnative-derive/src/export.rs @@ -1,3 +1,4 @@ +use crate::crate_gdnative_core; use proc_macro2::{Span, TokenStream as TokenStream2}; use syn::spanned::Spanned; use syn::{DeriveInput, Fields}; @@ -44,21 +45,23 @@ fn impl_export(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result>(); + let gdnative_core = crate_gdnative_core(); let impl_block = quote! { - impl ::gdnative::export::Export for #enum_ty { - type Hint = ::gdnative::export::hint::IntHint; - #[inline] - fn export_info(hint: Option) -> ::gdnative::export::ExportInfo { - if let Some(hint) = hint { - return hint.export_info(); - } else { + const _: () = { + pub enum NoHint {} + + impl #gdnative_core::export::Export for #enum_ty { + type Hint = NoHint; + + #[inline] + fn export_info(_hint: Option) -> #gdnative_core::export::ExportInfo { let mappings = vec![ #(#mappings),* ]; - let enum_hint = ::gdnative::export::hint::EnumHint::with_numbers(mappings); - return ::gdnative::export::hint::IntHint::::Enum(enum_hint).export_info(); + let enum_hint = #gdnative_core::export::hint::EnumHint::with_values(mappings); + return #gdnative_core::export::hint::IntHint::::Enum(enum_hint).export_info(); } } - } + }; }; Ok(impl_block) diff --git a/test/src/lib.rs b/test/src/lib.rs index d32d6d75d..8aa79bd38 100644 --- a/test/src/lib.rs +++ b/test/src/lib.rs @@ -8,7 +8,6 @@ mod test_as_arg; mod test_async; mod test_constructor; mod test_derive; -mod test_export_enum; mod test_free_ub; mod test_generic_class; mod test_indexed_props; @@ -53,7 +52,6 @@ pub extern "C" fn run_tests( status &= test_vararray_return::run_tests(); status &= test_variant_call_args::run_tests(); status &= test_variant_ops::run_tests(); - status &= test_export_enum::run_tests(); Variant::new(status).leak() } diff --git a/test/src/test_export_enum.rs b/test/src/test_export_enum.rs deleted file mode 100644 index a738cdd28..000000000 --- a/test/src/test_export_enum.rs +++ /dev/null @@ -1,30 +0,0 @@ -use gdnative::prelude::*; - -#[derive(Debug, PartialEq, Clone, Copy, Export, ToVariant, FromVariant)] -#[variant(enum = "repr")] -#[repr(i32)] -enum Dir { - Up = 1, - Down = -1, -} - -pub(crate) fn run_tests() -> bool { - let mut ok = true; - - ok &= test_from_variant(); - ok &= test_to_variant(); - - ok -} - -crate::godot_itest!(test_from_variant { - assert_eq!(Dir::from_variant(&1_i32.to_variant()), Ok(Dir::Up)); - assert_eq!(Dir::from_variant(&(-1_i32).to_variant()), Ok(Dir::Down)); - // 42 isn't mapped to any variant of `Dir` - assert!(Dir::from_variant(&42_i32.to_variant()).is_err()); -}); - -crate::godot_itest!(test_to_variant { - assert_eq!(Dir::Up.to_variant(), 1_i32.to_variant()); - assert_eq!(Dir::Down.to_variant(), (-1_i32).to_variant()); -});