godot_core/meta/args/
object_arg.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
/*
 * Copyright (c) godot-rust; Bromeon and contributors.
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
 */

use crate::builtin::Variant;
use crate::meta::error::ConvertError;
use crate::meta::{ClassName, FromGodot, GodotConvert, GodotFfiVariant, GodotType, ToGodot};
use crate::obj::{bounds, Bounds, Gd, GodotClass, Inherits, RawGd};
use crate::{obj, sys};
use godot_ffi::{GodotFfi, GodotNullableFfi, PtrcallType};
use std::ptr;

/// Objects that can be passed as arguments to Godot engine functions.
///
/// This trait is implemented for **shared references** in multiple ways:
/// - [`&Gd<T>`][crate::obj::Gd]  to pass objects. Subclasses of `T` are explicitly supported.
/// - [`Option<&Gd<T>>`][Option], to pass optional objects. `None` is mapped to a null argument.
/// - [`Gd::null_arg()`], to pass `null` arguments without using `Option`.
///
/// Note that [`AsObjectArg`] is very similar to the more general [`AsArg`][crate::meta::AsArg] trait. The two may be merged in the future.
///
/// # Nullability
/// <div class="warning">
/// The GDExtension API does not inform about nullability of its function parameters. It is up to you to verify that the arguments you pass
/// are only null when this is allowed. Doing this wrong should be safe, but can lead to the function call failing.
/// </div>
///
/// # Different argument types
/// Currently, the trait requires pass-by-ref, which helps detect accidental cloning when interfacing with Godot APIs. Plus, it is more
/// consistent with the [`AsArg`][crate::meta::AsArg] trait (for strings, but also `AsArg<Gd<T>>` as used in
/// [`Array::push()`][crate::builtin::Array::push] and similar methods).
///
/// The following table lists the possible argument types and how you can pass them. `Gd` is short for `Gd<T>`.
///
/// | Type              | Closest accepted type | How to transform |
/// |-------------------|-----------------------|------------------|
/// | `Gd`              | `&Gd`                 | `&arg`           |
/// | `&Gd`             | `&Gd`                 | `arg`            |
/// | `&mut Gd`         | `&Gd`                 | `&*arg`          |
/// | `Option<Gd>`      | `Option<&Gd>`         | `arg.as_ref()`   |
/// | `Option<&Gd>`     | `Option<&Gd>`         | `arg`            |
/// | `Option<&mut Gd>` | `Option<&Gd>`         | `arg.as_deref()` |
/// | (null literal)    |                       | `Gd::null_arg()` |
#[diagnostic::on_unimplemented(
    message = "Argument of type `{Self}` cannot be passed to an `impl AsObjectArg<{T}>` parameter",
    note = "If you pass by value, consider borrowing instead.",
    note = "See also `AsObjectArg` docs: https://godot-rust.github.io/docs/gdext/master/godot/meta/trait.AsObjectArg.html"
)]
pub trait AsObjectArg<T>
where
    T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
{
    #[doc(hidden)]
    fn as_object_arg(&self) -> ObjectArg<T>;

    /// Returns
    #[doc(hidden)]
    fn consume_arg(self) -> ObjectCow<T>;
}

/*
Currently not implemented for values, to be consistent with AsArg for by-ref builtins. The idea is that this can discover patterns like
api.method(refc.clone()), and encourage better performance with api.method(&refc). However, we need to see if there's a notable ergonomic
impact, and consider that for nodes, Gd<T> copies are relatively cheap (no ref-counting). There is also some value in prematurely ending
the lifetime of a Gd<T> by moving out, so it's not accidentally used later.

impl<T, U> AsObjectArg<T> for Gd<U>
where
    T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
    U: Inherits<T>,
{
    fn as_object_arg(&self) -> ObjectArg<T> {
        <&Gd<U>>::as_object_arg(&self)
    }

    fn consume_arg(self) -> ObjectCow<T> {
        ObjectCow::Owned(self.upcast())
    }
}
*/

impl<T, U> AsObjectArg<T> for &Gd<U>
where
    T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
    U: Inherits<T>,
{
    fn as_object_arg(&self) -> ObjectArg<T> {
        // SAFETY: In the context where as_object_arg() is called (a Godot engine call), the original Gd is guaranteed to remain valid.
        // This function is not part of the public API.
        unsafe { ObjectArg::from_raw_gd(&self.raw) }
    }

    fn consume_arg(self) -> ObjectCow<T> {
        ObjectCow::Borrowed(self.as_object_arg())
    }
}

impl<T, U> AsObjectArg<T> for Option<U>
where
    T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
    U: AsObjectArg<T>,
{
    fn as_object_arg(&self) -> ObjectArg<T> {
        self.as_ref()
            .map_or_else(ObjectArg::null, AsObjectArg::as_object_arg)
    }

    fn consume_arg(self) -> ObjectCow<T> {
        match self {
            Some(obj) => obj.consume_arg(),
            None => Gd::null_arg().consume_arg(),
        }
    }
}

/*
It's relatively common that Godot APIs return `Option<Gd<T>>` or pass this type in virtual functions. To avoid excessive `as_ref()` calls, we
**could** directly support `&Option<Gd>` in addition to `Option<&Gd>`. However, this is currently not done as it hides nullability,
especially in situations where a return type is directly propagated:
    api(create_obj().as_ref())
    api(&create_obj())
While the first is slightly longer, it looks different from a function create_obj() that returns Gd<T> and thus can never be null.
In some scenarios, it's better to immediately ensure non-null (e.g. through `unwrap()`) instead of propagating nulls to the engine.
It's also quite idiomatic to use as_ref() for inner-option transforms in Rust.

impl<T, U> AsObjectArg<T> for &Option<U>
where
    T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
    for<'a> &'a U: AsObjectArg<T>,
{
    fn as_object_arg(&self) -> ObjectArg<T> {
        match self {
            Some(obj) => obj.as_object_arg(),
            None => ObjectArg::null(),
        }
    }

    fn consume_arg(self) -> ObjectCow<T> {
        match self {
            Some(obj) => obj.consume_arg(),
            None => Gd::null_arg().consume_arg(),
        }
    }
}
*/

impl<T> AsObjectArg<T> for ObjectNullArg<T>
where
    T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
{
    fn as_object_arg(&self) -> ObjectArg<T> {
        ObjectArg::null()
    }

    fn consume_arg(self) -> ObjectCow<T> {
        // Null pointer is safe to borrow.
        ObjectCow::Borrowed(ObjectArg::null())
    }
}

// ----------------------------------------------------------------------------------------------------------------------------------------------

#[doc(hidden)]
pub struct ObjectNullArg<T>(pub(crate) std::marker::PhantomData<*mut T>);

/// Exists for cases where a value must be moved, and retaining `ObjectArg<T>` may not be possible if the source is owned.
///
/// Only used in default-param extender structs.
#[doc(hidden)]
pub enum ObjectCow<T: GodotClass> {
    Owned(Gd<T>),
    Borrowed(ObjectArg<T>),
}

impl<T> ObjectCow<T>
where
    T: GodotClass + Bounds<Declarer = bounds::DeclEngine>,
{
    /// Returns the actual `ObjectArg` to be passed to function calls.
    ///
    /// [`ObjectCow`] does not implement [`AsObjectArg<T>`] because a differently-named method is more explicit (fewer errors in codegen),
    /// and because [`AsObjectArg::consume_arg()`] is not meaningful.
    pub fn cow_as_object_arg(&self) -> ObjectArg<T> {
        match self {
            ObjectCow::Owned(gd) => gd.as_object_arg(),
            ObjectCow::Borrowed(obj) => obj.clone(),
        }
    }
}

// ----------------------------------------------------------------------------------------------------------------------------------------------

/// View for object arguments passed to the Godot engine. Never owning; must be null or backed by `Gd<T>`.
///
/// Could technically have a lifetime, but this makes the whole calling code more complex, e.g. `type CallSig`. Since usage is quite localized
/// and this type doesn't use `Drop` or is propagated further, this should be fine.
#[derive(Debug)]
#[doc(hidden)]
pub struct ObjectArg<T: GodotClass> {
    // Never dropped since it's just a view; see constructor.
    object_ptr: sys::GDExtensionObjectPtr,
    _marker: std::marker::PhantomData<*mut T>,
}

impl<T> ObjectArg<T>
where
    T: GodotClass,
{
    /// # Safety
    /// The referenced `RawGd` must remain valid for the lifetime of this `ObjectArg`.
    pub unsafe fn from_raw_gd<Derived>(obj: &RawGd<Derived>) -> Self
    where
        Derived: Inherits<T>,
    {
        // Runtime check is necessary, to ensure that object is still alive and has correct runtime type.
        if !obj.is_null() {
            obj.check_rtti("from_raw_gd");
        }

        Self {
            object_ptr: obj.obj_sys(),
            _marker: std::marker::PhantomData,
        }
    }

    pub fn null() -> Self {
        Self {
            object_ptr: ptr::null_mut(),
            _marker: std::marker::PhantomData,
        }
    }

    pub fn is_null(&self) -> bool {
        self.object_ptr.is_null()
    }
}

// #[derive(Clone)] doesn't seem to get bounds right.
impl<T: GodotClass> Clone for ObjectArg<T> {
    fn clone(&self) -> Self {
        Self {
            object_ptr: self.object_ptr,
            _marker: std::marker::PhantomData,
        }
    }
}

// SAFETY: see impl GodotFfi for RawGd.
unsafe impl<T> GodotFfi for ObjectArg<T>
where
    T: GodotClass,
{
    // If anything changes here, keep in sync with RawGd impl.

    fn variant_type() -> sys::VariantType {
        sys::VariantType::OBJECT
    }

    unsafe fn new_from_sys(_ptr: sys::GDExtensionConstTypePtr) -> Self {
        unreachable!("ObjectArg should only be passed *to* Godot, not *from*.")
    }

    unsafe fn new_with_uninit(_init: impl FnOnce(sys::GDExtensionUninitializedTypePtr)) -> Self {
        unreachable!("ObjectArg should only be passed *to* Godot, not *from*.")
    }

    unsafe fn new_with_init(_init: impl FnOnce(sys::GDExtensionTypePtr)) -> Self {
        unreachable!("ObjectArg should only be passed *to* Godot, not *from*.")
    }

    fn sys(&self) -> sys::GDExtensionConstTypePtr {
        self.object_ptr.cast()
    }

    fn sys_mut(&mut self) -> sys::GDExtensionTypePtr {
        self.object_ptr.cast()
    }

    // For more context around `ref_get_object` and `ref_set_object`, see:
    // https://github.com/godotengine/godot-cpp/issues/954

    fn as_arg_ptr(&self) -> sys::GDExtensionConstTypePtr {
        obj::object_as_arg_ptr(&self.object_ptr)
    }

    unsafe fn from_arg_ptr(_ptr: sys::GDExtensionTypePtr, _call_type: PtrcallType) -> Self {
        unreachable!("ObjectArg should only be passed *to* Godot, not *from*.")
    }

    unsafe fn move_return_ptr(self, _ptr: sys::GDExtensionTypePtr, _call_type: PtrcallType) {
        unreachable!("ObjectArg should only be passed *to* Godot, not *from*.")
    }
}

impl<T: GodotClass> GodotConvert for ObjectArg<T> {
    type Via = Self;
}

impl<T: GodotClass> ToGodot for ObjectArg<T> {
    type ToVia<'v> = Self;

    fn to_godot(&self) -> Self::ToVia<'_> {
        (*self).clone()
    }
}

// TODO refactor signature tuples into separate in+out traits, so FromGodot is no longer needed.
impl<T: GodotClass> FromGodot for ObjectArg<T> {
    fn try_from_godot(_via: Self::Via) -> Result<Self, ConvertError> {
        unreachable!("ObjectArg should only be passed *to* Godot, not *from*.")
    }
}

impl<T: GodotClass> GodotType for ObjectArg<T> {
    type Ffi = Self;
    type ToFfi<'f> = Self; // TODO: maybe ObjectArg becomes redundant with RefArg?

    fn to_ffi(&self) -> Self::ToFfi<'_> {
        (*self).clone()
    }

    fn into_ffi(self) -> Self::Ffi {
        self
    }

    fn try_from_ffi(_ffi: Self::Ffi) -> Result<Self, ConvertError> {
        //unreachable!("ObjectArg should only be passed *to* Godot, not *from*.")
        Ok(_ffi)
    }

    fn class_name() -> ClassName {
        T::class_name()
    }

    fn godot_type_name() -> String {
        T::class_name().to_string()
    }
}

impl<T: GodotClass> GodotFfiVariant for ObjectArg<T> {
    fn ffi_to_variant(&self) -> Variant {
        // Note: currently likely not invoked since there are no known varcall APIs taking Object parameters; however this might change.
        obj::object_ffi_to_variant(self)
    }

    fn ffi_from_variant(_variant: &Variant) -> Result<Self, ConvertError> {
        unreachable!("ObjectArg should only be passed *to* Godot, not *from*.")
    }
}

impl<T: GodotClass> GodotNullableFfi for ObjectArg<T> {
    fn null() -> Self {
        Self::null()
    }

    fn is_null(&self) -> bool {
        Self::is_null(self)
    }
}