Trait UniformObjectDeref

pub trait UniformObjectDeref<Declarer>: GodotClass {
    type TargetRef<'a>: Deref<Target = Self>;
    type TargetMut<'a>: DerefMut<Target = Self>;

    // Required methods
    fn object_as_ref<'a>(gd: &'a Gd<Self>) -> Self::TargetRef<'a>;
    fn object_as_mut<'a>(gd: &'a mut Gd<Self>) -> Self::TargetMut<'a>;
}
Expand description

Unifies dereferencing of user and engine classes, as &T/&mut T and Gd<T>.

This is mainly used by the connect_* functions of TypedSignal.

§Motivation

Although both user and engine classes are often wrapped in a Gd<T>, dereferencing them is done differently depending on whether they are made by the user or engine:

  • Gd<EngineClass> can be deref-ed directly into &EngineClass and &mut EngineClass.
  • Gd<UserClass> must first go through bind()/bind_mut(), which can finally be deref-ed into &UserClass and &mut UserClass, respectively.

Without this trait, there’s no clear/generic way of writing functions that can accept both user and engine classes, but need to deref said classes in some way.

UniformObjectDeref solves this by explicitly handling each category in a different way, but still resulting in a variable that can be deref-ed into &T/&mut T.

§Generic param Declarer

Rustc does not acknowledge associated type bounds when checking for overlapping impls, this parameter is essentially used to create 2 different traits, one for each “category” (user or engine).

Despite being 2 different traits, a function can accept both by simply being generic over Declarer:

use godot::meta::UniformObjectDeref;

fn abstract_over_objects<Declarer, C>(obj: &Gd<C>)
where
    C: UniformObjectDeref<Declarer>,
{
    let ref_provider = UniformObjectDeref::object_as_ref(obj);
    let obj_ref: &C = & *ref_provider;
    // Regardless of `Declarer`, we can still deref, since the bounds on
    // `TargetRef`/`TargetMut` enforce that.
}

#[derive(GodotClass)]
#[class(init)]
struct MyClass {
    _base: Base<RefCounted>
}

fn main() {
    let engine_obj: Gd<RefCounted> = RefCounted::new_gd();
    let user_obj: Gd<MyClass> = MyClass::new_gd();

    abstract_over_objects(&engine_obj);
    abstract_over_objects(&user_obj);
}

Required Associated Types§

type TargetRef<'a>: Deref<Target = Self>

type TargetMut<'a>: DerefMut<Target = Self>

Required Methods§

fn object_as_ref<'a>(gd: &'a Gd<Self>) -> Self::TargetRef<'a>

fn object_as_mut<'a>(gd: &'a mut Gd<Self>) -> Self::TargetMut<'a>

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementors§

§

impl<T> UniformObjectDeref<DeclEngine> for T
where T: GodotClass<Declarer = DeclEngine>,

§

type TargetRef<'a> = Gd<T>

§

type TargetMut<'a> = Gd<T>

§

impl<T> UniformObjectDeref<DeclUser> for T
where T: WithBaseField,

§

type TargetRef<'a> = GdRef<'a, T>

§

type TargetMut<'a> = GdMut<'a, T>