Skip to content

Commit

Permalink
Remove ToVariant, FromVariant, and VariantMetadata impls for pointers
Browse files Browse the repository at this point in the history
This commit splits SignatureTuple into two separate traits:
PtrcallSignatureTuple and VarcallSignatureTuple. The latter is a child
of the former. PtrcallSignatureTuple is used for ptrcall and only
demands GodotFuncMarshall of its arguments. VarcallSignatureTuple is
used for varcall and additionally demands ToVariant, FromVariant, and
VariantMetadata of its arguments, so pointers cannot benefit from the
optimizations provided by varcall over ptrcall.
  • Loading branch information
Mercerenies committed May 17, 2023
1 parent 4107ee6 commit 07f8d2e
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 92 deletions.
5 changes: 5 additions & 0 deletions godot-codegen/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,11 @@ fn to_rust_type_uncached(ty: &str, ctx: &mut Context) -> RustTy {
if is_const {
ty = ty.replace("const ", "");
}
// .trim() is necessary here, as the Godot extension API
// places a space between a type and its stars if it's a
// double pointer. That is, Godot writes "int*" but, if it's a
// double pointer, then it writes "int **" instead (with a
// space in the middle).
let inner_type = to_rust_type(ty.trim(), ctx);
return RustTy::RawPointer {
inner: Box::new(inner_type),
Expand Down
68 changes: 47 additions & 21 deletions godot-core/src/builtin/meta/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ use godot_ffi::VariantType;
use std::fmt::Debug;

#[doc(hidden)]
pub trait SignatureTuple {
type Params;
type Ret;

pub trait VarcallSignatureTuple: PtrcallSignatureTuple {
fn variant_type(index: i32) -> VariantType;
fn property_info(index: i32, param_name: &str) -> PropertyInfo;
fn param_metadata(index: i32) -> sys::GDExtensionClassMethodArgumentMetadata;
Expand All @@ -25,6 +22,12 @@ pub trait SignatureTuple {
func: fn(sys::GDExtensionClassInstancePtr, Self::Params) -> Self::Ret,
method_name: &str,
);
}

#[doc(hidden)]
pub trait PtrcallSignatureTuple {
type Params;
type Ret;

// Note: this method imposes extra bounds on GodotFfi, which may not be implemented for user types.
// We could fall back to varcalls in such cases, and not require GodotFfi categorically.
Expand Down Expand Up @@ -58,19 +61,16 @@ use crate::builtin::meta::*;
use crate::builtin::{FromVariant, ToVariant, Variant};
use crate::obj::GodotClass;

macro_rules! impl_signature_for_tuple {
macro_rules! impl_varcall_signature_for_tuple {
(
$R:ident
$(, $Pn:ident : $n:literal)*
) => {
#[allow(unused_variables)]
impl<$R, $($Pn,)*> SignatureTuple for ($R, $($Pn,)*)
impl<$R, $($Pn,)*> VarcallSignatureTuple for ($R, $($Pn,)*)
where $R: VariantMetadata + ToVariant + sys::GodotFuncMarshal + Debug,
$( $Pn: VariantMetadata + FromVariant + sys::GodotFuncMarshal + Debug, )*
{
type Params = ($($Pn,)*);
type Ret = $R;

#[inline]
fn variant_type(index: i32) -> sys::VariantType {
match index {
Expand Down Expand Up @@ -122,8 +122,23 @@ macro_rules! impl_signature_for_tuple {

varcall_return::<$R>(func(instance_ptr, args), ret, err)
}
}
};
}

macro_rules! impl_ptrcall_signature_for_tuple {
(
$R:ident
$(, $Pn:ident : $n:literal)*
) => {
#[allow(unused_variables)]
impl<$R, $($Pn,)*> PtrcallSignatureTuple for ($R, $($Pn,)*)
where $R: sys::GodotFuncMarshal + Debug,
$( $Pn: sys::GodotFuncMarshal + Debug, )*
{
type Params = ($($Pn,)*);
type Ret = $R;

#[inline]
unsafe fn ptrcall<C : GodotClass>(
instance_ptr: sys::GDExtensionClassInstancePtr,
args_ptr: *const sys::GDExtensionConstTypePtr,
Expand Down Expand Up @@ -219,14 +234,25 @@ fn return_error<R>(method_name: &str, arg: &impl Debug) -> ! {
panic!("{method_name}: return type {return_ty} is unable to store value {arg:?}",);
}

impl_signature_for_tuple!(R);
impl_signature_for_tuple!(R, P0: 0);
impl_signature_for_tuple!(R, P0: 0, P1: 1);
impl_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2);
impl_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3);
impl_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4);
impl_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5);
impl_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6);
impl_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6, P7: 7);
impl_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6, P7: 7, P8: 8);
impl_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6, P7: 7, P8: 8, P9: 9);
impl_varcall_signature_for_tuple!(R);
impl_ptrcall_signature_for_tuple!(R);
impl_varcall_signature_for_tuple!(R, P0: 0);
impl_ptrcall_signature_for_tuple!(R, P0: 0);
impl_varcall_signature_for_tuple!(R, P0: 0, P1: 1);
impl_ptrcall_signature_for_tuple!(R, P0: 0, P1: 1);
impl_varcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2);
impl_ptrcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2);
impl_varcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3);
impl_ptrcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3);
impl_varcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4);
impl_ptrcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4);
impl_varcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5);
impl_ptrcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5);
impl_varcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6);
impl_ptrcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6);
impl_varcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6, P7: 7);
impl_ptrcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6, P7: 7);
impl_varcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6, P7: 7, P8: 8);
impl_ptrcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6, P7: 7, P8: 8);
impl_varcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6, P7: 7, P8: 8, P9: 9);
impl_ptrcall_signature_for_tuple!(R, P0: 0, P1: 1, P2: 2, P3: 3, P4: 4, P5: 5, P6: 6, P7: 7, P8: 8, P9: 9);
68 changes: 0 additions & 68 deletions godot-core/src/builtin/variant/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,71 +263,3 @@ impl<T: EngineEnum> VariantMetadata for T {
sys::GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT32
}
}

impl<T> ToVariant for *mut T {
fn to_variant(&self) -> Variant {
(*self as i64).to_variant()
}
}

impl<T> ToVariant for *const T {
fn to_variant(&self) -> Variant {
(*self as i64).to_variant()
}
}

impl<T> FromVariant for *mut T {
fn try_from_variant(variant: &Variant) -> Result<Self, VariantConversionError> {
let n = i64::try_from_variant(variant)?;
Ok(n as Self)
}
}

impl<T> FromVariant for *const T {
fn try_from_variant(variant: &Variant) -> Result<Self, VariantConversionError> {
let n = i64::try_from_variant(variant)?;
Ok(n as Self)
}
}

impl<T> VariantMetadata for *mut T {
fn variant_type() -> VariantType {
VariantType::Int
}

fn property_info(property_name: &str) -> PropertyInfo {
PropertyInfo {
variant_type: Self::variant_type(),
class_name: Self::class_name(),
property_name: StringName::from(property_name),
hint: global::PropertyHint::PROPERTY_HINT_INT_IS_POINTER,
hint_string: GodotString::from("pointer"),
usage: global::PropertyUsageFlags::PROPERTY_USAGE_DEFAULT,
}
}

fn param_metadata() -> sys::GDExtensionClassMethodArgumentMetadata {
sys::GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64
}
}

impl<T> VariantMetadata for *const T {
fn variant_type() -> VariantType {
VariantType::Int
}

fn property_info(property_name: &str) -> PropertyInfo {
PropertyInfo {
variant_type: Self::variant_type(),
class_name: Self::class_name(),
property_name: StringName::from(property_name),
hint: global::PropertyHint::PROPERTY_HINT_INT_IS_POINTER,
hint_string: GodotString::from("pointer"),
usage: global::PropertyUsageFlags::PROPERTY_USAGE_DEFAULT,
}
}

fn param_metadata() -> sys::GDExtensionClassMethodArgumentMetadata {
sys::GDEXTENSION_METHOD_ARGUMENT_METADATA_INT_IS_INT64
}
}
4 changes: 2 additions & 2 deletions godot-core/src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ macro_rules! gdext_call_signature_method {
$method_name:ident,
$ptrcall_type:path
) => {
<Sig as $crate::builtin::meta::SignatureTuple>::ptrcall::<$Class>(
<Sig as $crate::builtin::meta::PtrcallSignatureTuple>::ptrcall::<$Class>(
$instance_ptr,
$args,
$ret,
Expand All @@ -79,7 +79,7 @@ macro_rules! gdext_call_signature_method {
$func:expr,
$method_name:ident
) => {
<Sig as $crate::builtin::meta::SignatureTuple>::varcall::<$Class>(
<Sig as $crate::builtin::meta::VarcallSignatureTuple>::varcall::<$Class>(
$instance_ptr,
$args,
$ret,
Expand Down
2 changes: 1 addition & 1 deletion itest/rust/src/native_structures_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ impl TextServerExtensionVirtual for TestTextServer {
}

#[itest]
fn test_native_structures() {
fn test_native_structures_codegen() {
// Test construction of a few simple types.
let _ = AudioFrame {
left: 0.0,
Expand Down

0 comments on commit 07f8d2e

Please sign in to comment.