Skip to content

Commit ae505cf

Browse files
committed
docs
1 parent aab13ee commit ae505cf

File tree

9 files changed

+275
-219
lines changed

9 files changed

+275
-219
lines changed

godot-core/src/meta/godot_convert/mod.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -108,19 +108,6 @@ pub trait FromGodot: Sized + GodotConvert {
108108
}
109109
}
110110

111-
pub(crate) fn into_ffi_variant<T: ToGodot>(value: &T) -> Variant {
112-
let via = value.to_godot();
113-
let ffi = via.to_ffi();
114-
GodotFfiVariant::ffi_to_variant(&ffi)
115-
}
116-
117-
pub(crate) fn try_from_ffi<T: FromGodot>(
118-
ffi: <T::Via as GodotType>::Ffi,
119-
) -> Result<T, ConvertError> {
120-
let via = <T::Via as GodotType>::try_from_ffi(ffi)?;
121-
T::try_from_godot(via)
122-
}
123-
124111
#[macro_export]
125112
macro_rules! impl_godot_as_self {
126113
($T:ty) => {

godot-core/src/meta/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ mod method_info;
5151
mod param_tuple;
5252
mod property_info;
5353
mod sealed;
54-
// mod signature;
55-
pub(crate) mod signature;
54+
mod signature;
5655
mod traits;
5756

5857
pub mod error;

godot-core/src/meta/param_tuple.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use crate::builtin::Variant;
99

10-
use super::{CallContext, CallResult, PropertyInfo};
10+
use super::{CallContext, CallResult};
1111
use godot_ffi as sys;
1212

1313
mod impls;
@@ -20,9 +20,6 @@ pub trait ParamTuple: Sized {
2020
/// The number of elements in this parameter list.
2121
const LEN: usize;
2222

23-
/// The property info of the parameter at index `index`.
24-
fn property_info(index: usize, param_name: &str) -> PropertyInfo;
25-
2623
/// The param info of the parameter at index `index`.
2724
fn param_info(
2825
index: usize,
@@ -42,8 +39,8 @@ pub trait InParamTuple: ParamTuple {
4239
///
4340
/// # Safety
4441
///
45-
/// - `args_ptr` must be a pointer to a valid array of length `Self::LEN`
46-
/// - each element of `args_ptr` must be a `Variant`
42+
/// - `args_ptr` must be a pointer to an array of length [`Self::LEN`](ParamTuple::LEN)
43+
/// - Each element of `args_ptr` must be reborrowable as a `&Variant` with a lifetime that lasts for the duration of the call.
4744
unsafe fn from_varcall_args(
4845
args_ptr: *const sys::GDExtensionConstVariantPtr,
4946
call_ctx: &CallContext,
@@ -53,7 +50,7 @@ pub trait InParamTuple: ParamTuple {
5350
///
5451
/// # Safety
5552
///
56-
/// - `args_ptr` must be a pointer to a valid array of length `Self::LEN`
53+
/// - `args_ptr` must be a pointer to a valid array of length [`Self::LEN`](ParamTuple::LEN)
5754
/// - each element of `args_ptr` must be of the same type as each element of `Self`
5855
unsafe fn from_ptrcall_args(
5956
args_ptr: *const sys::GDExtensionConstTypePtr,
@@ -70,16 +67,21 @@ pub trait InParamTuple: ParamTuple {
7067
/// As an example, this would be used to call Godot functions through ffi, however this is _not_ used when Godot calls a user-defined
7168
/// function.
7269
pub trait OutParamTuple: ParamTuple {
73-
/// Calls `f` with arrays to the values in `self` represented by a `Variant` and a pointer to those variants.
74-
fn with_args<F, R>(self, f: F) -> R
70+
/// Call `f` on the tuple `self` by first converting `self` to an array of [`Variant`]s.
71+
fn with_variants<F, R>(self, f: F) -> R
72+
where
73+
F: FnOnce(&[Variant]) -> R;
74+
75+
/// Call `f` on the tuple `self` by first converting `self` to an array of [`Variant`] pointers.
76+
fn with_variant_pointers<F, R>(self, f: F) -> R
7577
where
76-
F: FnOnce(&[Variant], &[sys::GDExtensionConstVariantPtr]) -> R;
78+
F: FnOnce(&[sys::GDExtensionConstVariantPtr]) -> R;
7779

78-
/// Calls `f` with an array to the values in `self` represented by pointers to the values.
79-
fn with_ptr_args<F, R>(self, f: F) -> R
80+
/// Call `f` on the tuple `self` by first converting `self` to an array of Godot type pointers.
81+
fn with_type_pointers<F, R>(self, f: F) -> R
8082
where
8183
F: FnOnce(&[sys::GDExtensionConstTypePtr]) -> R;
8284

83-
/// Converts `array` to `Self` by calling [`to_variant`](crate::meta::FromGodot::to_variant) on each argument.
85+
/// Converts `array` to `Self` by calling [`to_variant`](crate::meta::ToGodot::to_variant) on each argument.
8486
fn to_variant_array(&self) -> Vec<Variant>;
8587
}

godot-core/src/meta/param_tuple/impls.rs

Lines changed: 122 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -5,29 +5,24 @@
55
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
66
*/
77

8+
#![deny(unsafe_op_in_unsafe_fn)]
9+
810
use crate::builtin::Variant;
9-
use crate::meta::signature;
11+
use crate::meta::error::{CallError, ConvertError};
12+
use crate::meta::{signature, CallContext};
1013
use crate::meta::{
1114
FromGodot, GodotConvert, GodotFfiVariant, GodotType, InParamTuple, OutParamTuple, ParamTuple,
1215
ToGodot,
1316
};
1417
use godot_ffi as sys;
1518
use std::fmt;
19+
use sys::GodotFfi;
1620

17-
macro_rules! impl_param_tuple {
21+
macro_rules! unsafe_impl_param_tuple {
1822
($Len:literal; $(($p:ident, $n:tt): $P:ident),+) => {
1923
impl<$($P),+> ParamTuple for ($($P,)+) where $($P: GodotConvert + fmt::Debug),+ {
2024
const LEN: usize = $Len;
2125

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-
3126
fn param_info(
3227
index: usize,
3328
param_name: &str,
@@ -44,7 +39,7 @@ macro_rules! impl_param_tuple {
4439
let ($($p,)*) = self;
4540
format!(
4641
// 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 `,`.
4843
concat!("" $(, "{", stringify!($p), ":?}" ,)", "*),
4944
$($p=$p),*
5045
)
@@ -58,11 +53,20 @@ macro_rules! impl_param_tuple {
5853
) -> signature::CallResult<Self> {
5954
let args = (
6055
$(
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)? },
6266
)+
6367
);
6468

65-
Ok(args)
69+
Ok(param_tuple)
6670
}
6771

6872
unsafe fn from_ptrcall_args(
@@ -72,7 +76,9 @@ macro_rules! impl_param_tuple {
7276
) -> Self {
7377
(
7478
$(
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) },
7682
)+
7783
)
7884
}
@@ -91,9 +97,9 @@ macro_rules! impl_param_tuple {
9197
}
9298

9399
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
95101
where
96-
F: FnOnce(&[crate::builtin::Variant], &[godot_ffi::GDExtensionConstVariantPtr]) -> R,
102+
F: FnOnce(&[Variant]) -> R,
97103
{
98104
let ffi_args = (
99105
$(
@@ -107,16 +113,24 @@ macro_rules! impl_param_tuple {
107113
)+
108114
];
109115

110-
let sys_args = [
111-
$(
112-
Variant::var_sys(&variant_args[$n]),
113-
)+
114-
];
116+
f(&variant_args)
117+
}
115118

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+
})
117131
}
118132

119-
fn with_ptr_args<F, R>(self, f: F) -> R
133+
fn with_type_pointers<F, R>(self, f: F) -> R
120134
where
121135
F: FnOnce(&[godot_ffi::GDExtensionConstTypePtr]) -> R,
122136
{
@@ -146,28 +160,26 @@ macro_rules! impl_param_tuple {
146160
};
147161
}
148162

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.
163179

164180
impl ParamTuple for () {
165181
const LEN: usize = 0;
166182

167-
fn property_info(_index: usize, _param_name: &str) -> crate::meta::PropertyInfo {
168-
unreachable!("empty argument list has no parameters")
169-
}
170-
171183
fn param_info(
172184
_index: usize,
173185
_param_name: &str,
@@ -193,24 +205,29 @@ impl InParamTuple for () {
193205
_call_type: godot_ffi::PtrcallType,
194206
_call_ctx: &crate::meta::CallContext,
195207
) -> Self {
196-
()
197208
}
198209

199210
fn from_variant_array(array: &[&Variant]) -> Self {
200211
assert_array_length::<()>(array);
201-
()
202212
}
203213
}
204214

205215
impl OutParamTuple for () {
206-
fn with_args<F, R>(self, f: F) -> R
216+
fn with_variants<F, R>(self, f: F) -> R
207217
where
208-
F: FnOnce(&[crate::builtin::Variant], &[godot_ffi::GDExtensionConstVariantPtr]) -> R,
218+
F: FnOnce(&[Variant]) -> R,
209219
{
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(&[])
211228
}
212229

213-
fn with_ptr_args<F, R>(self, f: F) -> R
230+
fn with_type_pointers<F, R>(self, f: F) -> R
214231
where
215232
F: FnOnce(&[godot_ffi::GDExtensionConstTypePtr]) -> R,
216233
{
@@ -222,6 +239,52 @@ impl OutParamTuple for () {
222239
}
223240
}
224241

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+
225288
fn assert_array_length<P: ParamTuple>(array: &[&Variant]) {
226289
assert_eq!(
227290
array.len(),
@@ -231,3 +294,14 @@ fn assert_array_length<P: ParamTuple>(array: &[&Variant]) {
231294
array.len()
232295
);
233296
}
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

Comments
 (0)