mm1_core/
envelope.rs

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}