@@ -10,17 +10,19 @@ use godot_ffi as sys;
10
10
use sys:: types:: OpaqueString ;
11
11
use sys:: { ffi_methods, interface_fn, GodotFfi } ;
12
12
13
- use super :: {
14
- string_chars:: validate_unicode_scalar_sequence, FromVariant , ToVariant , Variant ,
15
- VariantConversionError ,
16
- } ;
13
+ use crate :: builtin:: inner;
17
14
15
+ use super :: string_chars:: validate_unicode_scalar_sequence;
16
+ use super :: { NodePath , StringName } ;
17
+
18
+ /// Godot's reference counted string type.
18
19
#[ repr( C , align( 8 ) ) ]
19
20
pub struct GodotString {
20
21
opaque : OpaqueString ,
21
22
}
22
23
23
24
impl GodotString {
25
+ /// Construct a new empty GodotString.
24
26
pub fn new ( ) -> Self {
25
27
Self :: default ( )
26
28
}
@@ -29,12 +31,12 @@ impl GodotString {
29
31
Self { opaque }
30
32
}
31
33
32
- ffi_methods ! {
33
- type sys :: GDExtensionStringPtr = * mut Opaque ;
34
-
35
- fn from_string_sys = from_sys ;
36
- fn from_string_sys_init = from_sys_init ;
37
- fn string_sys = sys ;
34
+ /// Returns a 32-bit integer hash value representing the string.
35
+ pub fn hash ( & self ) -> u32 {
36
+ self . as_inner ( )
37
+ . hash ( )
38
+ . try_into ( )
39
+ . expect ( "Godot hashes are uint32_t" )
38
40
}
39
41
40
42
/// Move `self` into a system pointer. This transfers ownership and thus does not call the destructor.
@@ -83,6 +85,19 @@ impl GodotString {
83
85
}
84
86
std:: slice:: from_raw_parts ( ptr as * const char , len as usize )
85
87
}
88
+
89
+ ffi_methods ! {
90
+ type sys:: GDExtensionStringPtr = * mut Opaque ;
91
+
92
+ fn from_string_sys = from_sys;
93
+ fn from_string_sys_init = from_sys_init;
94
+ fn string_sys = sys;
95
+ }
96
+
97
+ #[ doc( hidden) ]
98
+ pub fn as_inner ( & self ) -> inner:: InnerString {
99
+ inner:: InnerString :: from_outer ( self )
100
+ }
86
101
}
87
102
88
103
// SAFETY:
@@ -122,9 +137,28 @@ impl_builtin_traits! {
122
137
Drop => string_destroy;
123
138
Eq => string_operator_equal;
124
139
Ord => string_operator_less;
140
+ Hash ;
141
+ }
142
+ }
143
+
144
+ impl fmt:: Display for GodotString {
145
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
146
+ let s: String = self . chars_checked ( ) . iter ( ) . collect ( ) ;
147
+ f. write_str ( s. as_str ( ) )
148
+ }
149
+ }
150
+
151
+ /// Uses literal syntax from GDScript: `"string"`
152
+ impl fmt:: Debug for GodotString {
153
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
154
+ let s = String :: from ( self ) ;
155
+ write ! ( f, "\" {s}\" " )
125
156
}
126
157
}
127
158
159
+ // ----------------------------------------------------------------------------------------------------------------------------------------------
160
+ // Conversion from/into rust string-types
161
+
128
162
impl < S > From < S > for GodotString
129
163
where
130
164
S : AsRef < str > ,
@@ -162,7 +196,14 @@ impl From<&GodotString> for String {
162
196
}
163
197
}
164
198
165
- // TODO From<&NodePath> + test
199
+ impl From < GodotString > for String {
200
+ /// Converts this `GodotString` to a `String`.
201
+ ///
202
+ /// This is identical to `String::from(&string)`, and as such there is no performance benefit.
203
+ fn from ( string : GodotString ) -> Self {
204
+ Self :: from ( & string)
205
+ }
206
+ }
166
207
167
208
impl FromStr for GodotString {
168
209
type Err = Infallible ;
@@ -172,49 +213,47 @@ impl FromStr for GodotString {
172
213
}
173
214
}
174
215
175
- impl fmt:: Display for GodotString {
176
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
177
- let s = String :: from ( self ) ;
178
- f. write_str ( s. as_str ( ) )
179
- }
180
- }
181
-
182
- /// Uses literal syntax from GDScript: `"string"`
183
- impl fmt:: Debug for GodotString {
184
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
185
- let s = String :: from ( self ) ;
186
- write ! ( f, "\" {s}\" " )
187
- }
188
- }
216
+ // ----------------------------------------------------------------------------------------------------------------------------------------------
217
+ // Conversion from other Godot string-types
189
218
190
- impl ToVariant for & str {
191
- fn to_variant ( & self ) -> Variant {
192
- GodotString :: from ( * self ) . to_variant ( )
219
+ impl From < & StringName > for GodotString {
220
+ fn from ( string : & StringName ) -> Self {
221
+ unsafe {
222
+ Self :: from_sys_init_default ( |self_ptr| {
223
+ let ctor = sys:: builtin_fn!( string_from_string_name) ;
224
+ let args = [ string. sys_const ( ) ] ;
225
+ ctor ( self_ptr, args. as_ptr ( ) ) ;
226
+ } )
227
+ }
193
228
}
194
229
}
195
230
196
- impl ToVariant for String {
197
- fn to_variant ( & self ) -> Variant {
198
- GodotString :: from ( self ) . to_variant ( )
231
+ impl From < StringName > for GodotString {
232
+ /// Converts this `StringName` to a `GodotString`.
233
+ ///
234
+ /// This is identical to `GodotString::from(&string_name)`, and as such there is no performance benefit.
235
+ fn from ( string_name : StringName ) -> Self {
236
+ Self :: from ( & string_name)
199
237
}
200
238
}
201
239
202
- impl FromVariant for String {
203
- fn try_from_variant ( variant : & Variant ) -> Result < Self , VariantConversionError > {
204
- Ok ( GodotString :: try_from_variant ( variant) ?. to_string ( ) )
240
+ impl From < & NodePath > for GodotString {
241
+ fn from ( path : & NodePath ) -> Self {
242
+ unsafe {
243
+ Self :: from_sys_init_default ( |self_ptr| {
244
+ let ctor = sys:: builtin_fn!( string_from_node_path) ;
245
+ let args = [ path. sys_const ( ) ] ;
246
+ ctor ( self_ptr, args. as_ptr ( ) ) ;
247
+ } )
248
+ }
205
249
}
206
250
}
207
251
208
- // While this is a nice optimisation for ptrcalls, it's not easily possible
209
- // to pass in &GodotString when doing varcalls.
210
- /*
211
- impl PtrCall for &GodotString {
212
- unsafe fn from_ptr_call_arg(arg: *const godot_ffi::GDExtensionTypePtr) -> Self {
213
- &*(*arg as *const GodotString)
214
- }
215
-
216
- unsafe fn to_ptr_call_arg(self, arg: godot_ffi::GDExtensionTypePtr) {
217
- std::ptr::write(arg as *mut GodotString, self.clone());
252
+ impl From < NodePath > for GodotString {
253
+ /// Converts this `NodePath` to a `GodotString`.
254
+ ///
255
+ /// This is identical to `GodotString::from(&path)`, and as such there is no performance benefit.
256
+ fn from ( path : NodePath ) -> Self {
257
+ Self :: from ( & path)
218
258
}
219
259
}
220
- */
0 commit comments