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}