godot_core/meta/args/as_arg.rs
1/*
2 * Copyright (c) godot-rust; Bromeon and contributors.
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at https://mozilla.org/MPL/2.0/.
6 */
7
8use crate::builtin::{GString, NodePath, StringName, Variant};
9use crate::meta::sealed::Sealed;
10use crate::meta::traits::{GodotFfiVariant, GodotNullableFfi};
11use crate::meta::{CowArg, FfiArg, GodotType, ObjectArg, ToGodot};
12use crate::obj::{DynGd, Gd, GodotClass, Inherits};
13
14/// Implicit conversions for arguments passed to Godot APIs.
15///
16/// An `impl AsArg<T>` parameter allows values to be passed which can be represented in the target type `T`. Note that unlike `From<T>`,
17/// this trait is implemented more conservatively.
18///
19/// As a result, `AsArg<T>` is currently only implemented for certain argument types:
20/// - `T` for **by-value** built-ins: `i32`, `bool`, `Vector3`, `Transform2D`...
21/// - These all implement `ToGodot<Pass = ByValue>` and typically also `Copy`.
22/// - `&T` for **by-ref** built-ins: `GString`, `Array`, `Dictionary`, `PackedArray`, `Variant`...
23/// - These all implement `ToGodot<Pass = ByRef>`.
24/// - `&str`, `&String` additionally for string types `GString`, `StringName`, `NodePath`, see [String arguments](#string-arguments).
25/// - `&Gd`, `Option<&Gd>` for objects, see [Object arguments](#object-arguments).
26///
27/// # Owned values vs. references
28/// Implicitly converting from `T` for **by-ref** built-ins is explicitly not supported, i.e. you need to pass `&variant` instead of `variant`.
29/// This emphasizes that there is no need to consume the object, thus discourages unnecessary cloning. Similarly, you cannot pass by-value
30/// types like `i32` by reference.
31///
32/// Sometimes, you need exactly that for generic programming though: consistently pass `T` or `&T`. For this purpose, the global functions
33/// [`owned_into_arg()`] and [`ref_to_arg()`] are provided.
34///
35/// # Using the trait
36/// `AsArg` is meant to be used from the function call site, not the declaration site. If you declare a parameter as `impl AsArg<...>` yourself,
37/// you can only forward it as-is to a Godot API -- there are no stable APIs to access the inner object yet.
38///
39/// The blanket implementations of `AsArg` for `T` (in case of `Pass = ByValue`) and `&T` (`Pass = ByRef`) should readily enable most use
40/// cases, as long as your type already supports `ToGodot`. In the majority of cases, you'll simply use by-value passing, e.g. for enums.
41///
42/// # String arguments
43/// Godot has three string types: [`GString`], [`StringName`] and [`NodePath`]. Conversions between those three, as well as between `String` and
44/// them, is generally expensive because of allocations, re-encoding, validations, hashing, etc. While this doesn't matter for a few strings
45/// passed to engine APIs, it can become a problematic when passing long strings in a hot loop.
46///
47/// In the case of strings, we allow implicit conversion from Rust types `&str`, `&String` and `&'static CStr` (`StringName` only).
48/// While these conversions are not free, those are either explicit because a string literal is used, or they are unsurprising, because Godot
49/// cannot deal with raw Rust types. On the other hand, `GString` and `StringName` are sometimes used almost interchangeably (example:
50/// [`Node::set_name`](crate::classes::Node::set_name) takes `GString` but [`Node::get_name`](crate::classes::Node::get_name) returns `StringName`).
51///
52/// If you want to convert between Godot's string types for the sake of argument passing, each type provides an `arg()` method, such as
53/// [`GString::arg()`]. You cannot use this method in other contexts.
54///
55/// # Object arguments
56/// This section treats `AsArg<Gd<*>>`. The trait is implemented for **shared references** in multiple ways:
57/// - [`&Gd<T>`][crate::obj::Gd] to pass objects. Subclasses of `T` are explicitly supported.
58/// - [`Option<&Gd<T>>`][Option], to pass optional objects. `None` is mapped to a null argument.
59/// - [`Gd::null_arg()`], to pass `null` arguments without using `Option`.
60///
61/// The following table lists the possible argument types and how you can pass them. `Gd` is short for `Gd<T>`.
62///
63/// | Type | Closest accepted type | How to transform |
64/// |-------------------|-----------------------|------------------|
65/// | `Gd` | `&Gd` | `&arg` |
66/// | `&Gd` | `&Gd` | `arg` |
67/// | `&mut Gd` | `&Gd` | `&*arg` |
68/// | `Option<Gd>` | `Option<&Gd>` | `arg.as_ref()` |
69/// | `Option<&Gd>` | `Option<&Gd>` | `arg` |
70/// | `Option<&mut Gd>` | `Option<&Gd>` | `arg.as_deref()` |
71/// | (null literal) | | `Gd::null_arg()` |
72///
73/// ## Nullability
74/// <div class="warning">
75/// The GDExtension API does not inform about nullability of its function parameters. It is up to you to verify that the arguments you pass
76/// are only null when this is allowed. Doing this wrong should be safe, but can lead to the function call failing.
77/// </div>
78#[diagnostic::on_unimplemented(
79 message = "Argument of type `{Self}` cannot be passed to an `impl AsArg<{T}>` parameter",
80 note = "if you pass by value, consider borrowing instead.",
81 note = "GString/StringName/NodePath aren't implicitly convertible for performance reasons; use their `arg()` method.",
82 note = "see also `AsArg` docs: https://godot-rust.github.io/docs/gdext/master/godot/meta/trait.AsArg.html"
83)]
84pub trait AsArg<T: ToGodot>
85where
86 Self: Sized,
87{
88 // The usage of the CowArg return type introduces a small runtime penalty for values that implement Copy. Currently, the usage
89 // ergonomics out weigh the runtime cost. Using the CowArg allows us to create a blanket implementation of the trait for all types that
90 // implement ToGodot.
91 #[doc(hidden)]
92 fn into_arg<'arg>(self) -> CowArg<'arg, T>
93 where
94 Self: 'arg;
95
96 /// FFI-optimized argument conversion that may use `FfiObject` when beneficial.
97 ///
98 /// Defaults to calling `into_arg()` and wrapping in `FfiArg::Cow()`, which always works, but might be an `Owned` for a conservative
99 /// approach (e.g. object upcast).
100 #[doc(hidden)]
101 fn into_ffi_arg<'arg>(self) -> FfiArg<'arg, T>
102 where
103 Self: 'arg,
104 {
105 FfiArg::Cow(self.into_arg())
106 }
107}
108
109impl<T> AsArg<T> for &T
110where
111 T: ToGodot<Pass = ByRef>,
112{
113 fn into_arg<'arg>(self) -> CowArg<'arg, T>
114 where
115 Self: 'arg,
116 {
117 CowArg::Borrowed(self)
118 }
119}
120
121impl<T> AsArg<T> for T
122where
123 T: ToGodot<Pass = ByValue>,
124{
125 fn into_arg<'arg>(self) -> CowArg<'arg, T>
126 where
127 Self: 'arg,
128 {
129 CowArg::Owned(self)
130 }
131}
132
133// ----------------------------------------------------------------------------------------------------------------------------------------------
134// Object (Gd + DynGd) impls
135
136// Convert `Gd` -> `Gd` (with upcast).
137impl<T, Base> AsArg<Gd<Base>> for &Gd<T>
138where
139 T: Inherits<Base>,
140 Base: GodotClass,
141{
142 //noinspection RsConstantConditionIf - false positive in IDE for `T::IS_SAME_CLASS`.
143 fn into_arg<'arg>(self) -> CowArg<'arg, Gd<Base>>
144 where
145 Self: 'arg,
146 {
147 if T::IS_SAME_CLASS {
148 // SAFETY: T == Base, so &Gd<T> can be treated as &Gd<Base>.
149 let gd_ref = unsafe { std::mem::transmute::<&Gd<T>, &Gd<Base>>(self) };
150 CowArg::Borrowed(gd_ref)
151 } else {
152 // Different types: clone and upcast. May incur ref-count increment for RefCounted objects, but the common path
153 // of FFI passing is already optimized.
154 CowArg::Owned(self.clone().upcast())
155 }
156 }
157
158 fn into_ffi_arg<'arg>(self) -> FfiArg<'arg, Gd<Base>>
159 where
160 Self: 'arg,
161 {
162 let arg = ObjectArg::from_gd(self);
163 FfiArg::FfiObject(arg)
164 }
165}
166
167/// Convert `DynGd` -> `DynGd` (with upcast).
168impl<T, D, Base> AsArg<DynGd<Base, D>> for &DynGd<T, D>
169where
170 T: Inherits<Base>,
171 D: ?Sized,
172 Base: GodotClass,
173{
174 //noinspection RsConstantConditionIf - false positive in IDE for `T::IS_SAME_CLASS`.
175 fn into_arg<'arg>(self) -> CowArg<'arg, DynGd<Base, D>>
176 where
177 Self: 'arg,
178 {
179 if T::IS_SAME_CLASS {
180 // SAFETY: T == Base, so &DynGd<T, D> can be treated as &DynGd<Base, D>.
181 let gd_ref = unsafe { std::mem::transmute::<&DynGd<T, D>, &DynGd<Base, D>>(self) };
182 CowArg::Borrowed(gd_ref)
183 } else {
184 // Different types: clone and upcast. May incur ref-count increment for RefCounted objects, but the common path
185 // of FFI passing is already optimized.
186 CowArg::Owned(self.clone().upcast())
187 }
188 }
189
190 fn into_ffi_arg<'arg>(self) -> FfiArg<'arg, DynGd<Base, D>>
191 where
192 Self: 'arg,
193 {
194 let arg = ObjectArg::from_gd(self);
195 FfiArg::FfiObject(arg)
196 }
197}
198
199/// Convert `DynGd` -> `Gd` (with upcast).
200impl<T, D, Base> AsArg<Gd<Base>> for &DynGd<T, D>
201where
202 T: Inherits<Base>,
203 D: ?Sized,
204 Base: GodotClass,
205{
206 fn into_arg<'arg>(self) -> CowArg<'arg, Gd<Base>>
207 where
208 Self: 'arg,
209 {
210 let gd_ref: &Gd<T> = self; // DynGd -> Gd deref.
211 AsArg::into_arg(gd_ref)
212 }
213
214 fn into_ffi_arg<'arg>(self) -> FfiArg<'arg, Gd<Base>>
215 where
216 Self: 'arg,
217 {
218 let gd_ref: &Gd<T> = self; // DynGd -> Gd deref.
219 AsArg::into_ffi_arg(gd_ref)
220 }
221}
222
223// ----------------------------------------------------------------------------------------------------------------------------------------------
224// Null arguments
225
226/// Private struct for passing null arguments to optional object parameters.
227///
228/// This struct implements `AsArg` for both `Option<Gd<T>>` and `Option<DynGd<T, D>>`, allowing [`Gd::null_arg()`] and [`DynGd::null_arg()`]
229/// to share implementation.
230///
231/// Not public, as `impl AsArg<...>` is used by `null_arg()` methods.
232pub(crate) struct NullArg<T>(pub std::marker::PhantomData<*mut T>);
233
234impl<T> AsArg<Option<Gd<T>>> for NullArg<T>
235where
236 T: GodotClass,
237{
238 fn into_arg<'arg>(self) -> CowArg<'arg, Option<Gd<T>>>
239 where
240 Self: 'arg,
241 {
242 CowArg::Owned(None)
243 }
244}
245
246impl<T, D> AsArg<Option<DynGd<T, D>>> for NullArg<T>
247where
248 T: GodotClass,
249 D: ?Sized + 'static,
250{
251 fn into_arg<'arg>(self) -> CowArg<'arg, Option<DynGd<T, D>>>
252 where
253 Self: 'arg,
254 {
255 CowArg::Owned(None)
256 }
257}
258
259// ----------------------------------------------------------------------------------------------------------------------------------------------
260// Optional object (Gd + DynGd) impls
261
262/// Convert `&Gd` -> `Option<Gd>` (with upcast).
263impl<T, Base> AsArg<Option<Gd<Base>>> for &Gd<T>
264where
265 T: Inherits<Base>,
266 Base: GodotClass,
267{
268 fn into_arg<'arg>(self) -> CowArg<'arg, Option<Gd<Base>>>
269 where
270 Self: 'arg,
271 {
272 // Upcasting to an owned value Gd<Base> requires cloning. Optimized path in into_ffi_arg().
273 CowArg::Owned(Some(self.clone().upcast::<Base>()))
274 }
275
276 fn into_ffi_arg<'arg>(self) -> FfiArg<'arg, Option<Gd<Base>>>
277 where
278 Self: 'arg,
279 {
280 let arg = ObjectArg::from_gd(self);
281 FfiArg::FfiObject(arg)
282 }
283}
284
285/// Convert `Option<&Gd>` -> `Option<Gd>` (with upcast).
286impl<T, Base> AsArg<Option<Gd<Base>>> for Option<&Gd<T>>
287where
288 T: Inherits<Base>,
289 Base: GodotClass,
290{
291 fn into_arg<'arg>(self) -> CowArg<'arg, Option<Gd<Base>>>
292 where
293 Self: 'arg,
294 {
295 // Upcasting to an owned value Gd<Base> requires cloning. Optimized path in into_ffi_arg().
296 match self {
297 Some(gd_ref) => AsArg::into_arg(gd_ref),
298 None => CowArg::Owned(None),
299 }
300 }
301
302 fn into_ffi_arg<'arg>(self) -> FfiArg<'arg, Option<Gd<Base>>>
303 where
304 Self: 'arg,
305 {
306 let arg = ObjectArg::from_option_gd(self);
307 FfiArg::FfiObject(arg)
308 }
309}
310
311/// Convert `&DynGd` -> `Option<DynGd>` (with upcast).
312impl<T, D, Base> AsArg<Option<DynGd<Base, D>>> for &DynGd<T, D>
313where
314 T: Inherits<Base>,
315 D: ?Sized,
316 Base: GodotClass,
317{
318 fn into_arg<'arg>(self) -> CowArg<'arg, Option<DynGd<Base, D>>>
319 where
320 Self: 'arg,
321 {
322 // Upcasting to an owned value DynGd<Base, D> requires cloning. Optimized path in into_ffi_arg().
323 CowArg::Owned(Some(self.clone().upcast()))
324 }
325
326 fn into_ffi_arg<'arg>(self) -> FfiArg<'arg, Option<DynGd<Base, D>>>
327 where
328 Self: 'arg,
329 {
330 let arg = ObjectArg::from_gd(self);
331 FfiArg::FfiObject(arg)
332 }
333}
334
335/// Convert `&DynGd` -> `Option<Gd>` (with upcast).
336impl<T, D, Base> AsArg<Option<Gd<Base>>> for &DynGd<T, D>
337where
338 T: Inherits<Base>,
339 D: ?Sized,
340 Base: GodotClass,
341{
342 fn into_arg<'arg>(self) -> CowArg<'arg, Option<Gd<Base>>>
343 where
344 Self: 'arg,
345 {
346 let gd_ref: &Gd<T> = self; // DynGd -> Gd deref.
347 AsArg::into_arg(gd_ref)
348 }
349
350 fn into_ffi_arg<'arg>(self) -> FfiArg<'arg, Option<Gd<Base>>>
351 where
352 Self: 'arg,
353 {
354 let gd_ref: &Gd<T> = self; // DynGd -> Gd deref.
355 AsArg::into_ffi_arg(gd_ref)
356 }
357}
358
359/// Convert `Option<&DynGd>` -> `Option<DynGd>` (with upcast).
360impl<T, D, Base> AsArg<Option<DynGd<Base, D>>> for Option<&DynGd<T, D>>
361where
362 T: Inherits<Base>,
363 D: ?Sized,
364 Base: GodotClass,
365{
366 fn into_arg<'arg>(self) -> CowArg<'arg, Option<DynGd<Base, D>>>
367 where
368 Self: 'arg,
369 {
370 // Upcasting to an owned value Gd<Base> requires cloning. Optimized path in into_ffi_arg().
371 match self {
372 Some(gd_ref) => AsArg::into_arg(gd_ref),
373 None => CowArg::Owned(None),
374 }
375 }
376
377 fn into_ffi_arg<'arg>(self) -> FfiArg<'arg, Option<DynGd<Base, D>>>
378 where
379 Self: 'arg,
380 {
381 let option_gd: Option<&Gd<T>> = self.map(|v| &**v); // as_deref() not working.
382 let arg = ObjectArg::from_option_gd(option_gd);
383 FfiArg::FfiObject(arg)
384 }
385}
386
387// ----------------------------------------------------------------------------------------------------------------------------------------------
388// Public helper functions (T|&T -> AsArg)
389
390/// Generic abstraction over `T` owned values that should be passed as `AsArg<T>`.
391///
392/// Useful for generic programming: you have owned values, and want the argument conversion to benefit from moving whenever possible.
393/// You don't care if the value can truly be moved efficiently, since you don't need the value at the call site anymore.
394///
395/// Note that the pattern `owned_into_arg(value.clone())` is inefficient -- instead, use [`ref_to_arg(&value)`][ref_to_arg].
396///
397/// # Example
398/// ```
399/// use godot::prelude::*;
400/// use godot::meta::{ArrayElement, owned_into_arg};
401///
402/// // Creates random values, e.g. for fuzzing, property-based testing, etc.
403/// // Assume global state for simplicity.
404/// trait Generator {
405/// fn next() -> Self;
406/// }
407///
408/// fn fill_randomly<T>(arr: &mut Array<T>, count: usize)
409/// where
410/// T: ArrayElement + ToGodot + Generator,
411/// {
412/// for _ in 0..count {
413/// let value = T::next();
414/// arr.push(owned_into_arg(value));
415/// }
416/// }
417/// ```
418pub fn owned_into_arg<'arg, T>(owned_val: T) -> impl AsArg<T> + 'arg
419where
420 T: ToGodot + 'arg,
421{
422 CowArg::Owned(owned_val)
423}
424
425/// Generic abstraction over `&T` references that should be passed as `AsArg<T>`.
426///
427/// Useful for generic programming: you have references, and want the argument conversion to benefit from borrowing whenever possible.
428///
429/// If you no longer need the value at the call site, consider using [`owned_into_arg(value)`][owned_into_arg] instead.
430///
431/// # Example
432/// ```
433/// use godot::prelude::*;
434/// use godot::meta::{ArrayElement, ref_to_arg};
435///
436/// // Could use `impl AsArg<T>` and forward it, but let's demonstrate `&T` here.
437/// fn log_and_push<T>(arr: &mut Array<T>, value: &T)
438/// where
439/// T: ArrayElement + ToGodot + std::fmt::Debug,
440/// {
441/// println!("Add value: {value:?}");
442/// arr.push(ref_to_arg(value));
443/// }
444/// ```
445pub fn ref_to_arg<'r, T>(ref_val: &'r T) -> impl AsArg<T> + 'r
446where
447 T: ToGodot + 'r,
448{
449 CowArg::Borrowed(ref_val)
450}
451
452// ----------------------------------------------------------------------------------------------------------------------------------------------
453// Internal helper macros (AsArg -> &T|T)
454
455/// Converts `impl AsArg<T>` into a locally valid `&T`.
456///
457/// This cannot be done via function, since an intermediate variable (the Cow) is needed, which would go out of scope
458/// once the reference is returned. Could use more fancy syntax like `arg_into_ref! { let path = ref; }` or `let path = arg_into_ref!(path)`,
459/// but still isn't obvious enough to avoid doc lookup and might give a wrong idea about the scope. So being more exotic is a feature.
460#[macro_export]
461#[doc(hidden)] // Doesn't work at re-export.
462macro_rules! arg_into_ref {
463 ($arg_variable:ident) => {
464 // Non-generic version allows type inference. Only applicable for CowArg types.
465 let $arg_variable = $arg_variable.into_arg();
466 let $arg_variable = $arg_variable.cow_as_ref();
467 };
468 ($arg_variable:ident: $T:ty) => {
469 let $arg_variable = $arg_variable.into_arg();
470 let $arg_variable: &$T = $arg_variable.cow_as_ref();
471 };
472}
473
474/// Converts `impl AsArg<T>` into a locally valid `T`.
475///
476/// A macro for consistency with [`arg_into_ref`][crate::arg_into_ref].
477#[macro_export]
478#[doc(hidden)] // Doesn't work at re-export.
479macro_rules! arg_into_owned {
480 ($arg_variable:ident) => {
481 // Non-generic version allows type inference. Only applicable for CowArg types.
482 let $arg_variable = $arg_variable.into_arg();
483 let $arg_variable = $arg_variable.cow_into_owned();
484 };
485 (infer $arg_variable:ident) => {
486 let $arg_variable = $arg_variable.into_arg();
487 let $arg_variable = $arg_variable.cow_into_owned();
488 };
489}
490
491#[macro_export]
492macro_rules! declare_arg_method {
493 ($ ($docs:tt)+ ) => {
494 $( $docs )+
495 ///
496 /// # Generic bounds
497 /// The bounds are implementation-defined and may change at any time. Do not use this function in a generic context requiring `T`
498 /// -- use the `From` trait or [`AsArg`][crate::meta::AsArg] in that case.
499 pub fn arg<T>(&self) -> impl $crate::meta::AsArg<T>
500 where
501 for<'a> T: From<&'a Self>
502 + $crate::meta::ToGodot
503 + 'a,
504 {
505 $crate::meta::CowArg::Owned(T::from(self))
506 }
507 };
508}
509
510// ----------------------------------------------------------------------------------------------------------------------------------------------
511// CowArg
512
513/// `CowArg` can itself be passed as an argument (internal only).
514///
515/// Allows forwarding of `impl AsArg<T>` arguments to both another signature of `impl AsArg<T>` and signature of `T` for `Copy` types.
516/// This is necessary for packed array dispatching to different "inner" backend signatures.
517impl<T> AsArg<T> for CowArg<'_, T>
518where
519 for<'r> T: ToGodot,
520{
521 fn into_arg<'arg>(self) -> CowArg<'arg, T>
522 where
523 Self: 'arg,
524 {
525 self
526 }
527}
528
529// ----------------------------------------------------------------------------------------------------------------------------------------------
530// GString
531
532// Note: for all string types S, `impl AsArg<S> for &mut String` is not yet provided, but we can add them if needed.
533
534impl AsArg<GString> for &str {
535 fn into_arg<'arg>(self) -> CowArg<'arg, GString> {
536 CowArg::Owned(GString::from(self))
537 }
538}
539
540impl AsArg<GString> for &String {
541 fn into_arg<'arg>(self) -> CowArg<'arg, GString> {
542 CowArg::Owned(GString::from(self))
543 }
544}
545
546// ----------------------------------------------------------------------------------------------------------------------------------------------
547// StringName
548
549impl AsArg<StringName> for &str {
550 fn into_arg<'arg>(self) -> CowArg<'arg, StringName> {
551 CowArg::Owned(StringName::from(self))
552 }
553}
554
555impl AsArg<StringName> for &String {
556 fn into_arg<'arg>(self) -> CowArg<'arg, StringName> {
557 CowArg::Owned(StringName::from(self))
558 }
559}
560
561// ----------------------------------------------------------------------------------------------------------------------------------------------
562// NodePath
563
564impl AsArg<NodePath> for &str {
565 fn into_arg<'arg>(self) -> CowArg<'arg, NodePath> {
566 CowArg::Owned(NodePath::from(self))
567 }
568}
569
570impl AsArg<NodePath> for &String {
571 fn into_arg<'arg>(self) -> CowArg<'arg, NodePath> {
572 CowArg::Owned(NodePath::from(self))
573 }
574}
575
576// ----------------------------------------------------------------------------------------------------------------------------------------------
577// Argument passing (mutually exclusive by-val or by-ref).
578
579/// Determines whether arguments are passed by value or by reference to Godot.
580///
581/// See [`ToGodot::Pass`].
582pub trait ArgPassing: Sealed {
583 /// Return type: `T` or `&'r T`.
584 type Output<'r, T: 'r>
585 where
586 Self: 'r;
587
588 /// FFI argument type: `T::Ffi` or `T::ToFfi<'f>`.
589 #[doc(hidden)]
590 type FfiOutput<'f, T>: GodotFfiVariant
591 where
592 T: GodotType + 'f;
593
594 /// Convert to owned `T::Via` (cloning if necessary).
595 #[doc(hidden)]
596 fn ref_to_owned_via<T>(value: &T) -> T::Via
597 where
598 T: ToGodot<Pass = Self>,
599 T::Via: Clone;
600
601 /// Convert to FFI repr in the most efficient way (move or borrow).
602 #[doc(hidden)]
603 fn ref_to_ffi<T>(value: &T) -> Self::FfiOutput<'_, T::Via>
604 where
605 T: ToGodot<Pass = Self>,
606 T::Via: GodotType;
607
608 /// Convert to `Variant` in the most efficient way (move or borrow).
609 #[doc(hidden)]
610 fn ref_to_variant<T>(value: &T) -> Variant
611 where
612 T: ToGodot<Pass = Self>,
613 {
614 let ffi_result = Self::ref_to_ffi(value);
615 GodotFfiVariant::ffi_to_variant(&ffi_result)
616 }
617}
618
619/// Pass arguments to Godot by value.
620///
621/// See [`ToGodot::Pass`].
622pub enum ByValue {}
623impl Sealed for ByValue {}
624impl ArgPassing for ByValue {
625 type Output<'r, T: 'r> = T;
626
627 type FfiOutput<'a, T>
628 = T::Ffi
629 where
630 T: GodotType + 'a;
631
632 fn ref_to_owned_via<T>(value: &T) -> T::Via
633 where
634 T: ToGodot<Pass = Self>,
635 T::Via: Clone,
636 {
637 value.to_godot()
638 }
639
640 fn ref_to_ffi<T>(value: &T) -> Self::FfiOutput<'_, T::Via>
641 where
642 T: ToGodot<Pass = Self>,
643 T::Via: GodotType,
644 {
645 // For ByValue: to_godot() returns owned T::Via, move directly to FFI.
646 GodotType::into_ffi(value.to_godot())
647 }
648}
649
650/// Pass arguments to Godot by reference.
651///
652/// See [`ToGodot::Pass`].
653pub enum ByRef {}
654impl Sealed for ByRef {}
655impl ArgPassing for ByRef {
656 type Output<'r, T: 'r> = &'r T;
657
658 type FfiOutput<'f, T>
659 = T::ToFfi<'f>
660 where
661 T: GodotType + 'f;
662
663 fn ref_to_owned_via<T>(value: &T) -> T::Via
664 where
665 T: ToGodot<Pass = Self>,
666 T::Via: Clone,
667 {
668 // For ByRef types, clone the reference to get owned value.
669 value.to_godot().clone()
670 }
671
672 fn ref_to_ffi<T>(value: &T) -> <T::Via as GodotType>::ToFfi<'_>
673 where
674 T: ToGodot<Pass = Self>,
675 T::Via: GodotType,
676 {
677 // Use by-ref conversion if possible, avoiding unnecessary clones when passing to FFI.
678 GodotType::to_ffi(value.to_godot())
679 }
680}
681
682/// Pass arguments to Godot by object pointer (for objects only).
683///
684/// Currently distinct from [`ByRef`] to not interfere with the blanket impl for `&T` for all `ByRef` types. Semantics are largely the same.
685///
686/// See [`ToGodot::Pass`].
687pub enum ByObject {}
688impl Sealed for ByObject {}
689impl ArgPassing for ByObject {
690 type Output<'r, T: 'r> = &'r T;
691
692 type FfiOutput<'f, T>
693 = ObjectArg<'f>
694 where
695 T: GodotType + 'f;
696
697 fn ref_to_owned_via<T>(value: &T) -> T::Via
698 where
699 T: ToGodot<Pass = Self>,
700 T::Via: Clone,
701 {
702 // For ByObject types, do like ByRef: clone the reference to get owned value.
703 value.to_godot().clone()
704 }
705
706 fn ref_to_ffi<T>(value: &T) -> ObjectArg<'_>
707 where
708 T: ToGodot<Pass = Self>,
709 T::Via: GodotType,
710 {
711 let obj_ref: &T::Via = value.to_godot(); // implements GodotType.
712 obj_ref.as_object_arg()
713 }
714}
715
716/// Pass optional arguments by returning `Option<&T::Via>`, allowing delegation to underlying type's strategy.
717///
718/// This enables `Option<T>` to benefit from the underlying type's efficient passing without cloning. [`ByRef`] doesn't support this because it
719/// would transform `Option<T>` to `&Option<T>`; however, we need `Option<&T>` instead.
720///
721/// See [`ToGodot::Pass`].
722pub enum ByOption<Via> {
723 // Uses `Via` generic type to work around the near-impossibility of Output<'r, T> pointing to a metafunction that transforms Option<T> to
724 // Option<&'r T>. Such a metafunction cannot be implemented via trait (overlapping impls cause coherence issues), and we would need to
725 // pollute also the other `By*` types by anything. Using a generic parameter on the trait rather than the associated type avoids that.
726 _Phantom(std::marker::PhantomData<Via>),
727}
728impl<Via> Sealed for ByOption<Via> {}
729impl<Via> ArgPassing for ByOption<Via>
730where
731 Via: GodotType,
732 for<'f> Via::ToFfi<'f>: GodotNullableFfi,
733{
734 type Output<'r, T: 'r>
735 = Option<&'r Via>
736 where
737 Self: 'r;
738
739 type FfiOutput<'f, T>
740 = <Via as GodotType>::ToFfi<'f>
741 where
742 T: GodotType + 'f;
743
744 // value: &Option<U>
745 // return: T::Via = Option<U::Via>
746 fn ref_to_owned_via<T>(value: &T) -> T::Via
747 where
748 T: ToGodot<Pass = Self>,
749 T::Via: Clone,
750 {
751 value.to_godot_owned()
752 }
753
754 fn ref_to_ffi<T>(value: &T) -> Self::FfiOutput<'_, T::Via>
755 where
756 T: ToGodot<Pass = Self>,
757 T::Via: GodotType,
758 {
759 // Reuse pattern from impl GodotType for Option<T>:
760 // Convert Option<&Via> to Option<Via::ToFfi> and then flatten to Via::ToFfi with null handling.
761 GodotNullableFfi::flatten_option(value.to_godot().map(|via_ref| via_ref.to_ffi()))
762 }
763}
764
765#[doc(hidden)] // Easier for internal use.
766pub type ToArg<'r, Via, Pass> = <Pass as ArgPassing>::Output<'r, Via>;
767
768/// This type exists only as a place to add doctests for `AsArg`, which do not need to be in the public documentation.
769///
770/// `AsArg<Option<Gd<UserClass>>` can be used with signals correctly:
771///
772/// ```no_run
773/// # use godot::prelude::*;
774/// #[derive(GodotClass)]
775/// #[class(init, base = Node)]
776/// struct MyClass {
777/// base: Base<Node>
778/// }
779///
780/// #[godot_api]
781/// impl MyClass {
782/// #[signal]
783/// fn signal_optional_user_obj(arg1: Option<Gd<MyClass>>);
784///
785/// fn foo(&mut self) {
786/// let arg = self.to_gd();
787/// // Directly:
788/// self.signals().signal_optional_user_obj().emit(&arg);
789/// // Via Some:
790/// self.signals().signal_optional_user_obj().emit(Some(&arg));
791/// // With None (Note: Gd::null_arg() is restricted to engine classes):
792/// self.signals().signal_optional_user_obj().emit(None::<Gd<MyClass>>.as_ref());
793/// }
794/// }
795/// ```
796///
797#[allow(dead_code)]
798struct PhantomAsArgDoctests;