Diffstat (limited to 'src/protocol.rs')
-rw-r--r--src/protocol.rs150
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 {