Diffstat (limited to 'src/protocol.rs')
| -rw-r--r-- | src/protocol.rs | 37 |
1 files changed, 24 insertions, 13 deletions
diff --git a/src/protocol.rs b/src/protocol.rs index 2535449..124d270 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -1,13 +1,24 @@ -use core::any::{Any, TypeId}; +mod id; pub use any_implementation::AnyImpl; +pub use id::ProtocolId; -pub trait Protocol: Any { +pub trait Protocol: 'static { type Object<'a, 'ctx: 'a>; } +pub trait ProtocolExt: Protocol { + fn id() -> ProtocolId; +} + +impl<T: Protocol> ProtocolExt for T { + fn id() -> ProtocolId { + ProtocolId::of::<T>() + } +} + pub trait Implementer<'ctx> { - fn interface(&mut self, id: TypeId) -> Option<AnyImpl<'_, 'ctx>>; + fn interface(&mut self, id: ProtocolId) -> Option<AnyImpl<'_, 'ctx>>; } pub trait Implementation<'ctx, P: Protocol> { @@ -20,13 +31,13 @@ pub trait ImplementerExt<'ctx>: Implementer<'ctx> { impl<'ctx, T: Implementer<'ctx> + ?Sized> ImplementerExt<'ctx> for T { fn interface_for<P: Protocol>(&mut self) -> Option<&mut dyn Implementation<'ctx, P>> { - match self.interface(TypeId::of::<P>()) { + match self.interface(P::id()) { Some(interface) => match interface.downcast::<P>() { Ok(implementation) => Some(implementation), Err(interface) => panic!( "unexpected type ID for protocol implementation: `{:?}`, expected: `{:?}`", interface.id(), - TypeId::of::<P>() + P::id() ), }, None => None, @@ -42,9 +53,9 @@ macro_rules! implementer { } => { impl<$ctx $($generic)*> $crate::protocol::Implementer<$ctx> for $name { #[inline] - fn interface(&mut self, id: ::core::any::TypeId) -> ::core::option::Option<$crate::protocol::AnyImpl<'_, $ctx>> { + fn interface(&mut self, id: $crate::protocol::ProtocolId) -> ::core::option::Option<$crate::protocol::AnyImpl<'_, $ctx>> { match id { - $(id if id == ::core::any::TypeId::of::<$protocol>() => Some($crate::protocol::AnyImpl::new::<$protocol>(self)),)* + $(id if id == $crate::protocol::ProtocolId::of::<$protocol>() => Some($crate::protocol::AnyImpl::new::<$protocol>(self)),)* _ => None } } @@ -75,16 +86,16 @@ macro_rules! implementer { pub use implementer; mod any_implementation { - use core::{any::TypeId, marker::PhantomData, mem::MaybeUninit}; + use core::{marker::PhantomData, mem::MaybeUninit}; - use super::{Implementation, Protocol}; + use super::{Implementation, Protocol, ProtocolExt, ProtocolId}; trait ErasedImplementation<'ctx> {} const DYN_PTR_SIZE: usize = core::mem::size_of::<&mut dyn ErasedImplementation<'static>>(); pub struct AnyImpl<'a, 'ctx> { - id: TypeId, + id: ProtocolId, fat_ptr: MaybeUninit<[u8; DYN_PTR_SIZE]>, _marker: PhantomData<&'a mut dyn ErasedImplementation<'ctx>>, } @@ -92,7 +103,7 @@ mod any_implementation { impl<'a, 'ctx> AnyImpl<'a, 'ctx> { pub fn new<P: Protocol>(implementation: &'a mut dyn Implementation<'ctx, P>) -> Self { Self { - id: TypeId::of::<P>(), + id: P::id(), // SAFETY: A maybe uninit array of bytes can hold any pointer. // Additionally, transmute makes sure the size is correct. fat_ptr: unsafe { core::mem::transmute(implementation) }, @@ -101,7 +112,7 @@ mod any_implementation { } pub fn downcast<P: Protocol>(self) -> Result<&'a mut dyn Implementation<'ctx, P>, Self> { - if self.id == TypeId::of::<P>() { + 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. @@ -114,7 +125,7 @@ mod any_implementation { } } - pub fn id(&self) -> TypeId { + pub fn id(&self) -> ProtocolId { self.id } } |