Skip to content

Commit

Permalink
Merge pull request #899 from godot-rust/qol/test-behavior
Browse files Browse the repository at this point in the history
Unicode `ClassName::new_cached()`; adjust test
  • Loading branch information
Bromeon authored Sep 17, 2024
2 parents 3d053d7 + 0140dd7 commit e47936e
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 10 deletions.
11 changes: 8 additions & 3 deletions godot-core/src/meta/class_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,15 +102,15 @@ pub struct ClassName {
}

impl ClassName {
/// Construct a new ASCII class name.
/// Construct a new class name.
///
/// This is expensive the first time it called for a given `T`, but will be cached for subsequent calls.
///
/// It is not specified when exactly `init_fn` is invoked. However, it must return the same value for the same `T`. Generally, we expect
/// to keep the invocations limited, so you can use more expensive construction in the closure.
///
/// # Panics
/// If the string is not ASCII.
/// If the string is not ASCII and the Godot version is older than 4.4. From Godot 4.4 onwards, class names can be Unicode.
pub fn new_cached<T: GodotClass>(init_fn: impl FnOnce() -> String) -> Self {
// Check if class name exists.
let type_id = TypeId::of::<T>();
Expand All @@ -119,7 +119,12 @@ impl ClassName {
// Insert into linear vector. Note: this doesn't check for overlaps of TypeId between static and dynamic class names.
let global_index = *map.entry(type_id).or_insert_with(|| {
let name = init_fn();
debug_assert!(name.is_ascii(), "Class name must be ASCII: '{name}'");

#[cfg(before_api = "4.4")]
assert!(
name.is_ascii(),
"In Godot < 4.4, class name must be ASCII: '{name}'"
);

insert_class(ClassNameSource::Owned(name))
});
Expand Down
9 changes: 7 additions & 2 deletions itest/rust/src/builtin_tests/containers/callable_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ pub mod custom_callable {
use super::*;
use crate::framework::assert_eq_self;
use godot::builtin::{Dictionary, RustCallable};
use godot::sys::GdextBuild;
use std::fmt;
use std::hash::Hash;
use std::sync::{Arc, Mutex};
Expand Down Expand Up @@ -285,8 +286,12 @@ pub mod custom_callable {
dict.set(b, "hi");
assert_eq!(hash_count(&at), 1, "hash for a untouched if b is inserted");
assert_eq!(hash_count(&bt), 1, "hash needed for b dict key");
assert_eq!(eq_count(&at), 1, "hash collision, eq for a needed");
assert_eq!(eq_count(&bt), 1, "hash collision, eq for b needed");

// Introduced in https://github.com/godotengine/godot/pull/96797.
let eq = if GdextBuild::since_api("4.4") { 2 } else { 1 };

assert_eq!(eq_count(&at), eq, "hash collision, eq for a needed");
assert_eq!(eq_count(&bt), eq, "hash collision, eq for b needed");
}

#[itest]
Expand Down
34 changes: 34 additions & 0 deletions itest/rust/src/object_tests/class_name_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ use godot::sys;
use std::borrow::Cow;

struct A;
struct U;

implement_godot_bounds!(A);
implement_godot_bounds!(U);

impl GodotClass for A {
type Base = godot::classes::Object;
Expand All @@ -24,6 +26,14 @@ impl GodotClass for A {
}
}

impl GodotClass for U {
type Base = godot::classes::Object;

fn class_name() -> ClassName {
ClassName::new_cached::<U>(|| "统一码".to_string())
}
}

#[itest]
fn class_name_dynamic() {
let a = A::class_name();
Expand All @@ -37,3 +47,27 @@ fn class_name_dynamic() {
assert_eq!(a.to_string_name(), StringName::from("A"));
assert_eq!(a.to_cow_str(), Cow::<'static, str>::Owned("A".to_string()));
}

#[cfg(since_api = "4.4")]
#[itest]
fn class_name_dynamic_unicode() {
let a = U::class_name();
let b = U::class_name();

assert_eq!(a, b);
assert_eq!(sys::hash_value(&a), sys::hash_value(&b));

assert_eq!(a.to_string(), "统一码");
assert_eq!(a.to_gstring(), GString::from("统一码"));
assert_eq!(a.to_string_name(), StringName::from("统一码"));
assert_eq!(
a.to_cow_str(),
Cow::<'static, str>::Owned("统一码".to_string())
);
}

// Test Unicode proc-macro support for ClassName.
#[cfg(since_api = "4.4")]
#[derive(godot::register::GodotClass)]
#[class(no_init)]
struct 统一码 {}
5 changes: 0 additions & 5 deletions itest/rust/src/register_tests/naming_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,3 @@ impl IEditorExportPlugin for KeywordParameterEditorExportPlugin {
fn get_customization_configuration_hash(&self) -> u64 { unreachable!() }
fn get_name(&self) -> GString { unreachable!() }
}

#[cfg(since_api = "4.4")]
#[derive(GodotClass)]
#[class(no_init)]
struct 统一码 {}

0 comments on commit e47936e

Please sign in to comment.