From 30427680df40b814a78ff207a6d604292776ec5d Mon Sep 17 00:00:00 2001 From: lufterc Date: Thu, 11 Nov 2021 20:59:50 +0300 Subject: [PATCH] Expose GodotString formatting facility This PR exposes `godot_string_format` API method to make built-in Godot string formatting available in GDNative API. It also adds a basic formatting in-engine test case. Signed-off-by: Jan Haller --- gdnative-core/src/core_types/string.rs | 55 +++++++++++++++++++++++++- 1 file changed, 54 insertions(+), 1 deletion(-) diff --git a/gdnative-core/src/core_types/string.rs b/gdnative-core/src/core_types/string.rs index a8b3a0e7c..8a48db37c 100644 --- a/gdnative-core/src/core_types/string.rs +++ b/gdnative-core/src/core_types/string.rs @@ -1,3 +1,4 @@ +use crate::core_types::Variant; use crate::object::NewRef; use crate::private::get_api; use crate::sys; @@ -201,6 +202,41 @@ impl GodotString { unsafe { (get_api().godot_string_find_last)(&self.0, what.0) } } + /// Formats the string by replacing all occurrences of a key in the string with the + /// corresponding value. The method can handle arrays or dictionaries for the key/value pairs. + /// + /// Arrays can be used as key, index, or mixed style (see below examples). Order only matters + /// when the index or mixed style of Array is used. + /// + /// # Examples + /// + /// ```no_run + /// # use gdnative::prelude::*; + /// // Array values, index style + /// let template = GodotString::from("{0} {1}"); + /// let data = VariantArray::new(); + /// data.push("foo"); + /// data.push("bar"); + /// + /// let formatted = template.format(&data.into_shared().to_variant()); + /// godot_print!("{}", formatted); // "foo bar" + /// ``` + /// + /// ```no_run + /// # use gdnative::prelude::*; + /// // Dictionary values + /// let template = GodotString::from("foo {bar}"); + /// let data = Dictionary::new(); + /// data.insert("bar", "baz"); + /// + /// let formatted = template.format(&data.into_shared().to_variant()); + /// godot_print!("{}", formatted); // "foo baz" + /// ``` + #[inline] + pub fn format(&self, values: &Variant) -> Self { + Self(unsafe { (get_api().godot_string_format)(&self.0, &values.0) }) + } + /// Returns the internal ffi representation of the string and consumes /// the rust object without running the destructor. /// @@ -663,7 +699,7 @@ mod serialize { } godot_test!(test_string { - use crate::core_types::{GodotString, Variant, VariantType, ToVariant}; + use crate::core_types::{GodotString, Variant, VariantType, ToVariant, VariantArray, Dictionary}; let foo: GodotString = "foo".into(); assert_eq!(foo.len(), 3); @@ -708,4 +744,21 @@ godot_test!(test_string { } assert_eq!(foo.to_utf8().as_str(), "foo"); + + let fmt_string = GodotString::from("foo {bar}"); + let fmt_data = Dictionary::new(); + fmt_data.insert("bar", "baz"); + + let fmt = fmt_string.format(&fmt_data.into_shared().to_variant()); + assert_eq!(fmt, GodotString::from("foo baz")); + assert_eq!(fmt_string, GodotString::from("foo {bar}")); + + let fmt_string2 = GodotString::from("{0} {1}"); + let fmt_data2 = VariantArray::new(); + fmt_data2.push("foo"); + fmt_data2.push("bar"); + + let fmt2 = fmt_string2.format(&fmt_data2.into_shared().to_variant()); + assert_eq!(fmt2, GodotString::from("foo bar")); + assert_eq!(fmt_string2, GodotString::from("{0} {1}")); });