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