godot_ffi/
godot_ffi.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 std::marker::PhantomData;
9
10use crate as sys;
11use crate::VariantType;
12
13/// Types that can directly and fully represent some Godot type.
14///
15/// Adds methods to convert from and to Godot FFI pointers.
16/// See [crate::ffi_methods] for ergonomic implementation.
17///
18/// # Safety
19///
20/// - [`from_arg_ptr`](GodotFfi::from_arg_ptr) and [`move_return_ptr`](GodotFfi::move_return_ptr)
21/// must properly initialize and clean up values given the [`PtrcallType`] provided by the caller.
22///
23/// - [`new_with_uninit`](GodotFfi::new_with_uninit) must call `init_fn` with a pointer to a *new*
24/// [allocated object](https://doc.rust-lang.org/std/ptr/index.html#safety).
25///
26/// - [`new_with_init`](GodotFfi::new_with_init) must call `init_fn` with a reference to a *new* value.
27#[doc(hidden)] // shows up in implementors otherwise
28pub unsafe trait GodotFfi {
29    #[doc(hidden)]
30    const VARIANT_TYPE: ExtVariantType;
31
32    #[doc(hidden)]
33    fn default_param_metadata() -> sys::GDExtensionClassMethodArgumentMetadata {
34        sys::GDEXTENSION_METHOD_ARGUMENT_METADATA_NONE
35    }
36
37    /// Construct from Godot opaque pointer.
38    ///
39    /// This will increment reference counts if the type is reference counted. If you need to avoid this, then a `borrow_sys` associated
40    /// function should usually be used. That function that takes a sys-pointer and returns it as a `&Self` reference. This must be manually
41    /// implemented for each relevant type, as not all types can be borrowed like this.
42    ///
43    /// # Safety
44    /// `ptr` must be a valid _type ptr_: it must follow Godot's convention to encode `Self`,
45    /// which is different depending on the type.
46    #[doc(hidden)]
47    unsafe fn new_from_sys(ptr: sys::GDExtensionConstTypePtr) -> Self;
48
49    /// Construct uninitialized opaque data, then initialize it with `init_fn` function.
50    ///
51    /// # Safety
52    /// `init_fn` must be a function that correctly handles a (possibly-uninitialized) _type ptr_.
53    #[doc(hidden)]
54    unsafe fn new_with_uninit(init_fn: impl FnOnce(sys::GDExtensionUninitializedTypePtr)) -> Self;
55
56    /// Like [`new_with_uninit`](GodotFfi::new_with_uninit), but pre-initializes the sys pointer to a default instance (usually
57    /// [`Default::default()`]) before calling `init_fn`.
58    ///
59    /// Some FFI functions in Godot expect a pre-existing instance at the destination pointer, e.g. CoW/ref-counted
60    /// builtin types like `Array`, `Dictionary`, `String`, `StringName`.
61    ///
62    /// # Note
63    ///
64    /// This does call `init_fn` with a `&mut Self` reference, but in some cases initializing the reference to a more appropriate
65    /// value may involve violating the value's safety invariant. In those cases it is important to ensure that this violation isn't
66    /// leaked to user-code.
67    #[doc(hidden)]
68    unsafe fn new_with_init(init_fn: impl FnOnce(sys::GDExtensionTypePtr)) -> Self;
69
70    /// Return Godot opaque pointer, for an immutable operation.
71    #[doc(hidden)]
72    fn sys(&self) -> sys::GDExtensionConstTypePtr;
73
74    /// Return Godot opaque pointer, for a mutable operation.
75    #[doc(hidden)]
76    fn sys_mut(&mut self) -> sys::GDExtensionTypePtr;
77
78    #[doc(hidden)]
79    fn as_arg_ptr(&self) -> sys::GDExtensionConstTypePtr {
80        self.sys()
81    }
82
83    /// Construct from a pointer to an argument in a call.
84    ///
85    /// # Safety
86    /// * `ptr` must be a valid _type ptr_: it must follow Godot's convention to encode `Self`,
87    ///   which is different depending on the type.
88    ///
89    /// * `ptr` must encode `Self` according to the given `call_type`'s encoding of argument values.
90    #[doc(hidden)]
91    unsafe fn from_arg_ptr(ptr: sys::GDExtensionTypePtr, call_type: PtrcallType) -> Self;
92
93    /// Move self into the pointer in pointer `dst`, dropping what is already in `dst.
94    ///
95    /// # Safety
96    /// * `dst` must be a valid _type ptr_: it must follow Godot's convention to encode `Self`,
97    ///    which is different depending on the type.
98    ///
99    /// * `dst` must be able to accept a value of type `Self` encoded according to the given
100    ///   `call_type`'s encoding of return values.
101    #[doc(hidden)]
102    unsafe fn move_return_ptr(self, dst: sys::GDExtensionTypePtr, call_type: PtrcallType);
103}
104
105// ----------------------------------------------------------------------------------------------------------------------------------------------
106
107/// Types that can represent null-values.
108///
109/// Used to blanket implement various conversions over `Option<T>`.
110///
111/// This is currently only implemented for `RawGd`.
112// TODO: Consider implementing for `Variant`.
113pub trait GodotNullableFfi: Sized + GodotFfi {
114    fn null() -> Self;
115
116    fn is_null(&self) -> bool;
117
118    fn flatten_option(opt: Option<Self>) -> Self {
119        opt.unwrap_or_else(Self::null)
120    }
121}
122
123// ----------------------------------------------------------------------------------------------------------------------------------------------
124
125/// Variant type that differentiates between `Variant` and `NIL` types.
126#[doc(hidden)]
127#[derive(Copy, Clone, Eq, PartialEq)]
128pub enum ExtVariantType {
129    /// The type `Variant` itself.
130    Variant,
131
132    /// A Godot built-in type. `NIL` means actually nil (unit type `()` in Rust), not `Variant`.
133    Concrete(VariantType),
134}
135
136impl ExtVariantType {
137    /// Returns the variant type as Godot `VariantType`, using `NIL` for the `Variant` case.
138    pub const fn variant_as_nil(&self) -> VariantType {
139        match self {
140            ExtVariantType::Variant => VariantType::NIL,
141            ExtVariantType::Concrete(variant_type) => *variant_type,
142        }
143    }
144}
145
146// ----------------------------------------------------------------------------------------------------------------------------------------------
147
148/// An indication of what type of pointer call is being made.
149#[derive(Default, Copy, Clone, Eq, PartialEq, Debug)]
150#[doc(hidden)]
151pub enum PtrcallType {
152    /// Standard pointer call.
153    ///
154    /// In a standard ptrcall, every argument is passed in as a pointer to a value of that type, and the
155    /// return value must be moved into the return pointer.
156    #[default]
157    Standard,
158
159    /// Virtual pointer call.
160    ///
161    /// A virtual call behaves like [`PtrcallType::Standard`], except for Objects.
162    ///
163    /// Objects that do not inherit from `RefCounted` are passed in as `Object**`
164    /// (`*mut GDExtensionObjectPtr` in GDExtension terms), and objects that inherit from
165    /// `RefCounted` are passed in as `Ref<T>*` (`GDExtensionRefPtr` in GDExtension
166    /// terms) and returned as `Ref<T>` objects in Godot.
167    ///
168    /// To get a `GDExtensionObjectPtr` from a `GDExtensionRefPtr`, you must use `ref_get_object`, and to
169    /// set a `GDExtensionRefPtr` to some object, you must use `ref_set_object`.
170    ///
171    /// See also <https://github.com/godotengine/godot-cpp/issues/954>.
172    Virtual,
173}
174
175// ----------------------------------------------------------------------------------------------------------------------------------------------
176// Macros to choose a certain implementation of `GodotFfi` trait for GDExtensionTypePtr;
177// or a freestanding `impl` for concrete sys pointers such as GDExtensionObjectPtr.
178// See doc comment of `ffi_methods!` for information
179
180// TODO: explicitly document safety invariants.
181#[macro_export]
182#[doc(hidden)]
183macro_rules! ffi_methods_one {
184    // type $Ptr = *mut Opaque
185    (OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_from_sys:ident = new_from_sys) => {
186        $( #[$attr] )? $vis
187        unsafe fn $new_from_sys(ptr: <$Ptr as $crate::SysPtr>::Const) -> Self {
188            // TODO: Directly use copy constructors here?
189            let opaque = std::ptr::read(ptr.cast());
190            let new = Self::from_opaque(opaque);
191            std::mem::forget(new.clone());
192            new
193        }
194    };
195    (OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_with_uninit:ident = new_with_uninit) => {
196        $( #[$attr] )? $vis
197        unsafe fn $new_with_uninit(init: impl FnOnce(<$Ptr as $crate::SysPtr>::Uninit)) -> Self {
198            let mut raw = std::mem::MaybeUninit::uninit();
199            init(raw.as_mut_ptr() as *mut _);
200
201            Self::from_opaque(raw.assume_init())
202        }
203    };
204    (OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_with_init:ident = new_with_init) => {
205        $( #[$attr] )? $vis
206        unsafe fn $new_with_init(init: impl FnOnce($Ptr)) -> Self {
207            let mut default = Self::default();
208            init(default.sys_mut().cast());
209            default
210        }
211    };
212    (OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $sys:ident = sys) => {
213        $( #[$attr] )? $vis
214        fn $sys(&self) -> <$Ptr as $crate::SysPtr>::Const {
215            std::ptr::from_ref(&self.opaque).cast()
216        }
217    };
218    (OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $sys_mut:ident = sys_mut) => {
219        $( #[$attr] )? $vis
220        fn $sys_mut(&mut self) -> $Ptr {
221            std::ptr::from_mut(&mut self.opaque).cast()
222        }
223    };
224    (OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $from_arg_ptr:ident = from_arg_ptr) => {
225        $( #[$attr] )? $vis
226        unsafe fn $from_arg_ptr(ptr: $Ptr, _call_type: $crate::PtrcallType) -> Self {
227            Self::new_from_sys(ptr.cast())
228        }
229    };
230    (OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $move_return_ptr:ident = move_return_ptr) => {
231        $( #[$attr] )? $vis
232        unsafe fn $move_return_ptr(mut self, dst: $Ptr, _call_type: $crate::PtrcallType) {
233            std::ptr::swap(dst.cast(), std::ptr::addr_of_mut!(self.opaque))
234        }
235    };
236
237    // type $Ptr = *mut Self
238    (SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_from_sys:ident = new_from_sys) => {
239        $( #[$attr] )? $vis
240        unsafe fn $new_from_sys(ptr: <$Ptr as $crate::SysPtr>::Const) -> Self {
241            let borrowed = &*ptr.cast::<Self>();
242            borrowed.clone()
243        }
244    };
245    (SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_with_uninit:ident = new_with_uninit) => {
246        $( #[$attr] )? $vis
247        unsafe fn $new_with_uninit(init: impl FnOnce(<$Ptr as $crate::SysPtr>::Uninit)) -> Self {
248            let mut raw = std::mem::MaybeUninit::<Self>::uninit();
249            init(raw.as_mut_ptr().cast());
250
251            raw.assume_init()
252        }
253    };
254    (SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_with_init:ident = new_with_init) => {
255        $( #[$attr] )? $vis
256        unsafe fn $new_with_init(init: impl FnOnce($Ptr)) -> Self {
257            let mut default = Self::default();
258            init(default.sys_mut().cast());
259            default
260        }
261    };
262    (SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $sys:ident = sys) => {
263        $( #[$attr] )? $vis
264        fn $sys(&self) -> <$Ptr as $crate::SysPtr>::Const {
265            std::ptr::from_ref(self).cast()
266        }
267    };
268    (SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $sys_mut:ident = sys_mut) => {
269        $( #[$attr] )? $vis
270        fn $sys_mut(&mut self) -> $Ptr {
271            std::ptr::from_mut(self).cast()
272        }
273    };
274    (SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $from_arg_ptr:ident = from_arg_ptr) => {
275        $( #[$attr] )? $vis
276        unsafe fn $from_arg_ptr(ptr: $Ptr, _call_type: $crate::PtrcallType) -> Self {
277            Self::new_from_sys(ptr.cast())
278        }
279    };
280    (SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $move_return_ptr:ident = move_return_ptr) => {
281        $( #[$attr] )? $vis
282        unsafe fn $move_return_ptr(self, dst: $Ptr, _call_type: $crate::PtrcallType) {
283            *(dst.cast::<Self>()) = self
284        }
285    };
286}
287
288#[macro_export]
289#[doc(hidden)]
290macro_rules! ffi_methods_rest {
291    ( // impl T: each method has a custom name and is annotated with 'pub'
292        $Impl:ident $Ptr:ty; $( fn $user_fn:ident = $sys_fn:ident; )*
293    ) => {
294        $( $crate::ffi_methods_one!($Impl $Ptr; #[doc(hidden)] pub $user_fn = $sys_fn); )*
295    };
296
297    ( // impl GodotFfi for T: methods have given names, no 'pub' needed
298        $Impl:ident $Ptr:ty; $( fn $sys_fn:ident; )*
299    ) => {
300        $( $crate::ffi_methods_one!($Impl $Ptr; $sys_fn = $sys_fn); )*
301    };
302
303    ( // impl GodotFfi for T (default all 5)
304        $Impl:ident $Ptr:ty; ..
305    ) => {
306        $crate::ffi_methods_one!($Impl $Ptr; new_from_sys = new_from_sys);
307        $crate::ffi_methods_one!($Impl $Ptr; new_with_uninit = new_with_uninit);
308        $crate::ffi_methods_one!($Impl $Ptr; new_with_init = new_with_init);
309        $crate::ffi_methods_one!($Impl $Ptr; sys = sys);
310        $crate::ffi_methods_one!($Impl $Ptr; sys_mut = sys_mut);
311        $crate::ffi_methods_one!($Impl $Ptr; from_arg_ptr = from_arg_ptr);
312        $crate::ffi_methods_one!($Impl $Ptr; move_return_ptr = move_return_ptr);
313    };
314}
315
316/// Provides "sys" style methods for FFI and ptrcall integration with Godot.
317/// The generated implementations follow one of three patterns:
318///
319/// * `*mut Opaque`<br>
320///   Implements FFI methods for a type with `Opaque` data that stores a value type (e.g. Vector2).
321///   The **address of** the `Opaque` field is used as the sys pointer.
322///   Expects a `from_opaque()` constructor and a `opaque` field.
323///
324/// * `*mut Self`<br>
325///   Implements FFI methods for a type implemented with standard Rust fields (not opaque).
326///   The address of `Self` is directly reinterpreted as the sys pointer.
327///   The size of the corresponding sys type (the `N` in `Opaque*<N>`) must not be bigger than `size_of::<Self>()`.
328///   This cannot be checked easily, because Self cannot be used in size_of(). There would of course be workarounds.
329///
330/// Using this macro as a complete implementation for [`GodotFfi`] is sound only when:
331///
332/// ## Using `*mut Opaque`
333///
334/// Turning ptrcall arguments into a value is simply calling `from_opaque` on the
335/// dereferenced argument pointer.
336/// Returning a value from a pointer call is simply calling [`std::ptr::swap`] on the return pointer
337/// and the address to the `opaque` field.
338///  
339/// ## Using `*mut Self`
340///
341/// Turning ptrcall arguments into a value is a dereferencing.
342/// Returning a value from a pointer call is `*ret_ptr = value`.
343#[macro_export]
344macro_rules! ffi_methods {
345    ( // Sys pointer = address of opaque
346        type $Ptr:ty = *mut Opaque;
347        $( $rest:tt )*
348    ) => {
349        $crate::ffi_methods_rest!(OpaquePtr $Ptr; $($rest)*);
350    };
351
352    ( // Sys pointer = address of self
353        type $Ptr:ty = *mut Self;
354        $( $rest:tt )*
355    ) => {
356        $crate::ffi_methods_rest!(SelfPtr $Ptr; $($rest)*);
357    };
358}
359
360/// An error representing a failure to convert some value of type `From` into the type `Into`.
361#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
362pub struct PrimitiveConversionError<From, Into> {
363    from: From,
364    into_ty: PhantomData<Into>,
365}
366
367impl<From, Into> PrimitiveConversionError<From, Into> {
368    pub fn new(from: From) -> Self {
369        Self {
370            from,
371            into_ty: PhantomData,
372        }
373    }
374}
375
376impl<From, Into> std::fmt::Display for PrimitiveConversionError<From, Into>
377where
378    From: std::fmt::Display,
379    Into: std::fmt::Display,
380{
381    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
382        write!(
383            f,
384            "could not convert {} to type {}",
385            self.from,
386            std::any::type_name::<Into>()
387        )
388    }
389}
390
391impl<From, Into> std::error::Error for PrimitiveConversionError<From, Into>
392where
393    From: std::fmt::Display + std::fmt::Debug,
394    Into: std::fmt::Display + std::fmt::Debug,
395{
396}
397
398// ----------------------------------------------------------------------------------------------------------------------------------------------
399// Implementation for common types (needs to be this crate due to orphan rule)
400mod scalars {
401    use super::{ExtVariantType, GodotFfi};
402    use crate as sys;
403
404    /*
405    macro_rules! impl_godot_marshalling {
406        ($T:ty) => {
407            // SAFETY:
408            // This type is represented as `Self` in Godot, so `*mut Self` is sound.
409            unsafe impl GodotFfi for $T {
410                ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
411            }
412        };
413
414        ($T:ty as $Via:ty) => {
415            // implicit bounds:
416            //    T: TryFrom<Via>, Copy
417            //    Via: TryFrom<T>, GodotFfi
418            impl GodotFuncMarshal for $T {
419                type Via = $Via;
420                type FromViaError = PrimitiveConversionError<$Via, Self>;
421                type IntoViaError = PrimitiveConversionError<Self, $Via>;
422
423                fn try_from_via(via: Self::Via) -> Result<Self, Self::FromViaError> {
424                    Self::try_from(via).map_err(|_| PrimitiveConversionError::new(via))
425                }
426
427                fn try_into_via(self) -> Result<Self::Via, Self::IntoViaError> {
428                    <$Via>::try_from(self).map_err(|_| PrimitiveConversionError::new(self))
429                }
430            }
431        };
432
433        ($T:ty as $Via:ty; lossy) => {
434            // implicit bounds:
435            //    T: TryFrom<Via>, Copy
436            //    Via: TryFrom<T>, GodotFfi
437            impl GodotFuncMarshal for $T {
438                type Via = $Via;
439                type FromViaError = Infallible;
440                type IntoViaError = Infallible;
441
442                #[inline]
443                fn try_from_via(via: Self::Via) -> Result<Self, Self::FromViaError> {
444                    Ok(via as Self)
445                }
446
447                #[inline]
448                fn try_into_via(self) -> Result<Self::Via, Self::IntoViaError> {
449                    Ok(self as $Via)
450                }
451            }
452        };
453    }
454    */
455    unsafe impl GodotFfi for bool {
456        const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::BOOL);
457
458        ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
459    }
460
461    unsafe impl GodotFfi for i64 {
462        const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::INT);
463
464        fn default_param_metadata() -> sys::GDExtensionClassMethodArgumentMetadata {
465            sys::GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64
466        }
467
468        ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
469    }
470
471    unsafe impl GodotFfi for f64 {
472        const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::FLOAT);
473
474        fn default_param_metadata() -> sys::GDExtensionClassMethodArgumentMetadata {
475            sys::GDEXTENSION_METHOD_ARGUMENT_METADATA_REAL_IS_DOUBLE
476        }
477
478        ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
479    }
480
481    unsafe impl GodotFfi for () {
482        const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::NIL);
483
484        unsafe fn new_from_sys(_ptr: sys::GDExtensionConstTypePtr) -> Self {
485            // Do nothing
486        }
487
488        unsafe fn new_with_uninit(init: impl FnOnce(sys::GDExtensionUninitializedTypePtr)) -> Self {
489            // `init` may contain code that should be run, however it shouldn't actually write to the passed in pointer.
490            let mut unit = ();
491            init(std::ptr::addr_of_mut!(unit).cast());
492            unit
493        }
494
495        unsafe fn new_with_init(init: impl FnOnce(sys::GDExtensionTypePtr)) -> Self {
496            // `init` may contain code that should be run, however it shouldn't actually write to the passed in pointer.
497            let mut unit = ();
498            init(std::ptr::addr_of_mut!(unit).cast());
499            unit
500        }
501
502        fn sys(&self) -> sys::GDExtensionConstTypePtr {
503            // ZST dummy pointer
504            std::ptr::from_ref(self).cast()
505        }
506
507        fn sys_mut(&mut self) -> sys::GDExtensionTypePtr {
508            // ZST dummy pointer
509            std::ptr::from_mut(self).cast()
510        }
511
512        // SAFETY:
513        // We're not accessing the value in `_ptr`.
514        unsafe fn from_arg_ptr(
515            _ptr: sys::GDExtensionTypePtr,
516            _call_type: super::PtrcallType,
517        ) -> Self {
518        }
519
520        // SAFETY:
521        // We're not doing anything with `_dst`.
522        unsafe fn move_return_ptr(
523            self,
524            _dst: sys::GDExtensionTypePtr,
525            _call_type: super::PtrcallType,
526        ) {
527            // Do nothing
528        }
529    }
530}