Diffstat (limited to 'src/protocol.rs')
-rw-r--r--src/protocol.rs103
1 files changed, 34 insertions, 69 deletions
diff --git a/src/protocol.rs b/src/protocol.rs
index 8511c46..0c20eec 100644
--- a/src/protocol.rs
+++ b/src/protocol.rs
@@ -33,51 +33,14 @@
//! This is done via the help of the [`AnyImpl`] type. This is not required for the core
//! idea of DIDETs.
-/// Type nameable trait.
-///
-/// Traits cannot by named in the type system. Trait objects can. However,
-/// trait objects are not always `'static` so don't always have a
-/// [`TypeId`][core::any::TypeId]. This trait provides a way to name a trait object
-/// in the type system and with a `TypeId` even if it contains lifetimes.
-///
-/// [`Protocol`] should be implemented on a marker type that is `'static`.
-/// [`Protocol`] then gives a mapping from that marker type to a trait object
-/// given by [`Protocol::Object`]. Its recommended to use uninhabited marker
-/// types when possible as the marker never needs to exist as a value.
-///
-/// The `'ctx` lifetime is a lifetime the trait object can contain. The `'a` lifetime
-/// is the lifetime of a reference to the trait object. As such, the trait object
-/// needs to live for at least `'a`.
-///
-/// ```
-/// // Some trait we want to use as a protocol.
-/// trait MyTrait<'ctx> {}
-///
-/// // Type to name MyTrait in the type system.
-/// enum MyTraitProtocol {}
-///
-/// // By implementing this we map MyTraitProtocol to MyTrait.
-/// impl Protocol for MyTraitProtocol {
-/// type Object<'a, 'ctx: 'a> = dyn MyTrait<'ctx> + 'a;
-/// }
-/// ```
-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
- /// required lifetime of the trait object.
- ///
- /// 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>: ?Sized where 'ctx: 'a;
-}
+use crate::any::{IndirectLtAny, LtAny, LtTypeId, Mut, Ref, TypeNameable};
pub trait Implementer<'ctx> {
- fn interface(&self, id: LtTypeId<'ctx>) -> Option<&dyn LtAny<'ctx>>;
+ fn interface(&self, id: LtTypeId<'ctx>) -> Option<IndirectLtAny<'_, 'ctx, Ref>>;
}
pub trait ImplementerMut<'ctx> {
- fn interface_mut(&mut self, id: LtTypeId<'ctx>) -> Option<&mut dyn LtAny<'ctx>>;
+ fn interface_mut<'a>(&'a mut self, id: LtTypeId<'ctx>) -> Option<IndirectLtAny<'a, 'ctx, Mut>> where 'ctx: 'a;
}
/// Extension trait for getting the implementation of a protocol.
@@ -87,23 +50,23 @@ pub trait ImplementerMutExt<'ctx>: ImplementerMut<'ctx> {
/// This wraps [`Implementer::interface`] and [`AnyImpl::downcast`].
/// If [`Implementer::interface`] returns a [`AnyImpl`] for the wrong protocol then a panic is
/// generated.
- fn interface_mut_for<'a, P: Protocol<'ctx>>(&'a mut self) -> Option<&'a mut P::Object<'a>>
- where
+ fn interface_mut_for<'a, P: TypeNameable<'a, 'ctx>>(&'a mut self) -> Option<&'a mut P>
+ where
'ctx: 'a;
}
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,
+ fn interface_mut_for<'a, P: TypeNameable<'a, 'ctx>>(&'a mut self) -> Option<&'a mut P>
+ where
+ 'ctx: 'a
{
match self.interface_mut(LtTypeId::of::<P>()) {
- Some(interface) => match interface.downcast_mut::<P::Object<'a>>() {
- Some(implementation) => Some(implementation),
- None => panic!(
+ Some(interface) => match interface.downcast::<P>() {
+ Ok(implementation) => Some(implementation),
+ Err(interface) => panic!(
"unexpected protocol implementation: `{:?}`, expected: `{:?}`",
interface.id(),
- P::id()
+ LtTypeId::of::<P>()
),
},
None => None,
@@ -116,17 +79,20 @@ impl<'ctx, T: ImplementerMut<'ctx> + ?Sized> ImplementerMutExt<'ctx> for T {
#[macro_export]
macro_rules! implementer {
{
- impl[$ctx:lifetime $($generic:tt)*] $name:ty = [$($protocol:ty),* $(,)?];
+ impl[$a:lifetime, $ctx:lifetime $($generic:tt)*] $name:ty = [$($protocol:ty),* $(,)?];
} => {
- impl<$ctx $($generic)*> $crate::protocol::Implementer<$ctx> for $name {
+ impl<$ctx $($generic)*> $crate::protocol::ImplementerMut<$ctx> for $name {
#[inline]
- fn interface(
- &mut self,
- id: $crate::protocol::ProtocolId
- ) -> ::core::option::Option<$crate::protocol::AnyObject<'_, $ctx>> {
+ fn interface_mut<$a>(
+ &$a mut self,
+ id: $crate::any::LtTypeId<$ctx>
+ ) -> ::core::option::Option<$crate::any::IndirectLtAny<$a, $ctx, $crate::any::Mut>>
+ where
+ $ctx: $a
+ {
match id {
- $(id if id == $crate::protocol::ProtocolId::of::<$protocol>()
- => Some($crate::protocol::AnyObject::new::<$protocol>(self)),)*
+ $(id if id == $crate::any::LtTypeId::of::<$protocol>()
+ => Some($crate::any::IndirectLtAny::<$a, $ctx, _>::new::<$protocol>(self as _)),)*
_ => None
}
}
@@ -136,30 +102,29 @@ macro_rules! implementer {
#[doc(inline)]
pub use implementer;
-use crate::any::{LtTypeId, LtAny, TypeNameable};
-
#[cfg(test)]
mod test {
+ use crate::nameable;
+
use super::*;
#[test]
fn implementer_macro() {
- struct X<T>(T);
-
- enum Y {}
-
trait Z {}
- impl Protocol for Y {
- type Object<'a, 'ctx> = dyn Z + 'a;
+ nameable! {
+ ['a, 'ctx]
+ dyn Z + 'a where {'ctx: 'a}
}
+ struct X<T>(T);
+
+ impl<T: Clone> Z for X<T> {}
+
implementer! {
- impl['ctx, T: Clone] X<T> = [
- Y
+ impl['a, 'ctx, T: Clone] X<T> = [
+ dyn Z + 'a
];
}
-
- impl<T: Clone> Z for X<T> {}
}
}