1
+ //! Method registration
2
+
3
+ // Temporary for unsafe method registration
4
+ #![ allow( deprecated) ]
5
+
1
6
use std:: fmt;
2
7
use std:: marker:: PhantomData ;
3
8
4
- use crate :: thread_access:: Shared ;
5
- use crate :: nativescript:: class:: { NativeClass , RefInstance } ;
6
9
use crate :: core_types:: { FromVariant , FromVariantError , Variant } ;
10
+ use crate :: nativescript:: class:: { NativeClass , RefInstance } ;
7
11
use crate :: object:: { Ref , TRef } ;
12
+ use crate :: thread_access:: Shared ;
8
13
9
14
use super :: ClassBuilder ;
10
15
16
+ /// Builder type used to register a method on a `NativeClass`.
11
17
pub struct MethodBuilder < ' a , C , F > {
12
18
class_builder : & ' a super :: ClassBuilder < C > ,
13
19
name : & ' a str ,
80
86
}
81
87
}
82
88
89
+ #[ deprecated(
90
+ note = "Unsafe registration is deprecated. Use the safe, higher-level `MethodBuilder` API instead."
91
+ ) ]
83
92
pub type ScriptMethodFn = unsafe extern "C" fn (
84
93
* mut sys:: godot_object ,
85
94
* mut libc:: c_void ,
@@ -105,10 +114,16 @@ impl Default for RpcMode {
105
114
}
106
115
}
107
116
117
+ #[ deprecated(
118
+ note = "Unsafe registration is deprecated. Use the safe, higher-level `MethodBuilder` API instead."
119
+ ) ]
108
120
pub struct ScriptMethodAttributes {
109
121
pub rpc_mode : RpcMode ,
110
122
}
111
123
124
+ #[ deprecated(
125
+ note = "Unsafe registration is deprecated. Use the safe, higher-level `MethodBuilder` API instead."
126
+ ) ]
112
127
pub struct ScriptMethod < ' l > {
113
128
pub name : & ' l str ,
114
129
pub method_ptr : Option < ScriptMethodFn > ,
@@ -118,7 +133,7 @@ pub struct ScriptMethod<'l> {
118
133
pub free_func : Option < unsafe extern "C" fn ( * mut libc:: c_void ) -> ( ) > ,
119
134
}
120
135
121
- /// Low -level trait for stateful, variadic methods that can be called on a native script type.
136
+ /// Safe low -level trait for stateful, variadic methods that can be called on a native script type.
122
137
pub trait Method < C : NativeClass > : Send + Sync + ' static {
123
138
fn call ( & self , this : RefInstance < ' _ , C , Shared > , args : Varargs < ' _ > ) -> Variant ;
124
139
}
@@ -135,7 +150,50 @@ impl<C: NativeClass, F: Method<C> + Copy + Default> Method<C> for Stateless<F> {
135
150
}
136
151
}
137
152
138
- /// Interface to a list of borrowed method arguments with a convenient interface
153
+ /// Adapter for methods whose arguments are statically determined. If the arguments would fail to
154
+ /// type check, the method will print the errors to Godot's debug console and return `null`.
155
+ #[ derive( Clone , Copy , Default , Debug ) ]
156
+ pub struct StaticArgs < F > {
157
+ f : F ,
158
+ }
159
+
160
+ impl < F > StaticArgs < F > {
161
+ /// Wrap `f` in an adapter that implements `Method`.
162
+ #[ inline]
163
+ pub fn new ( f : F ) -> Self {
164
+ StaticArgs { f }
165
+ }
166
+ }
167
+
168
+ /// Trait for methods whose argument lists are known at compile time. Not to be confused with a
169
+ /// "static method".
170
+ pub trait StaticArgsMethod < C : NativeClass > : Send + Sync + ' static {
171
+ type Args : FromVarargs ;
172
+ fn call ( & self , this : RefInstance < ' _ , C , Shared > , args : Self :: Args ) -> Variant ;
173
+ }
174
+
175
+ impl < C : NativeClass , F : StaticArgsMethod < C > > Method < C > for StaticArgs < F > {
176
+ #[ inline]
177
+ fn call ( & self , this : RefInstance < ' _ , C , Shared > , mut args : Varargs < ' _ > ) -> Variant {
178
+ match args. read_many :: < F :: Args > ( ) {
179
+ Ok ( parsed) => {
180
+ if let Err ( err) = args. done ( ) {
181
+ godot_error ! ( "{}" , err) ;
182
+ return Variant :: new ( ) ;
183
+ }
184
+ F :: call ( & self . f , this, parsed)
185
+ }
186
+ Err ( errors) => {
187
+ for err in errors {
188
+ godot_error ! ( "{}" , err) ;
189
+ }
190
+ Variant :: new ( )
191
+ }
192
+ }
193
+ }
194
+ }
195
+
196
+ /// Safe interface to a list of borrowed method arguments with a convenient API
139
197
/// for common operations with them. Can also be used as an iterator.
140
198
pub struct Varargs < ' a > {
141
199
idx : usize ,
@@ -166,6 +224,13 @@ impl<'a> Varargs<'a> {
166
224
}
167
225
}
168
226
227
+ /// Parses a structure that implements `FromVarargs` incrementally from the
228
+ /// remaining arguments.
229
+ #[ inline]
230
+ pub fn read_many < T : FromVarargs > ( & mut self ) -> Result < T , Vec < ArgumentError < ' a > > > {
231
+ T :: read ( self )
232
+ }
233
+
169
234
/// Returns the remaining arguments as a slice of `Variant`s.
170
235
#[ inline]
171
236
pub fn as_slice ( & self ) -> & ' a [ & ' a Variant ] {
@@ -213,19 +278,36 @@ impl<'a> Iterator for Varargs<'a> {
213
278
}
214
279
}
215
280
281
+ /// Trait for structures that can be parsed from `Varargs`.
282
+ ///
283
+ /// This trait can be derived for structure types where each type implements `FromVariant`.
284
+ /// The order of fields matter for this purpose:
285
+ ///
286
+ /// ```ignore
287
+ /// #[derive(FromVarargs)]
288
+ /// struct MyArgs {
289
+ /// foo: i32,
290
+ /// bar: String,
291
+ /// #[opt] baz: Option<Ref<Node>>,
292
+ /// }
293
+ /// ```
294
+ pub trait FromVarargs : Sized {
295
+ fn read < ' a > ( args : & mut Varargs < ' a > ) -> Result < Self , Vec < ArgumentError < ' a > > > ;
296
+ }
297
+
216
298
/// Builder for providing additional argument information for error reporting.
217
299
pub struct ArgBuilder < ' r , ' a , T > {
218
300
args : & ' r mut Varargs < ' a > ,
219
- name : Option < & ' r str > ,
220
- ty : Option < & ' r str > ,
301
+ name : Option < & ' a str > ,
302
+ ty : Option < & ' a str > ,
221
303
_marker : PhantomData < T > ,
222
304
}
223
305
224
306
impl < ' r , ' a , T > ArgBuilder < ' r , ' a , T > {
225
307
/// Provides a name for this argument. If an old name is already set, it is
226
308
/// silently replaced.
227
309
#[ inline]
228
- pub fn with_name ( mut self , name : & ' r str ) -> Self {
310
+ pub fn with_name ( mut self , name : & ' a str ) -> Self {
229
311
self . name = Some ( name) ;
230
312
self
231
313
}
@@ -234,7 +316,7 @@ impl<'r, 'a, T> ArgBuilder<'r, 'a, T> {
234
316
/// already set, it is silently replaced. If no type name is given, a value
235
317
/// from `std::any::type_name` is used.
236
318
#[ inline]
237
- pub fn with_type_name ( mut self , ty : & ' r str ) -> Self {
319
+ pub fn with_type_name ( mut self , ty : & ' a str ) -> Self {
238
320
self . ty = Some ( ty) ;
239
321
self
240
322
}
@@ -247,7 +329,7 @@ impl<'r, 'a, T: FromVariant> ArgBuilder<'r, 'a, T> {
247
329
///
248
330
/// If the argument is missing, or cannot be converted to the desired type.
249
331
#[ inline]
250
- pub fn get ( self ) -> Result < T , ArgumentError < ' r > > {
332
+ pub fn get ( self ) -> Result < T , ArgumentError < ' a > > {
251
333
let name = self . name ;
252
334
let idx = self . args . idx ;
253
335
@@ -261,7 +343,7 @@ impl<'r, 'a, T: FromVariant> ArgBuilder<'r, 'a, T> {
261
343
///
262
344
/// If the argument is present, but cannot be converted to the desired type.
263
345
#[ inline]
264
- pub fn get_optional ( self ) -> Result < Option < T > , ArgumentError < ' r > > {
346
+ pub fn get_optional ( self ) -> Result < Option < T > , ArgumentError < ' a > > {
265
347
let Self { args, name, ty, .. } = self ;
266
348
let idx = args. idx ;
267
349
@@ -282,6 +364,7 @@ impl<'r, 'a, T: FromVariant> ArgBuilder<'r, 'a, T> {
282
364
}
283
365
}
284
366
367
+ /// Error during argument parsing.
285
368
#[ derive( Debug ) ]
286
369
pub enum ArgumentError < ' a > {
287
370
Missing {
@@ -380,7 +463,7 @@ unsafe extern "C" fn method_wrapper<C: NativeClass, F: Method<C>>(
380
463
C :: class_name( ) ,
381
464
) ;
382
465
return Variant :: new ( ) . forget ( ) ;
383
- } ,
466
+ }
384
467
} ;
385
468
386
469
let result = std:: panic:: catch_unwind ( move || {
@@ -389,7 +472,7 @@ unsafe extern "C" fn method_wrapper<C: NativeClass, F: Method<C>>(
389
472
let this: Ref < C :: Base , Shared > = Ref :: from_sys ( this) ;
390
473
let this: TRef < ' _ , C :: Base , _ > = this. assume_safe_unchecked ( ) ;
391
474
let this: RefInstance < ' _ , C , _ > = RefInstance :: from_raw_unchecked ( this, user_data) ;
392
-
475
+
393
476
let args = Varargs :: from_sys ( num_args, args) ;
394
477
395
478
F :: call ( method, this, args)
@@ -405,4 +488,4 @@ unsafe extern "C" fn method_wrapper<C: NativeClass, F: Method<C>>(
405
488
406
489
unsafe extern "C" fn free_func < F > ( method_data : * mut libc:: c_void ) {
407
490
drop ( Box :: from_raw ( method_data as * mut F ) )
408
- }
491
+ }
0 commit comments