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