@@ -17,6 +17,24 @@ macro_rules! impl_shared_string_api {
17
17
18
18
/// Manually-declared, shared methods between `GString` and `StringName`.
19
19
impl $Builtin {
20
+ /// Returns the Unicode code point ("character") at position `index`.
21
+ ///
22
+ /// # Panics
23
+ /// In debug builds, if `index` is out of bounds. In Release builds, `0` is returned instead.
24
+ // Unicode conversion panic is not documented because we rely on Godot strings having valid Unicode.
25
+ // TODO implement Index/IndexMut (for GString; StringName may have varying reprs).
26
+ pub fn unicode_at( & self , index: usize ) -> char {
27
+ debug_assert!( index < self . len( ) , "unicode_at: index {} out of bounds (len {})" , index, self . len( ) ) ;
28
+
29
+ let char_i64 = self . as_inner( ) . unicode_at( index as i64 ) ;
30
+
31
+ u32 :: try_from( char_i64) . ok( )
32
+ . and_then( |char_u32| char :: from_u32( char_u32) )
33
+ . unwrap_or_else( || {
34
+ panic!( "cannot map Unicode code point (value {char_i64}) to char (at position {index})" )
35
+ } )
36
+ }
37
+
20
38
/// Find first occurrence of `what` and return index, or `None` if not found.
21
39
///
22
40
/// Check [`find_ex()`](Self::find_ex) for all custom options.
@@ -84,8 +102,8 @@ macro_rules! impl_shared_string_api {
84
102
///
85
103
/// If `delimiter` is an empty string, each substring will be a single character.
86
104
///
87
- /// The builder struct offers methods to configure multiple dimensions. Note that `rsplit` in Godot is not useful without the `maxsplit`
88
- /// argument, so the two are combined in Rust as `maxsplit_r`.
105
+ /// The builder struct offers methods to configure multiple dimensions. Note that `rsplit` in Godot is not useful without the
106
+ /// `maxsplit` argument, so the two are combined in Rust as `maxsplit_r`.
89
107
///
90
108
/// | Method | Default behavior | Behavior after method call |
91
109
/// |--------------------|------------------------|---------------------------------------------------|
@@ -176,10 +194,44 @@ macro_rules! impl_shared_string_api {
176
194
self . as_inner( ) . format( array_or_dict, placeholder)
177
195
}
178
196
197
+ // left() + right() are not redefined, as their i64 can be negative.
198
+
199
+ /// Formats the string to be at least `min_length` long, by adding characters to the left of the string, if necessary.
200
+ ///
201
+ /// Godot itself allows padding with multiple characters, but that behavior is not very useful, because `min_length` isn't
202
+ /// respected in that case. The parameter in Godot is even called `character`. In Rust, we directly expose `char` instead.
203
+ ///
204
+ /// See also [`rpad()`](Self::rpad).
205
+ pub fn lpad( & self , min_length: usize , character: char ) -> GString {
206
+ let one_char_string = GString :: from( [ character] . as_slice( ) ) ;
207
+ self . as_inner( ) . lpad( min_length as i64 , & one_char_string)
208
+ }
209
+
210
+ /// Formats the string to be at least `min_length` long, by adding characters to the right of the string, if necessary.
211
+ ///
212
+ /// Godot itself allows padding with multiple characters, but that behavior is not very useful, because `min_length` isn't
213
+ /// respected in that case. The parameter in Godot is even called `character`. In Rust, we directly expose `char` instead.
214
+ ///
215
+ /// See also [`lpad()`](Self::lpad).
216
+ pub fn rpad( & self , min_length: usize , character: char ) -> GString {
217
+ let one_char_string = GString :: from( [ character] . as_slice( ) ) ;
218
+ self . as_inner( ) . rpad( min_length as i64 , & one_char_string)
219
+ }
220
+
221
+ /// Formats the string representing a number to have an exact number of `digits` _after_ the decimal point.
222
+ pub fn pad_decimals( & self , digits: usize ) -> GString {
223
+ self . as_inner( ) . pad_decimals( digits as i64 )
224
+ }
225
+
226
+ /// Formats the string representing a number to have an exact number of `digits` _before_ the decimal point.
227
+ pub fn pad_zeros( & self , digits: usize ) -> GString {
228
+ self . as_inner( ) . pad_zeros( digits as i64 )
229
+ }
230
+
179
231
/// Case-sensitive, lexicographic comparison to another string.
180
232
///
181
- /// Returns the `Ordering` relation of `self` towards `to`. Ordering is determined by the Unicode code points of each string, which roughly
182
- /// matches the alphabetical order.
233
+ /// Returns the `Ordering` relation of `self` towards `to`. Ordering is determined by the Unicode code points of each string, which
234
+ /// roughly matches the alphabetical order.
183
235
///
184
236
/// See also [`nocasecmp_to()`](Self::nocasecmp_to), [`naturalcasecmp_to()`](Self::naturalcasecmp_to), [`filecasecmp_to()`](Self::filecasecmp_to).
185
237
pub fn casecmp_to( & self , to: impl AsArg <GString >) -> std:: cmp:: Ordering {
@@ -188,8 +240,8 @@ macro_rules! impl_shared_string_api {
188
240
189
241
/// Case-**insensitive**, lexicographic comparison to another string.
190
242
///
191
- /// Returns the `Ordering` relation of `self` towards `to`. Ordering is determined by the Unicode code points of each string, which roughly
192
- /// matches the alphabetical order.
243
+ /// Returns the `Ordering` relation of `self` towards `to`. Ordering is determined by the Unicode code points of each string, which
244
+ /// roughly matches the alphabetical order.
193
245
///
194
246
/// See also [`casecmp_to()`](Self::casecmp_to), [`naturalcasecmp_to()`](Self::naturalcasecmp_to), [`filecasecmp_to()`](Self::filecasecmp_to).
195
247
pub fn nocasecmp_to( & self , to: impl AsArg <GString >) -> std:: cmp:: Ordering {
@@ -198,13 +250,15 @@ macro_rules! impl_shared_string_api {
198
250
199
251
/// Case-sensitive, **natural-order** comparison to another string.
200
252
///
201
- /// Returns the `Ordering` relation of `self` towards `to`. Ordering is determined by the Unicode code points of each string, which roughly
202
- /// matches the alphabetical order.
253
+ /// Returns the `Ordering` relation of `self` towards `to`. Ordering is determined by the Unicode code points of each string, which
254
+ /// roughly matches the alphabetical order.
203
255
///
204
- /// When used for sorting, natural order comparison orders sequences of numbers by the combined value of each digit as is often expected,
205
- /// instead of the single digit's value. A sorted sequence of numbered strings will be `["1", "2", "3", ...]`, not `["1", "10", "2", "3", ...]`.
256
+ /// When used for sorting, natural order comparison orders sequences of numbers by the combined value of each digit as is often
257
+ /// expected, instead of the single digit's value. A sorted sequence of numbered strings will be `["1", "2", "3", ...]`, not
258
+ /// `["1", "10", "2", "3", ...]`.
206
259
///
207
- /// With different string lengths, returns `Ordering::Greater` if this string is longer than the `to` string, or `Ordering::Less` if shorter.
260
+ /// With different string lengths, returns `Ordering::Greater` if this string is longer than the `to` string, or `Ordering::Less`
261
+ /// if shorter.
208
262
///
209
263
/// See also [`casecmp_to()`](Self::casecmp_to), [`naturalnocasecmp_to()`](Self::naturalnocasecmp_to), [`filecasecmp_to()`](Self::filecasecmp_to).
210
264
pub fn naturalcasecmp_to( & self , to: impl AsArg <GString >) -> std:: cmp:: Ordering {
@@ -213,13 +267,15 @@ macro_rules! impl_shared_string_api {
213
267
214
268
/// Case-insensitive, **natural-order** comparison to another string.
215
269
///
216
- /// Returns the `Ordering` relation of `self` towards `to`. Ordering is determined by the Unicode code points of each string, which roughly
217
- /// matches the alphabetical order.
270
+ /// Returns the `Ordering` relation of `self` towards `to`. Ordering is determined by the Unicode code points of each string, which
271
+ /// roughly matches the alphabetical order.
218
272
///
219
- /// When used for sorting, natural order comparison orders sequences of numbers by the combined value of each digit as is often expected,
220
- /// instead of the single digit's value. A sorted sequence of numbered strings will be `["1", "2", "3", ...]`, not `["1", "10", "2", "3", ...]`.
273
+ /// When used for sorting, natural order comparison orders sequences of numbers by the combined value of each digit as is often
274
+ /// expected, instead of the single digit's value. A sorted sequence of numbered strings will be `["1", "2", "3", ...]`, not
275
+ /// `["1", "10", "2", "3", ...]`.
221
276
///
222
- /// With different string lengths, returns `Ordering::Greater` if this string is longer than the `to` string, or `Ordering::Less` if shorter.
277
+ /// With different string lengths, returns `Ordering::Greater` if this string is longer than the `to` string, or `Ordering::Less`
278
+ /// if shorter.
223
279
///
224
280
/// See also [`casecmp_to()`](Self::casecmp_to), [`naturalcasecmp_to()`](Self::naturalcasecmp_to), [`filecasecmp_to()`](Self::filecasecmp_to).
225
281
pub fn naturalnocasecmp_to( & self , to: impl AsArg <GString >) -> std:: cmp:: Ordering {
@@ -228,8 +284,8 @@ macro_rules! impl_shared_string_api {
228
284
229
285
/// Case-sensitive, filename-oriented comparison to another string.
230
286
///
231
- /// Like [`naturalcasecmp_to()`][Self::naturalcasecmp_to], but prioritizes strings that begin with periods (`.`) and underscores (`_`) before
232
- /// any other character. Useful when sorting folders or file names.
287
+ /// Like [`naturalcasecmp_to()`][Self::naturalcasecmp_to], but prioritizes strings that begin with periods (`.`) and underscores
288
+ /// (`_`) before any other character. Useful when sorting folders or file names.
233
289
///
234
290
/// See also [`casecmp_to()`](Self::casecmp_to), [`naturalcasecmp_to()`](Self::naturalcasecmp_to), [`filenocasecmp_to()`](Self::filenocasecmp_to).
235
291
#[ cfg( since_api = "4.3" ) ]
@@ -239,15 +295,36 @@ macro_rules! impl_shared_string_api {
239
295
240
296
/// Case-insensitive, filename-oriented comparison to another string.
241
297
///
242
- /// Like [`naturalnocasecmp_to()`][Self::naturalnocasecmp_to], but prioritizes strings that begin with periods (`.`) and underscores (`_`) before
243
- /// any other character. Useful when sorting folders or file names.
298
+ /// Like [`naturalnocasecmp_to()`][Self::naturalnocasecmp_to], but prioritizes strings that begin with periods (`.`) and underscores
299
+ /// (`_`) before any other character. Useful when sorting folders or file names.
244
300
///
245
301
/// See also [`casecmp_to()`](Self::casecmp_to), [`naturalcasecmp_to()`](Self::naturalcasecmp_to), [`filecasecmp_to()`](Self::filecasecmp_to).
246
302
#[ cfg( since_api = "4.3" ) ]
247
303
pub fn filenocasecmp_to( & self , to: impl AsArg <GString >) -> std:: cmp:: Ordering {
248
304
sys:: i64_to_ordering( self . as_inner( ) . filenocasecmp_to( to) )
249
305
}
250
306
307
+ /// Simple expression match (also called "glob" or "globbing"), where `*` matches zero or more arbitrary characters and `?`
308
+ /// matches any single character except a period (`.`).
309
+ ///
310
+ /// An empty string or empty expression always evaluates to `false`.
311
+ ///
312
+ /// Renamed from `match` because of collision with Rust keyword + possible confusion with `String::matches()` that can match regex.
313
+ #[ doc( alias = "match" ) ]
314
+ pub fn match_glob( & self , pattern: impl AsArg <GString >) -> bool {
315
+ self . as_inner( ) . match_( pattern)
316
+ }
317
+
318
+ /// Simple **case-insensitive** expression match (also called "glob" or "globbing"), where `*` matches zero or more arbitrary
319
+ /// characters and `?` matches any single character except a period (`.`).
320
+ ///
321
+ /// An empty string or empty expression always evaluates to `false`.
322
+ ///
323
+ /// Renamed from `matchn` because of collision with Rust keyword + possible confusion with `String::matches()` that can match regex.
324
+ #[ doc( alias = "matchn" ) ]
325
+ pub fn matchn_glob( & self , pattern: impl AsArg <GString >) -> bool {
326
+ self . as_inner( ) . matchn( pattern)
327
+ }
251
328
}
252
329
253
330
// --------------------------------------------------------------------------------------------------------------------------------------
0 commit comments