Rantanen / intercom

Object based cross-language FFI for Rust
MIT License
63 stars 7 forks source link

Attempt to get rid of #[feature(fundamental)] #78

Closed Rantanen closed 5 years ago

Rantanen commented 5 years ago

Currently we need #[feature(fundamental)] to be able to impl Deref for ComItf<IComInterface> in the user crate as neither Deref or ComItf are user types.

I'm not even sure why we really need this impl as ideally we'd want to move that impl into Intercom crate so that the type system has some sort of an idea that any ComItf<T> can act as if it was a trait object &T.

I believe the following architecture might achieve that last part without needing fundamental:


// Library crate:

type RawComPtr = *mut std::os::raw::c_void;

// The basic ComItf container.
struct ComItf<T : ?Sized> {
    ptr : RawComPtr,
    phantom : std::marker::PhantomData<T>,
}

// Trait for COM interface traits.
// Handles turning a ComItf<T> into a T reference.
trait ComDelegate {
    fn wrap( ptr : &ComItf<Self> ) -> &Self;
}

// Allow Deref into trait for the ComItf.
// Works as long as the trait implements ComDelegate, which is used for wrapping.
impl<T: ComDelegate + ?Sized> std::ops::Deref for ComItf<T> {

    type Target = T;
    fn deref( &self ) -> &Self::Target {
        T::wrap( &self )
    }
}

// User crate:

// Normal trait.
trait IFoo {
    fn bar( &self, a : u32 ) -> u32;
}

// Impl ComDelegate (intercom type) for user trait.
// No need for #[feature(fundamental)]
impl ComDelegate for IFoo {
    fn wrap( ptr : &ComItf<IFoo> ) -> &(dyn IFoo + 'static) {
        ptr
    }
}

// Impl IFoo (user trait) for ComItf<IFoo>.
// No need for #[feature(fundamental)]
impl IFoo for ComItf<IFoo> {
    fn bar( &self, a : u32 ) -> u32 {
        ( self.ptr as usize + a as usize ) as u32
    }
}

fn main() {

    let ptr : RawComPtr = 1234 as RawComPtr;
    let itf = ComItf::<IFoo> { ptr, phantom: std::marker::PhantomData };
    println!( "{}", itf.bar( 10 ) );
}
Rantanen commented 5 years ago

Fixed in #80