1use std::any::{Any, TypeId};
2use std::fmt;
3
4pub use mm1_proto::Message;
5
6pub struct AnyMessage {
7 message: Box<dyn Any + Send + 'static>,
8 info: TypeInfo,
9}
10
11struct TypeInfo {
12 id: TypeId,
13 name: &'static str,
14}
15
16impl AnyMessage {
17 pub fn new<T>(value: T) -> Self
18 where
19 T: Message,
20 {
21 let info = TypeInfo {
22 id: std::any::TypeId::of::<T>(),
23 name: std::any::type_name::<T>(),
24 };
25 let message = Box::new(value);
26 Self { info, message }
27 }
28
29 pub fn peek<T>(&self) -> Option<&T>
30 where
31 T: Message,
32 {
33 self.message.downcast_ref()
34 }
35
36 pub fn cast<T>(self) -> Result<T, Self>
37 where
38 T: Message,
39 {
40 let Self { message, info } = self;
41 message
42 .downcast()
43 .map(|b| *b)
44 .map_err(move |message| Self { info, message })
45 }
46
47 pub fn is<T>(&self) -> bool
48 where
49 T: Message,
50 {
51 self.message.is::<T>()
52 }
53
54 pub fn tid(&self) -> TypeId {
55 self.info.id
56 }
57
58 pub fn type_name(&self) -> &'static str {
59 self.info.name
60 }
61}
62
63impl fmt::Debug for AnyMessage {
64 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65 f.debug_struct("AnyMessage")
66 .field("type_name", &self.type_name())
67 .field("type_id", &self.tid())
68 .finish()
69 }
70}