From 7a488457a4a0e2380bfc9e6840e30bbdfae3c512 Mon Sep 17 00:00:00 2001 From: Jovan Gerodetti Date: Fri, 28 Apr 2023 00:43:30 +0200 Subject: [PATCH] Option> does not implement ToVariant #240 --- godot-core/src/obj/gd.rs | 9 +++++ godot-ffi/src/godot_ffi.rs | 68 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/godot-core/src/obj/gd.rs b/godot-core/src/obj/gd.rs index eb13884a9..cbfab9314 100644 --- a/godot-core/src/obj/gd.rs +++ b/godot-core/src/obj/gd.rs @@ -706,6 +706,15 @@ impl ToVariant for Gd { } } +impl ToVariant for Option> { + fn to_variant(&self) -> Variant { + match self { + Some(gd) => gd.to_variant(), + None => Variant::nil(), + } + } +} + impl PartialEq for Gd { /// ⚠️ Returns whether two `Gd` pointers point to the same object. /// diff --git a/godot-ffi/src/godot_ffi.rs b/godot-ffi/src/godot_ffi.rs index 127bc2af6..835df9d2c 100644 --- a/godot-ffi/src/godot_ffi.rs +++ b/godot-ffi/src/godot_ffi.rs @@ -4,8 +4,8 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -use crate as sys; -use std::fmt::Debug; +use crate::{self as sys, interface_fn}; +use std::{fmt::Debug, ptr}; /// Adds methods to convert from and to Godot FFI pointers. /// See [crate::ffi_methods] for ergonomic implementation. @@ -487,3 +487,67 @@ mod scalars { } } } + +unsafe impl GodotFfi for Option +where + T: GodotFfi, +{ + fn sys(&self) -> sys::GDExtensionTypePtr { + match self { + Some(value) => value.sys(), + None => { + let nil_ptr = ptr::null_mut(); + let new_nil = interface_fn!(variant_new_nil); + + unsafe { + new_nil(nil_ptr); + } + + nil_ptr as sys::GDExtensionTypePtr + } + } + } + + unsafe fn from_sys(ptr: sys::GDExtensionTypePtr) -> Self { + let nil_ptr = ptr::null_mut(); + + interface_fn!(variant_new_nil)(nil_ptr); + + if ptr as sys::GDExtensionVariantPtr == nil_ptr { + return None; + } + + Some(T::from_sys(ptr)) + } + + unsafe fn from_sys_init(init_fn: impl FnOnce(sys::GDExtensionTypePtr)) -> Self { + let mut raw = std::mem::MaybeUninit::uninit(); + init_fn(raw.as_mut_ptr() as sys::GDExtensionTypePtr); + + Self::from_sys(raw.assume_init()) + } + + unsafe fn from_arg_ptr(ptr: sys::GDExtensionTypePtr, call_type: PtrcallType) -> Self { + let nil_ptr = ptr::null_mut(); + + interface_fn!(variant_new_nil)(nil_ptr); + + if ptr as sys::GDExtensionVariantPtr == nil_ptr { + return None; + } + + Some(T::from_arg_ptr(ptr, call_type)) + } + + unsafe fn move_return_ptr(self, ptr: sys::GDExtensionTypePtr, call_type: PtrcallType) { + match self { + Some(gd) => gd.move_return_ptr(ptr, call_type), + None => { + let nil_ptr = ptr::null_mut(); + + interface_fn!(variant_new_nil)(nil_ptr); + std::ptr::write(ptr as *mut _, nil_ptr as sys::GDExtensionTypePtr) + } + } + } +}