5
5
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
6
*/
7
7
8
+ #![ deny( unsafe_op_in_unsafe_fn) ]
9
+
8
10
use crate :: builtin:: Variant ;
9
- use crate :: meta:: signature;
11
+ use crate :: meta:: error:: { CallError , ConvertError } ;
12
+ use crate :: meta:: { signature, CallContext } ;
10
13
use crate :: meta:: {
11
14
FromGodot , GodotConvert , GodotFfiVariant , GodotType , InParamTuple , OutParamTuple , ParamTuple ,
12
15
ToGodot ,
13
16
} ;
14
17
use godot_ffi as sys;
15
18
use std:: fmt;
19
+ use sys:: GodotFfi ;
16
20
17
- macro_rules! impl_param_tuple {
21
+ macro_rules! unsafe_impl_param_tuple {
18
22
( $Len: literal; $( ( $p: ident, $n: tt) : $P: ident) ,+) => {
19
23
impl <$( $P) ,+> ParamTuple for ( $( $P, ) +) where $( $P: GodotConvert + fmt:: Debug ) ,+ {
20
24
const LEN : usize = $Len;
21
25
22
- fn property_info( index: usize , param_name: & str ) -> crate :: meta:: PropertyInfo {
23
- match index {
24
- $(
25
- $n => $P:: Via :: property_info( param_name) ,
26
- ) *
27
- _ => unreachable!( "property_info: unavailable for index {}" , index) ,
28
- }
29
- }
30
-
31
26
fn param_info(
32
27
index: usize ,
33
28
param_name: & str ,
@@ -44,7 +39,7 @@ macro_rules! impl_param_tuple {
44
39
let ( $( $p, ) * ) = self ;
45
40
format!(
46
41
// This repeat expression is basically just `"{$p:?}"`, the rest is only needed so that
47
- // the repeat separator can be `", "` instead of `,`.
42
+ // the repetition separator can be `", "` instead of `,`.
48
43
concat!( "" $( , "{" , stringify!( $p) , ":?}" , ) ", "* ) ,
49
44
$( $p=$p) ,*
50
45
)
@@ -58,11 +53,20 @@ macro_rules! impl_param_tuple {
58
53
) -> signature:: CallResult <Self > {
59
54
let args = (
60
55
$(
61
- signature:: varcall_arg:: <$P, $n>( args_ptr, call_ctx) ?,
56
+ // SAFETY: `args_ptr` is an array with length `$Len` and each element is a valid pointer, since they
57
+ // are all reborrowable as references.
58
+ unsafe { * args_ptr. offset( $n) } ,
59
+ ) +
60
+ ) ;
61
+
62
+ let param_tuple = (
63
+ $(
64
+ // SAFETY: Each pointer in `args_ptr` is reborrowable as a `&Variant` for the duration of this call.
65
+ unsafe { varcall_arg:: <$P>( args. $n, call_ctx, $n) ? } ,
62
66
) +
63
67
) ;
64
68
65
- Ok ( args )
69
+ Ok ( param_tuple )
66
70
}
67
71
68
72
unsafe fn from_ptrcall_args(
@@ -72,7 +76,9 @@ macro_rules! impl_param_tuple {
72
76
) -> Self {
73
77
(
74
78
$(
75
- signature:: ptrcall_arg:: <$P, $n>( args_ptr, call_ctx, call_type) ,
79
+ // SAFETY: `args_ptr` has length `$Len` and `$n` is less than `$Len`, and `args_ptr` must be an array whose
80
+ // `$n`-th element is of type `$P`.
81
+ unsafe { ptrcall_arg:: <$P, $n>( args_ptr, call_ctx, call_type) } ,
76
82
) +
77
83
)
78
84
}
@@ -91,9 +97,9 @@ macro_rules! impl_param_tuple {
91
97
}
92
98
93
99
impl <$( $P) ,+> OutParamTuple for ( $( $P, ) +) where $( $P: ToGodot + fmt:: Debug ) ,+ {
94
- fn with_args <F , R >( self , f: F ) -> R
100
+ fn with_variants <F , R >( self , f: F ) -> R
95
101
where
96
- F : FnOnce ( & [ crate :: builtin :: Variant ] , & [ godot_ffi :: GDExtensionConstVariantPtr ] ) -> R ,
102
+ F : FnOnce ( & [ Variant ] ) -> R ,
97
103
{
98
104
let ffi_args = (
99
105
$(
@@ -107,16 +113,24 @@ macro_rules! impl_param_tuple {
107
113
) +
108
114
] ;
109
115
110
- let sys_args = [
111
- $(
112
- Variant :: var_sys( & variant_args[ $n] ) ,
113
- ) +
114
- ] ;
116
+ f( & variant_args)
117
+ }
115
118
116
- f( & variant_args, & sys_args)
119
+ fn with_variant_pointers<F , R >( self , f: F ) -> R
120
+ where
121
+ F : FnOnce ( & [ godot_ffi:: GDExtensionConstVariantPtr ] ) -> R ,
122
+ {
123
+ self . with_variants( |variants| {
124
+ let sys_args = [
125
+ $(
126
+ Variant :: var_sys( & variants[ $n] ) ,
127
+ ) +
128
+ ] ;
129
+ f( & sys_args)
130
+ } )
117
131
}
118
132
119
- fn with_ptr_args <F , R >( self , f: F ) -> R
133
+ fn with_type_pointers <F , R >( self , f: F ) -> R
120
134
where
121
135
F : FnOnce ( & [ godot_ffi:: GDExtensionConstTypePtr ] ) -> R ,
122
136
{
@@ -146,28 +160,26 @@ macro_rules! impl_param_tuple {
146
160
} ;
147
161
}
148
162
149
- impl_param_tuple ! ( 1 ; ( p0, 0 ) : P0 ) ;
150
- impl_param_tuple ! ( 2 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 ) ;
151
- impl_param_tuple ! ( 3 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 ) ;
152
- impl_param_tuple ! ( 4 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 ) ;
153
- impl_param_tuple ! ( 5 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 ) ;
154
- impl_param_tuple ! ( 6 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 ) ;
155
- impl_param_tuple ! ( 7 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 ) ;
156
- impl_param_tuple ! ( 8 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 ) ;
157
- impl_param_tuple ! ( 9 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 ) ;
158
- impl_param_tuple ! ( 10 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 ) ;
159
- impl_param_tuple ! ( 11 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 , ( p10, 10 ) : P10 ) ;
160
- impl_param_tuple ! ( 12 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 , ( p10, 10 ) : P10 , ( p11, 11 ) : P11 ) ;
161
- impl_param_tuple ! ( 13 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 , ( p10, 10 ) : P10 , ( p11, 11 ) : P11 , ( p12, 12 ) : P12 ) ;
162
- impl_param_tuple ! ( 14 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 , ( p10, 10 ) : P10 , ( p11, 11 ) : P11 , ( p12, 12 ) : P12 , ( p13, 13 ) : P13 ) ;
163
+ unsafe_impl_param_tuple ! ( 1 ; ( p0, 0 ) : P0 ) ;
164
+ unsafe_impl_param_tuple ! ( 2 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 ) ;
165
+ unsafe_impl_param_tuple ! ( 3 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 ) ;
166
+ unsafe_impl_param_tuple ! ( 4 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 ) ;
167
+ unsafe_impl_param_tuple ! ( 5 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 ) ;
168
+ unsafe_impl_param_tuple ! ( 6 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 ) ;
169
+ unsafe_impl_param_tuple ! ( 7 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 ) ;
170
+ unsafe_impl_param_tuple ! ( 8 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 ) ;
171
+ unsafe_impl_param_tuple ! ( 9 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 ) ;
172
+ unsafe_impl_param_tuple ! ( 10 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 ) ;
173
+ unsafe_impl_param_tuple ! ( 11 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 , ( p10, 10 ) : P10 ) ;
174
+ unsafe_impl_param_tuple ! ( 12 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 , ( p10, 10 ) : P10 , ( p11, 11 ) : P11 ) ;
175
+ unsafe_impl_param_tuple ! ( 13 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 , ( p10, 10 ) : P10 , ( p11, 11 ) : P11 , ( p12, 12 ) : P12 ) ;
176
+ unsafe_impl_param_tuple ! ( 14 ; ( p0, 0 ) : P0 , ( p1, 1 ) : P1 , ( p2, 2 ) : P2 , ( p3, 3 ) : P3 , ( p4, 4 ) : P4 , ( p5, 5 ) : P5 , ( p6, 6 ) : P6 , ( p7, 7 ) : P7 , ( p8, 8 ) : P8 , ( p9, 9 ) : P9 , ( p10, 10 ) : P10 , ( p11, 11 ) : P11 , ( p12, 12 ) : P12 , ( p13, 13 ) : P13 ) ;
177
+
178
+ // Manually implement for () so we dont have to add a bunch of #[allow(..)] above for the 0-length case.
163
179
164
180
impl ParamTuple for ( ) {
165
181
const LEN : usize = 0 ;
166
182
167
- fn property_info ( _index : usize , _param_name : & str ) -> crate :: meta:: PropertyInfo {
168
- unreachable ! ( "empty argument list has no parameters" )
169
- }
170
-
171
183
fn param_info (
172
184
_index : usize ,
173
185
_param_name : & str ,
@@ -193,24 +205,29 @@ impl InParamTuple for () {
193
205
_call_type : godot_ffi:: PtrcallType ,
194
206
_call_ctx : & crate :: meta:: CallContext ,
195
207
) -> Self {
196
- ( )
197
208
}
198
209
199
210
fn from_variant_array ( array : & [ & Variant ] ) -> Self {
200
211
assert_array_length :: < ( ) > ( array) ;
201
- ( )
202
212
}
203
213
}
204
214
205
215
impl OutParamTuple for ( ) {
206
- fn with_args < F , R > ( self , f : F ) -> R
216
+ fn with_variants < F , R > ( self , f : F ) -> R
207
217
where
208
- F : FnOnce ( & [ crate :: builtin :: Variant ] , & [ godot_ffi :: GDExtensionConstVariantPtr ] ) -> R ,
218
+ F : FnOnce ( & [ Variant ] ) -> R ,
209
219
{
210
- f ( & [ ] , & [ ] )
220
+ f ( & [ ] )
221
+ }
222
+
223
+ fn with_variant_pointers < F , R > ( self , f : F ) -> R
224
+ where
225
+ F : FnOnce ( & [ godot_ffi:: GDExtensionConstVariantPtr ] ) -> R ,
226
+ {
227
+ f ( & [ ] )
211
228
}
212
229
213
- fn with_ptr_args < F , R > ( self , f : F ) -> R
230
+ fn with_type_pointers < F , R > ( self , f : F ) -> R
214
231
where
215
232
F : FnOnce ( & [ godot_ffi:: GDExtensionConstTypePtr ] ) -> R ,
216
233
{
@@ -222,6 +239,52 @@ impl OutParamTuple for () {
222
239
}
223
240
}
224
241
242
+ /// Convert the `N`th argument of `args_ptr` into a value of type `P`.
243
+ ///
244
+ /// # Safety
245
+ /// - It must be safe to dereference the address at `args_ptr.offset(N)`.
246
+ /// - The pointer at `args_ptr.offset(N)` must follow the safety requirements as laid out in
247
+ /// [`GodotFfi::from_arg_ptr`].
248
+ pub ( super ) unsafe fn ptrcall_arg < P : FromGodot , const N : isize > (
249
+ args_ptr : * const sys:: GDExtensionConstTypePtr ,
250
+ call_ctx : & CallContext ,
251
+ call_type : sys:: PtrcallType ,
252
+ ) -> P {
253
+ // SAFETY: It is safe to dereference `args_ptr` at `N`.
254
+ let offset_ptr = unsafe { * args_ptr. offset ( N ) } ;
255
+
256
+ // SAFETY: The pointer follows the safety requirements from `GodotFfi::from_arg_ptr`.
257
+ let ffi = unsafe {
258
+ <P :: Via as GodotType >:: Ffi :: from_arg_ptr ( sys:: force_mut_ptr ( offset_ptr) , call_type)
259
+ } ;
260
+
261
+ <P :: Via as GodotType >:: try_from_ffi ( ffi)
262
+ . and_then ( P :: try_from_godot)
263
+ . unwrap_or_else ( |err| param_error :: < P > ( call_ctx, N as i32 , err) )
264
+ }
265
+
266
+ /// Converts `arg` into a value of type `P`.
267
+ ///
268
+ /// # Safety
269
+ ///
270
+ /// - It must be safe to reborrow `arg` as a `&Variant` with a lifetime that lasts for the duration of the call.
271
+ pub ( super ) unsafe fn varcall_arg < P : FromGodot > (
272
+ arg : sys:: GDExtensionConstVariantPtr ,
273
+ call_ctx : & CallContext ,
274
+ param_index : isize ,
275
+ ) -> Result < P , CallError > {
276
+ // SAFETY: It is safe to dereference `args_ptr` at `N` as a `Variant`.
277
+ let variant_ref = unsafe { Variant :: borrow_var_sys ( arg) } ;
278
+
279
+ P :: try_from_variant ( variant_ref)
280
+ . map_err ( |err| CallError :: failed_param_conversion :: < P > ( call_ctx, param_index, err) )
281
+ }
282
+
283
+ fn param_error < P > ( call_ctx : & CallContext , index : i32 , err : ConvertError ) -> ! {
284
+ let param_ty = std:: any:: type_name :: < P > ( ) ;
285
+ panic ! ( "in function `{call_ctx}` at parameter [{index}] of type {param_ty}: {err}" ) ;
286
+ }
287
+
225
288
fn assert_array_length < P : ParamTuple > ( array : & [ & Variant ] ) {
226
289
assert_eq ! (
227
290
array. len( ) ,
@@ -231,3 +294,14 @@ fn assert_array_length<P: ParamTuple>(array: &[&Variant]) {
231
294
array. len( )
232
295
) ;
233
296
}
297
+
298
+ #[ cfg( test) ]
299
+ mod test {
300
+ use super :: * ;
301
+
302
+ #[ test]
303
+ fn format_args_test ( ) {
304
+ assert_eq ! ( & ( ) . format_args( ) , "" ) ;
305
+ assert_eq ! ( & ( 1 , 2 , 3 ) . format_args( ) , "1, 2, 3" ) ;
306
+ }
307
+ }
0 commit comments