1use quanta::Instant;
2
3use crate::{
4 addr::Addr,
5 address_book::AddressBook,
6 message::{AnyMessage, Message},
7 request_table::{RequestId, ResponseToken},
8 trace_id::TraceId,
9};
10
11#[derive(Debug)]
13pub struct Envelope<M = AnyMessage> {
14 created_time: Instant, trace_id: TraceId,
16 kind: MessageKind,
17 message: M,
18}
19
20assert_impl_all!(Envelope: Send);
21assert_eq_size!(Envelope, [u8; 256]);
22
23#[derive(Debug)]
24pub(crate) enum MessageKind {
25 Regular { sender: Addr },
26 RequestAny(ResponseToken<()>),
27 RequestAll(ResponseToken<()>),
28 Response { sender: Addr, request_id: RequestId },
29}
30
31impl<M> Envelope<M> {
32 #[inline]
33 pub fn trace_id(&self) -> TraceId {
34 self.trace_id
35 }
36
37 #[inline]
38 pub fn message(&self) -> &M {
39 &self.message
40 }
41
42 pub(crate) fn message_kind(&self) -> &MessageKind {
43 &self.kind
44 }
45
46 pub(crate) fn created_time(&self) -> Instant {
47 self.created_time
48 }
49
50 #[inline]
51 pub fn sender(&self) -> Addr {
52 match &self.kind {
53 MessageKind::Regular { sender } => *sender,
54 MessageKind::RequestAny(token) => token.sender,
55 MessageKind::RequestAll(token) => token.sender,
56 MessageKind::Response { sender, .. } => *sender,
57 }
58 }
59}
60
61impl<M: Message> Envelope<M> {
62 pub(crate) fn new(message: M, kind: MessageKind) -> Self {
63 Self::with_trace_id(message, kind, crate::scope::trace_id())
64 }
65
66 pub(crate) fn with_trace_id(message: M, kind: MessageKind, trace_id: TraceId) -> Self {
67 Self {
68 created_time: Instant::now(),
69 trace_id,
70 kind,
71 message,
72 }
73 }
74
75 pub(crate) fn upcast(self) -> Envelope {
76 Envelope {
77 created_time: self.created_time,
78 trace_id: self.trace_id,
79 kind: self.kind,
80 message: AnyMessage::new(self.message),
81 }
82 }
83
84 pub(crate) fn into_message(self) -> M {
86 self.message
87 }
88}
89
90impl Envelope {
91 #[inline]
92 pub fn is<M: Message>(&self) -> bool {
93 self.message.is::<M>()
94 }
95
96 pub(crate) fn do_downcast<M: Message>(self) -> Envelope<M> {
97 let message = self.message.downcast::<M>().expect("cannot downcast");
98 Envelope {
99 created_time: self.created_time,
100 trace_id: self.trace_id,
101 kind: self.kind,
102 message,
103 }
104 }
105
106 pub(crate) fn duplicate(&self, book: &AddressBook) -> Option<Self> {
109 Some(Self {
110 created_time: self.created_time,
111 trace_id: self.trace_id,
112 kind: match &self.kind {
113 MessageKind::Regular { sender } => MessageKind::Regular { sender: *sender },
114 MessageKind::RequestAny(token) => {
115 let object = book.get(token.sender)?;
116 let token = object.as_actor()?.request_table().clone_token(token)?;
117 MessageKind::RequestAny(token)
118 }
119 MessageKind::RequestAll(token) => {
120 let object = book.get(token.sender)?;
121 let token = object.as_actor()?.request_table().clone_token(token)?;
122 MessageKind::RequestAll(token)
123 }
124 MessageKind::Response { sender, request_id } => MessageKind::Response {
125 sender: *sender,
126 request_id: *request_id,
127 },
128 },
129 message: self.message.clone(),
130 })
131 }
132
133 pub(crate) fn set_message<M: Message>(&mut self, message: M) {
134 self.message = AnyMessage::new(message);
135 }
136}
137
138pub trait EnvelopeOwned {
141 fn unpack_regular(self) -> AnyMessage;
142 fn unpack_request<T>(self) -> (AnyMessage, ResponseToken<T>);
143}
144
145pub trait EnvelopeBorrowed {
146 fn unpack_regular(&self) -> &AnyMessage;
147}
148
149impl EnvelopeOwned for Envelope {
150 #[inline]
151 fn unpack_regular(self) -> AnyMessage {
152 self.message
153 }
154
155 #[inline]
156 fn unpack_request<T>(self) -> (AnyMessage, ResponseToken<T>) {
157 match self.kind {
158 MessageKind::RequestAny(token) => (self.message, token.into_typed()),
159 MessageKind::RequestAll(token) => (self.message, token.into_typed()),
160 _ => unreachable!(),
161 }
162 }
163}
164
165impl EnvelopeBorrowed for Envelope {
166 #[inline]
167 fn unpack_regular(&self) -> &AnyMessage {
168 &self.message
169 }
170}
171
172pub trait AnyMessageOwned {
173 fn downcast2<M: Message>(self) -> M;
174}
175
176pub trait AnyMessageBorrowed {
177 fn downcast2<M: Message>(&self) -> &M;
178}
179
180impl AnyMessageOwned for AnyMessage {
181 #[inline]
182 #[track_caller]
183 fn downcast2<M: Message>(self) -> M {
184 match self.downcast::<M>() {
185 Ok(message) => message,
186 Err(message) => panic!("unexpected message: {message:?}"),
187 }
188 }
189}
190
191impl AnyMessageBorrowed for AnyMessage {
192 #[inline]
193 #[track_caller]
194 fn downcast2<M: Message>(&self) -> &M {
195 ward!(
196 self.downcast_ref::<M>(),
197 panic!("unexpected message: {self:?}")
198 )
199 }
200}