Skip to content

Commit

Permalink
Removed dependency on mopa and instead use same implementation as std…
Browse files Browse the repository at this point in the history
…::any::Any.
  • Loading branch information
fdeantoni committed Jan 10, 2023
1 parent 8b348ba commit f50b938
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 6 deletions.
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,4 @@ serde = "1.0"
serde_json = "1.0"
serde_derive = "1.0"
chrono = { version = "0.4", default-features = false, features = ["serde"] }
mopa = "0.2.2"
typetag = "0.2"
73 changes: 68 additions & 5 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
#[macro_use]
extern crate mopa;

pub use inventory;

pub use typetag;

/// Trait to support serialization and deserialization of `prost` messages.
#[typetag::serde(tag = "@type")]
pub trait MessageSerde: prost::Message + mopa::Any {
pub trait MessageSerde: prost::Message + std::any::Any {
/// message name as in proto file
fn message_name(&self) -> &'static str;
/// package name as in proto file
Expand All @@ -23,7 +20,73 @@ pub trait MessageSerde: prost::Message + mopa::Any {
fn try_encoded(&self) -> Result<Vec<u8>, prost::EncodeError>;
}

mopafy!(MessageSerde);
/// The implementation here is a direct copy of the `impl dyn` of [`std::any::Any`]!
impl dyn MessageSerde {
/// Returns `true` if the inner type is the same as `T`.
#[inline]
pub fn is<T: MessageSerde>(&self) -> bool {
// Get `TypeId` of the type this function is instantiated with.
let t = std::any::TypeId::of::<T>();

// Get `TypeId` of the type in the trait object (`self`).
let concrete = self.type_id();

// Compare both `TypeId`s on equality.
t == concrete
}

/// Returns some reference to the inner value if it is of type `T`, or
/// `None` if it isn't.
#[inline]
pub fn downcast_ref<T: MessageSerde>(&self) -> Option<&T> {
if self.is::<T>() {
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
// that check for memory safety because we have implemented Any for all types; no other
// impls can exist as they would conflict with our impl.
unsafe { Some(self.downcast_ref_unchecked()) }
} else {
Option::None
}
}

/// Returns some mutable reference to the boxed value if it is of type `T`,
/// or `None` if it isn't.
#[inline]
pub fn downcast_mut<T: MessageSerde>(&mut self) -> Option<&mut T> {
if self.is::<T>() {
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
// that check for memory safety because we have implemented Any for all types; no other
// impls can exist as they would conflict with our impl.
unsafe { Some(self.downcast_mut_unchecked()) }
} else {
Option::None
}
}

/// Returns a reference to the inner value as type `dyn T`.
///
/// # Safety
///
/// The contained value must be of type `T`. Calling this method
/// with the incorrect type is *undefined behavior*.
#[inline]
pub unsafe fn downcast_ref_unchecked<T: MessageSerde>(&self) -> &T {
debug_assert!(self.is::<T>());
// SAFETY: caller guarantees that T is the correct type
unsafe { &*(self as *const dyn MessageSerde as *const T) }
}

/// Returns a mutable reference to the inner value as type `dyn T`.
///
/// # Safety
///
/// The contained value must be of type `T`. Calling this method
/// with the incorrect type is *undefined behavior*.
#[inline]
pub unsafe fn downcast_mut_unchecked<T: MessageSerde>(&mut self) -> &mut T {
&mut *(self as *mut Self as *mut T)
}
}

type MessageSerdeDecoderFn = fn(&[u8]) -> Result<Box<dyn MessageSerde>, ::prost::DecodeError>;

Expand Down

0 comments on commit f50b938

Please sign in to comment.