Skip to content

Commit d7d5105

Browse files
committed
feat(EnumHint): add EnumHintEntry to store entry info
1 parent 825ad68 commit d7d5105

File tree

4 files changed

+60
-66
lines changed

4 files changed

+60
-66
lines changed

gdnative-core/src/export/property/hint.rs

+46-23
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Strongly typed property hints.
22
3-
use std::fmt::{self, Write};
3+
use std::fmt::{self, Display, Write};
44
use std::ops::RangeInclusive;
55

66
use crate::core_types::GodotString;
@@ -116,52 +116,72 @@ where
116116
/// ```
117117
#[derive(Clone, Eq, PartialEq, Debug, Default)]
118118
pub struct EnumHint {
119-
values: Vec<(String, Option<i64>)>,
119+
entries: Vec<EnumHintEntry>,
120120
}
121121

122122
impl EnumHint {
123123
#[inline]
124-
pub fn new(values: Vec<String>) -> Self {
125-
let values = values.into_iter().map(|v| (v, None)).collect();
126-
EnumHint { values }
124+
pub fn new(keys: Vec<String>) -> Self {
125+
let entries = keys.into_iter().map(EnumHintEntry::new).collect();
126+
EnumHint { entries }
127127
}
128128

129129
#[inline]
130-
pub fn with_numbers(values: Vec<(String, i64)>) -> Self {
131-
let values = values
132-
.into_iter()
133-
.map(|(key, val)| (key, Some(val)))
134-
.collect();
135-
EnumHint { values }
130+
pub fn with_entries(entries: Vec<EnumHintEntry>) -> Self {
131+
EnumHint { entries }
136132
}
137133

138134
/// Formats the hint as a Godot hint string.
139135
fn to_godot_hint_string(&self) -> GodotString {
140136
let mut s = String::new();
141137

142-
let mut iter = self.values.iter();
143-
let write_item = |s: &mut String, item: &(String, Option<i64>)| match item {
144-
(key, Some(val)) => {
145-
write!(s, "{key}:{val}")
146-
}
147-
(key, None) => {
148-
write!(s, "{key}")
149-
}
150-
};
138+
let mut iter = self.entries.iter();
151139

152140
if let Some(first) = iter.next() {
153-
write_item(&mut s, first).unwrap();
141+
write!(s, "{first}").unwrap();
154142
}
155143

156144
for rest in iter {
157145
write!(s, ",").unwrap();
158-
write_item(&mut s, rest).unwrap();
146+
write!(s, "{rest}").unwrap();
159147
}
160148

161149
s.into()
162150
}
163151
}
164152

153+
#[derive(Clone, PartialEq, Eq, Debug)]
154+
pub struct EnumHintEntry {
155+
key: String,
156+
value: Option<i64>,
157+
}
158+
159+
impl EnumHintEntry {
160+
#[inline]
161+
pub fn new(key: String) -> Self {
162+
Self { key, value: None }
163+
}
164+
165+
#[inline]
166+
pub fn with_value(key: String, value: i64) -> Self {
167+
Self {
168+
key,
169+
value: Some(value),
170+
}
171+
}
172+
}
173+
174+
impl Display for EnumHintEntry {
175+
#[inline]
176+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177+
write!(f, "{}", self.key)?;
178+
if let Some(value) = self.value {
179+
write!(f, ":{}", value)?;
180+
}
181+
Ok(())
182+
}
183+
}
184+
165185
/// Possible hints for integers.
166186
#[derive(Clone, Debug)]
167187
#[non_exhaustive]
@@ -495,6 +515,9 @@ godot_test!(test_enum_hint_without_mapping {
495515
});
496516

497517
godot_test!(test_enum_hint_with_mapping {
498-
let hint = EnumHint::with_numbers(vec![("Foo".into(), 42), ("Bar".into(), 67)]);
518+
let hint = EnumHint::with_entries(vec![
519+
EnumHintEntry::with_value("Foo".to_string(), 42),
520+
EnumHintEntry::with_value("Bar".to_string(), 67),
521+
]);
499522
assert_eq!(hint.to_godot_hint_string().to_string(), "Foo:42,Bar:67".to_string(),);
500523
});

gdnative-derive/src/export.rs

+14-11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::crate_gdnative_core;
12
use proc_macro2::{Span, TokenStream as TokenStream2};
23
use syn::spanned::Spanned;
34
use syn::{DeriveInput, Fields};
@@ -35,30 +36,32 @@ fn impl_export(enum_ty: &syn::Ident, data: &syn::DataEnum) -> syn::Result<TokenS
3536
return Err(err);
3637
}
3738

39+
let gdnative_core = crate_gdnative_core();
3840
let mappings = data
3941
.variants
4042
.iter()
4143
.map(|variant| {
4244
let key = &variant.ident;
4345
let val = quote! { #enum_ty::#key as i64 };
44-
quote! { (stringify!(#key).to_string(), #val) }
46+
quote! { #gdnative_core::export::hint::EnumHintEntry::with_value(stringify!(#key).to_string(), #val) }
4547
})
4648
.collect::<Vec<_>>();
4749

4850
let impl_block = quote! {
49-
impl ::gdnative::export::Export for #enum_ty {
50-
type Hint = ::gdnative::export::hint::IntHint<i64>;
51-
#[inline]
52-
fn export_info(hint: Option<Self::Hint>) -> ::gdnative::export::ExportInfo {
53-
if let Some(hint) = hint {
54-
return hint.export_info();
55-
} else {
51+
const _: () = {
52+
pub enum NoHint {}
53+
54+
impl #gdnative_core::export::Export for #enum_ty {
55+
type Hint = NoHint;
56+
57+
#[inline]
58+
fn export_info(_hint: Option<Self::Hint>) -> #gdnative_core::export::ExportInfo {
5659
let mappings = vec![ #(#mappings),* ];
57-
let enum_hint = ::gdnative::export::hint::EnumHint::with_numbers(mappings);
58-
return ::gdnative::export::hint::IntHint::<i64>::Enum(enum_hint).export_info();
60+
let enum_hint = #gdnative_core::export::hint::EnumHint::with_entries(mappings);
61+
return #gdnative_core::export::hint::IntHint::<i64>::Enum(enum_hint).export_info();
5962
}
6063
}
61-
}
64+
};
6265
};
6366

6467
Ok(impl_block)

test/src/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ mod test_as_arg;
88
mod test_async;
99
mod test_constructor;
1010
mod test_derive;
11-
mod test_export_enum;
1211
mod test_free_ub;
1312
mod test_generic_class;
1413
mod test_indexed_props;
@@ -53,7 +52,6 @@ pub extern "C" fn run_tests(
5352
status &= test_vararray_return::run_tests();
5453
status &= test_variant_call_args::run_tests();
5554
status &= test_variant_ops::run_tests();
56-
status &= test_export_enum::run_tests();
5755

5856
Variant::new(status).leak()
5957
}

test/src/test_export_enum.rs

-30
This file was deleted.

0 commit comments

Comments
 (0)