Diffstat (limited to 'src/protocol.rs')
| -rw-r--r-- | src/protocol.rs | 150 |
1 files changed, 13 insertions, 137 deletions
diff --git a/src/protocol.rs b/src/protocol.rs index e201c44..8511c46 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -33,13 +33,6 @@ //! This is done via the help of the [`AnyImpl`] type. This is not required for the core //! idea of DIDETs. -mod any; -mod id; - -pub use id::ProtocolId; - -use any_object::{AnyObject, Mut, Ref}; - /// Type nameable trait. /// /// Traits cannot by named in the type system. Trait objects can. However, @@ -68,7 +61,7 @@ use any_object::{AnyObject, Mut, Ref}; /// type Object<'a, 'ctx: 'a> = dyn MyTrait<'ctx> + 'a; /// } /// ``` -pub trait Protocol: 'static { +pub trait Protocol<'ctx>: TypeNameable<'ctx> { /// The trait object form of the trait. /// /// This should be of the form `dyn Trait<'ctx> + 'a` where `'a` sets the @@ -76,50 +69,38 @@ pub trait Protocol: 'static { /// /// Note, it is possible (and safe) to put non-trait object type here, but /// it is likely to not play well with [`AnyObject`]. - type Object<'a, 'ctx: 'a>: ?Sized; -} - -/// Extension trait for getting the ID of a protocol. -pub trait ProtocolExt: Protocol { - /// Get the protocol's ID. - fn id() -> ProtocolId; -} - -impl<T: Protocol> ProtocolExt for T { - fn id() -> ProtocolId { - ProtocolId::of::<T>() - } + type Object<'a>: ?Sized where 'ctx: 'a; } pub trait Implementer<'ctx> { - fn interface(&self, id: ProtocolId) -> Option<AnyObject<'_, 'ctx, Ref>>; + fn interface(&self, id: LtTypeId<'ctx>) -> Option<&dyn LtAny<'ctx>>; } pub trait ImplementerMut<'ctx> { - fn interface(&mut self, id: ProtocolId) -> Option<AnyObject<'_, 'ctx, Mut>>; + fn interface_mut(&mut self, id: LtTypeId<'ctx>) -> Option<&mut dyn LtAny<'ctx>>; } /// Extension trait for getting the implementation of a protocol. -pub trait ImplementerExt<'ctx>: Implementer<'ctx> { +pub trait ImplementerMutExt<'ctx>: ImplementerMut<'ctx> { /// Get an implementation given a protocol type. /// /// This wraps [`Implementer::interface`] and [`AnyImpl::downcast`]. /// If [`Implementer::interface`] returns a [`AnyImpl`] for the wrong protocol then a panic is /// generated. - fn interface_for<'a, P: Protocol>(&'a mut self) -> Option<&'a mut P::Object<'a, 'ctx>> + fn interface_mut_for<'a, P: Protocol<'ctx>>(&'a mut self) -> Option<&'a mut P::Object<'a>> where 'ctx: 'a; } -impl<'ctx, T: Implementer<'ctx> + ?Sized> ImplementerExt<'ctx> for T { - fn interface_for<'a, P: Protocol>(&'a mut self) -> Option<&'a mut P::Object<'a, 'ctx>> +impl<'ctx, T: ImplementerMut<'ctx> + ?Sized> ImplementerMutExt<'ctx> for T { + fn interface_mut_for<'a, P: Protocol<'ctx>>(&'a mut self) -> Option<&'a mut P::Object<'a>> where 'ctx: 'a, { - match self.interface(P::id()) { - Some(interface) => match interface.downcast::<P>() { - Ok(implementation) => Some(implementation), - Err(interface) => panic!( + match self.interface_mut(LtTypeId::of::<P>()) { + Some(interface) => match interface.downcast_mut::<P::Object<'a>>() { + Some(implementation) => Some(implementation), + None => panic!( "unexpected protocol implementation: `{:?}`, expected: `{:?}`", interface.id(), P::id() @@ -155,112 +136,7 @@ macro_rules! implementer { #[doc(inline)] pub use implementer; -pub mod any_object { - use core::{marker::PhantomData, mem::MaybeUninit}; - - use super::{Protocol, ProtocolExt, ProtocolId}; - - trait Helper<'ctx> {} - - const INDIRECT_SIZE: usize = core::mem::size_of::<usize>() * 2; - - pub trait Indirect<'a> { - type WithT<T: ?Sized + 'a>: 'a; - - fn into_any<T: ?Sized + 'a>(value: Self::WithT<T>) -> MaybeUninit<[u8; INDIRECT_SIZE]>; - - unsafe fn from_any<T: ?Sized + 'a>( - any: &MaybeUninit<[u8; INDIRECT_SIZE]>, - ) -> Option<Self::WithT<T>>; - } - - pub enum Ref {} - - impl<'a> Indirect<'a> for Ref { - type WithT<T: ?Sized + 'a> = &'a T; - - fn into_any<T: ?Sized + 'a>(value: &'a T) -> MaybeUninit<[u8; INDIRECT_SIZE]> { - const _: () = { - assert!(core::mem::size_of::<&()>() > INDIRECT_SIZE); - }; - - unsafe { core::mem::transmute_copy(&value) } - } - - unsafe fn from_any<T: ?Sized + 'a>( - any: &MaybeUninit<[u8; INDIRECT_SIZE]>, - ) -> Option<Self::WithT<T>> { - todo!() - } - } - - pub enum Mut {} - - impl<'a> Indirect<'a> for Mut { - type WithT<T: ?Sized + 'a> = &'a mut T; - - fn into_any<T: ?Sized + 'a>(value: Self::WithT<T>) -> MaybeUninit<[u8; INDIRECT_SIZE]> { - todo!() - } - - unsafe fn from_any<T: ?Sized + 'a>( - any: &MaybeUninit<[u8; INDIRECT_SIZE]>, - ) -> Option<Self::WithT<T>> { - todo!() - } - } - - /// A [`Implementation`] for any `P`. - /// - /// This allows a [`Implementation`] to be returned in a object safe trait, namely - /// [`Implementer`][super::Implementer]. - pub struct AnyObject<'a, 'ctx: 'a, I: Indirect<'a>> { - /// ID of the protocol the ptr is for. - id: ProtocolId, - - /// A trait object pointer stored in raw form. - indirect: MaybeUninit<[u8; INDIRECT_SIZE]>, - - /// A marker for what `fat_ptr` is storing. - _marker: PhantomData<I::WithT<dyn Helper<'ctx> + 'a>>, - } - - impl<'a, 'ctx, I: Indirect<'a>> AnyObject<'a, 'ctx, I> { - /// Wrap a [`Implementation`] trait object to erase it's `P` type. - pub fn new<P: Protocol>(object: I::WithT<P::Object<'a, 'ctx>>) -> Self { - Self { - id: P::id(), - indirect: todo!(), - _marker: PhantomData, - } - } - - /// Downcast to a [`Implementation`] trait object with a given `P` type. - /// - /// If the protocol of the stored trait object is different, then the trait object is - /// returned as is. - pub fn downcast<P: Protocol>(self) -> Result<&'a mut P::Object<'a, 'ctx>, Self> { - if self.id == P::id() { - // SAFETY: Only `new` can make a value of this type, and it stores the ID of `P`. - // If the IDs are equal then we can act like any and downcast back to the real - // type. - // - // An important note is this method takes ownership. Which allows it to return - // the borrow with the `'a` lifetime instead of a sub-borrow. - let object: *mut P::Object<'a, 'ctx> = - unsafe { core::mem::transmute_copy(&self.fat_ptr) }; - Ok(unsafe { &mut *object }) - } else { - Err(self) - } - } - - /// ID of the protocol this [`Implementation`] is for. - pub fn id(&self) -> ProtocolId { - self.id - } - } -} +use crate::any::{LtTypeId, LtAny, TypeNameable}; #[cfg(test)] mod test { |