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;
10use crate::tracing::TraceId;
11
12static ENVELOPE_SEQ_NO: AtomicU64 = AtomicU64::new(0);
13
14const DEFAULT_TTL: u8 = 15;
15
16#[derive(Debug)]
17pub struct EnvelopeHeader {
18 pub to: Address,
19 pub ttl: u8,
20 pub priority: bool,
21 pub no: u64,
22 pub trace_id: TraceId,
23}
24
25pub struct Envelope<M = AnyMessage> {
26 header: EnvelopeHeader,
27 message: M,
28}
29
30impl EnvelopeHeader {
31 pub fn to_address(to: Address) -> Self {
32 Self {
33 to,
34 no: ENVELOPE_SEQ_NO.fetch_add(1, Ordering::Relaxed),
35 priority: false,
36 ttl: DEFAULT_TTL,
37 trace_id: TraceId::current(),
38 }
39 }
40
41 pub fn with_ttl(self, ttl: u8) -> Self {
42 Self { ttl, ..self }
43 }
44
45 pub fn with_trace_id(self, trace_id: TraceId) -> Self {
46 Self { trace_id, ..self }
47 }
48
49 pub fn with_priority(self, priority: bool) -> Self {
50 Self { priority, ..self }
51 }
52
53 pub fn with_no(self, no: u64) -> Self {
54 Self { no, ..self }
55 }
56
57 pub fn trace_id(&self) -> TraceId {
58 self.trace_id
59 }
60}
61
62impl<M> Envelope<M>
63where
64 M: Message,
65{
66 pub fn into_erased(self) -> Envelope<AnyMessage> {
67 let Self {
68 header: info,
69 message,
70 } = self;
71 let message = AnyMessage::new(message);
72 Envelope {
73 header: info,
74 message,
75 }
76 }
77}
78
79impl<M> Envelope<M> {
80 pub fn new(header: EnvelopeHeader, message: M) -> Self {
81 Self { header, message }
82 }
83
84 pub fn header(&self) -> &EnvelopeHeader {
85 &self.header
86 }
87}
88
89impl Envelope<AnyMessage> {
90 pub fn cast<M>(self) -> Result<Envelope<M>, Self>
91 where
92 M: Message,
93 {
94 let Self {
95 header: info,
96 message,
97 } = self;
98 match message.cast() {
99 Ok(message) => {
100 Ok(Envelope {
101 header: info,
102 message,
103 })
104 },
105 Err(message) => {
106 Err(Self {
107 header: info,
108 message,
109 })
110 },
111 }
112 }
113
114 pub fn peek<M>(&self) -> Option<&M>
115 where
116 M: Message,
117 {
118 self.message.peek()
119 }
120
121 pub fn is<M>(&self) -> bool
122 where
123 M: Message,
124 {
125 self.message.is::<M>()
126 }
127
128 pub fn tid(&self) -> TypeId {
129 self.message.tid()
130 }
131
132 pub fn message_name(&self) -> &str {
133 self.message.type_name()
134 }
135}
136impl<M> Envelope<M> {
137 pub fn take(self) -> (M, Envelope<()>) {
138 (
139 self.message,
140 Envelope {
141 header: self.header,
142 message: (),
143 },
144 )
145 }
146}
147
148impl From<Envelope<()>> for EnvelopeHeader {
149 fn from(value: Envelope<()>) -> Self {
150 let Envelope {
151 header,
152 message: (),
153 } = value;
154 header
155 }
156}
157
158impl<M> fmt::Debug for Envelope<M>
159where
160 M: fmt::Debug,
161{
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 f.debug_struct("Envelope")
164 .field("info", &self.header)
165 .field("message", &self.message)
166 .finish()
167 }
168}