use std::{any::Any, sync::Arc};
fn static_zst<T: Message + 'static>() -> MessagePtr {
let reference: &'static T = unsafe { &*std::ptr::NonNull::<T>::dangling().as_ptr() };
MessagePtr::Static(reference)
}
pub trait Message: Any + Send + Sync {
fn virtual_size(&self) -> usize {
usize::default()
}
}
#[derive(Clone)]
pub enum MessagePtr {
Shared(Arc<dyn Message>),
Static(&'static dyn Message),
}
impl MessagePtr {
pub fn new<T: Message + 'static>(msg: T) -> Self {
if std::mem::size_of::<T>() == 0 {
static_zst::<T>()
} else {
MessagePtr::Shared(Arc::new(msg))
}
}
fn as_dyn(&self) -> &dyn Message {
match self {
MessagePtr::Shared(arc) => &**arc,
MessagePtr::Static(r) => *r,
}
}
pub fn try_as_type<T: 'static>(&self) -> Option<&T> {
(self.as_dyn() as &dyn Any).downcast_ref::<T>()
}
pub fn is<T: 'static>(&self) -> bool {
self.try_as_type::<T>().is_some()
}
pub fn as_type<T: 'static>(&self) -> &T {
self.try_as_type::<T>().expect("Failed as_type")
}
pub fn virtual_size(&self) -> usize {
self.as_dyn().virtual_size()
}
}