use std::marker::PhantomData;
use crate as sys;
use crate::VariantType;
#[doc(hidden)] pub unsafe trait GodotFfi {
#[doc(hidden)]
const VARIANT_TYPE: ExtVariantType;
#[doc(hidden)]
unsafe fn new_from_sys(ptr: sys::GDExtensionConstTypePtr) -> Self;
#[doc(hidden)]
unsafe fn new_with_uninit(init_fn: impl FnOnce(sys::GDExtensionUninitializedTypePtr)) -> Self;
#[doc(hidden)]
unsafe fn new_with_init(init_fn: impl FnOnce(sys::GDExtensionTypePtr)) -> Self;
#[doc(hidden)]
fn sys(&self) -> sys::GDExtensionConstTypePtr;
#[doc(hidden)]
fn sys_mut(&mut self) -> sys::GDExtensionTypePtr;
#[doc(hidden)]
fn as_arg_ptr(&self) -> sys::GDExtensionConstTypePtr {
self.sys()
}
#[doc(hidden)]
unsafe fn from_arg_ptr(ptr: sys::GDExtensionTypePtr, call_type: PtrcallType) -> Self;
#[doc(hidden)]
unsafe fn move_return_ptr(self, dst: sys::GDExtensionTypePtr, call_type: PtrcallType);
}
#[doc(hidden)]
#[derive(Copy, Clone, Eq, PartialEq)]
pub enum ExtVariantType {
Variant,
Concrete(VariantType),
}
impl ExtVariantType {
pub const fn variant_as_nil(&self) -> VariantType {
match self {
ExtVariantType::Variant => VariantType::NIL,
ExtVariantType::Concrete(variant_type) => *variant_type,
}
}
}
#[derive(Default, Copy, Clone, Eq, PartialEq, Debug)]
#[doc(hidden)]
pub enum PtrcallType {
#[default]
Standard,
Virtual,
}
#[macro_export]
#[doc(hidden)]
macro_rules! ffi_methods_one {
(OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_from_sys:ident = new_from_sys) => {
$( #[$attr] )? $vis
unsafe fn $new_from_sys(ptr: <$Ptr as $crate::SysPtr>::Const) -> Self {
let opaque = std::ptr::read(ptr.cast());
let new = Self::from_opaque(opaque);
std::mem::forget(new.clone());
new
}
};
(OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_with_uninit:ident = new_with_uninit) => {
$( #[$attr] )? $vis
unsafe fn $new_with_uninit(init: impl FnOnce(<$Ptr as $crate::SysPtr>::Uninit)) -> Self {
let mut raw = std::mem::MaybeUninit::uninit();
init(raw.as_mut_ptr() as *mut _);
Self::from_opaque(raw.assume_init())
}
};
(OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_with_init:ident = new_with_init) => {
$( #[$attr] )? $vis
unsafe fn $new_with_init(init: impl FnOnce($Ptr)) -> Self {
let mut default = Self::default();
init(default.sys_mut().cast());
default
}
};
(OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $sys:ident = sys) => {
$( #[$attr] )? $vis
fn $sys(&self) -> <$Ptr as $crate::SysPtr>::Const {
std::ptr::from_ref(&self.opaque).cast()
}
};
(OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $sys_mut:ident = sys_mut) => {
$( #[$attr] )? $vis
fn $sys_mut(&mut self) -> $Ptr {
std::ptr::from_mut(&mut self.opaque).cast()
}
};
(OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $from_arg_ptr:ident = from_arg_ptr) => {
$( #[$attr] )? $vis
unsafe fn $from_arg_ptr(ptr: $Ptr, _call_type: $crate::PtrcallType) -> Self {
Self::new_from_sys(ptr.cast())
}
};
(OpaquePtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $move_return_ptr:ident = move_return_ptr) => {
$( #[$attr] )? $vis
unsafe fn $move_return_ptr(mut self, dst: $Ptr, _call_type: $crate::PtrcallType) {
std::ptr::swap(dst.cast(), std::ptr::addr_of_mut!(self.opaque))
}
};
(SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_from_sys:ident = new_from_sys) => {
$( #[$attr] )? $vis
unsafe fn $new_from_sys(ptr: <$Ptr as $crate::SysPtr>::Const) -> Self { unsafe {
let borrowed = &*ptr.cast::<Self>();
borrowed.clone()
}}
};
(SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_with_uninit:ident = new_with_uninit) => {
$( #[$attr] )? $vis
unsafe fn $new_with_uninit(init: impl FnOnce(<$Ptr as $crate::SysPtr>::Uninit)) -> Self { unsafe {
let mut raw = std::mem::MaybeUninit::<Self>::uninit();
init(raw.as_mut_ptr().cast());
raw.assume_init()
}}
};
(SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $new_with_init:ident = new_with_init) => {
$( #[$attr] )? $vis
unsafe fn $new_with_init(init: impl FnOnce($Ptr)) -> Self {
let mut default = Self::default();
init(default.sys_mut().cast());
default
}
};
(SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $sys:ident = sys) => {
$( #[$attr] )? $vis
fn $sys(&self) -> <$Ptr as $crate::SysPtr>::Const {
std::ptr::from_ref(self).cast()
}
};
(SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $sys_mut:ident = sys_mut) => {
$( #[$attr] )? $vis
fn $sys_mut(&mut self) -> $Ptr {
std::ptr::from_mut(self).cast()
}
};
(SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $from_arg_ptr:ident = from_arg_ptr) => {
$( #[$attr] )? $vis
unsafe fn $from_arg_ptr(ptr: $Ptr, _call_type: $crate::PtrcallType) -> Self { unsafe {
Self::new_from_sys(ptr.cast())
}}
};
(SelfPtr $Ptr:ty; $( #[$attr:meta] )? $vis:vis $move_return_ptr:ident = move_return_ptr) => {
$( #[$attr] )? $vis
unsafe fn $move_return_ptr(self, dst: $Ptr, _call_type: $crate::PtrcallType) { unsafe {
*(dst.cast::<Self>()) = self
}}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! ffi_methods_rest {
( // impl T: each method has a custom name and is annotated with 'pub'
$Impl:ident $Ptr:ty; $( fn $user_fn:ident = $sys_fn:ident; )*
) => {
$( $crate::ffi_methods_one!($Impl $Ptr; #[doc(hidden)] pub $user_fn = $sys_fn); )*
};
( // impl GodotFfi for T: methods have given names, no 'pub' needed
$Impl:ident $Ptr:ty; $( fn $sys_fn:ident; )*
) => {
$( $crate::ffi_methods_one!($Impl $Ptr; $sys_fn = $sys_fn); )*
};
( // impl GodotFfi for T (default all 5)
$Impl:ident $Ptr:ty; ..
) => {
$crate::ffi_methods_one!($Impl $Ptr; new_from_sys = new_from_sys);
$crate::ffi_methods_one!($Impl $Ptr; new_with_uninit = new_with_uninit);
$crate::ffi_methods_one!($Impl $Ptr; new_with_init = new_with_init);
$crate::ffi_methods_one!($Impl $Ptr; sys = sys);
$crate::ffi_methods_one!($Impl $Ptr; sys_mut = sys_mut);
$crate::ffi_methods_one!($Impl $Ptr; from_arg_ptr = from_arg_ptr);
$crate::ffi_methods_one!($Impl $Ptr; move_return_ptr = move_return_ptr);
};
}
#[macro_export]
macro_rules! ffi_methods {
( // Sys pointer = address of opaque
type $Ptr:ty = *mut Opaque;
$( $rest:tt )*
) => {
$crate::ffi_methods_rest!(OpaquePtr $Ptr; $($rest)*);
};
( // Sys pointer = address of self
type $Ptr:ty = *mut Self;
$( $rest:tt )*
) => {
$crate::ffi_methods_rest!(SelfPtr $Ptr; $($rest)*);
};
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub struct PrimitiveConversionError<From, Into> {
from: From,
into_ty: PhantomData<Into>,
}
impl<From, Into> PrimitiveConversionError<From, Into> {
pub fn new(from: From) -> Self {
Self {
from,
into_ty: PhantomData,
}
}
}
impl<From, Into> std::fmt::Display for PrimitiveConversionError<From, Into>
where
From: std::fmt::Display,
Into: std::fmt::Display,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"could not convert {} to type {}",
self.from,
std::any::type_name::<Into>()
)
}
}
impl<From, Into> std::error::Error for PrimitiveConversionError<From, Into>
where
From: std::fmt::Display + std::fmt::Debug,
Into: std::fmt::Display + std::fmt::Debug,
{
}
mod scalars {
use super::{ExtVariantType, GodotFfi};
use crate as sys;
unsafe impl GodotFfi for bool {
const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::BOOL);
ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
}
unsafe impl GodotFfi for i64 {
const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::INT);
ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
}
unsafe impl GodotFfi for f64 {
const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::FLOAT);
ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
}
unsafe impl GodotFfi for () {
const VARIANT_TYPE: ExtVariantType = ExtVariantType::Concrete(sys::VariantType::NIL);
unsafe fn new_from_sys(_ptr: sys::GDExtensionConstTypePtr) -> Self {
}
unsafe fn new_with_uninit(init: impl FnOnce(sys::GDExtensionUninitializedTypePtr)) -> Self {
let mut unit = ();
init(std::ptr::addr_of_mut!(unit).cast());
unit
}
unsafe fn new_with_init(init: impl FnOnce(sys::GDExtensionTypePtr)) -> Self {
let mut unit = ();
init(std::ptr::addr_of_mut!(unit).cast());
unit
}
fn sys(&self) -> sys::GDExtensionConstTypePtr {
std::ptr::from_ref(self).cast()
}
fn sys_mut(&mut self) -> sys::GDExtensionTypePtr {
std::ptr::from_mut(self).cast()
}
unsafe fn from_arg_ptr(
_ptr: sys::GDExtensionTypePtr,
_call_type: super::PtrcallType,
) -> Self {
}
unsafe fn move_return_ptr(
self,
_dst: sys::GDExtensionTypePtr,
_call_type: super::PtrcallType,
) {
}
}
}