1use std::any::TypeId;
2use std::fmt;
3use std::sync::atomic::{AtomicU64, Ordering};
4
5use mm1_address::address::Address;
6pub use mm1_proc_macros::dispatch;
7use mm1_proto::Message;
8
9use crate::message::AnyMessage;
10
11static ENVELOPE_SEQ_NO: AtomicU64 = AtomicU64::new(0);
12
13#[derive(Debug)]
14pub struct EnvelopeHeader {
15 pub to: Address,
16 #[allow(dead_code)]
17 no: u64,
18 #[allow(dead_code)]
19 trace_id: Option<u64>,
20 #[allow(dead_code)]
21 correlation_id: Option<u64>,
22}
23
24pub struct Envelope<M = AnyMessage> {
25 header: EnvelopeHeader,
26 message: M,
27}
28
29impl EnvelopeHeader {
30 pub fn to_address(to: Address) -> Self {
31 Self {
32 to,
33 no: ENVELOPE_SEQ_NO.fetch_add(1, Ordering::Relaxed),
34 trace_id: None,
35 correlation_id: None,
36 }
37 }
38}
39
40impl<M> Envelope<M>
41where
42 M: Message,
43{
44 pub fn into_erased(self) -> Envelope<AnyMessage> {
45 let Self {
46 header: info,
47 message,
48 } = self;
49 let message = AnyMessage::new(message);
50 Envelope {
51 header: info,
52 message,
53 }
54 }
55}
56
57impl<M> Envelope<M> {
58 pub fn new(header: EnvelopeHeader, message: M) -> Self {
59 Self { header, message }
60 }
61
62 pub fn header(&self) -> &EnvelopeHeader {
63 &self.header
64 }
65}
66
67impl Envelope<AnyMessage> {
68 pub fn cast<M>(self) -> Result<Envelope<M>, Self>
69 where
70 M: Message,
71 {
72 let Self {
73 header: info,
74 message,
75 } = self;
76 match message.cast() {
77 Ok(message) => {
78 Ok(Envelope {
79 header: info,
80 message,
81 })
82 },
83 Err(message) => {
84 Err(Self {
85 header: info,
86 message,
87 })
88 },
89 }
90 }
91
92 pub fn peek<M>(&self) -> Option<&M>
93 where
94 M: Message,
95 {
96 self.message.peek()
97 }
98
99 pub fn is<M>(&self) -> bool
100 where
101 M: Message,
102 {
103 self.message.is::<M>()
104 }
105
106 pub fn tid(&self) -> TypeId {
107 self.message.tid()
108 }
109
110 pub fn message_name(&self) -> &'static str {
111 self.message.type_name()
112 }
113}
114impl<M> Envelope<M> {
115 pub fn take(self) -> (M, Envelope<()>) {
116 (
117 self.message,
118 Envelope {
119 header: self.header,
120 message: (),
121 },
122 )
123 }
124}
125
126impl<M> fmt::Debug for Envelope<M>
127where
128 M: fmt::Debug,
129{
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 f.debug_struct("Envelope")
132 .field("info", &self.header)
133 .field("message", &self.message)
134 .finish()
135 }
136}