Skip to content

Commit

Permalink
Expose GodotString formatting facility
Browse files Browse the repository at this point in the history
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 <bromeon@gmail.com>
  • Loading branch information
mivort authored and Bromeon committed Nov 27, 2021
1 parent 29ddde3 commit 3042768
Showing 1 changed file with 54 additions and 1 deletion.
55 changes: 54 additions & 1 deletion 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;
Expand Down Expand Up @@ -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.
///
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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}"));
});

0 comments on commit 3042768

Please sign in to comment.