1use crate::{
20 buffer::Payload,
21 ids::{ActorId, MessageId},
22 message::{
23 DispatchKind, GasLimit, StoredDelayedDispatch, StoredDispatch, StoredMessage, Value,
24 },
25};
26use core::ops::Deref;
27use gear_core_errors::{ReplyCode, SignalCode};
28use parity_scale_codec::{Decode, Encode};
29use scale_info::TypeInfo;
30
31#[derive(Clone, Debug, PartialEq, Eq, Decode, Encode)]
34pub struct Message {
35 id: MessageId,
37 source: ActorId,
39 destination: ActorId,
41 payload: Payload,
43 gas_limit: Option<GasLimit>,
45 value: Value,
47 details: Option<MessageDetails>,
49}
50
51impl From<Message> for StoredMessage {
52 fn from(message: Message) -> StoredMessage {
53 StoredMessage::new(
54 message.id,
55 message.source,
56 message.destination,
57 message.payload,
58 message.value,
59 message.details,
60 )
61 }
62}
63
64impl Message {
65 pub fn new(
67 id: MessageId,
68 source: ActorId,
69 destination: ActorId,
70 payload: Payload,
71 gas_limit: Option<GasLimit>,
72 value: Value,
73 details: Option<MessageDetails>,
74 ) -> Self {
75 Self {
76 id,
77 source,
78 destination,
79 payload,
80 gas_limit,
81 value,
82 details,
83 }
84 }
85
86 pub fn into_parts(
88 self,
89 ) -> (
90 MessageId,
91 ActorId,
92 ActorId,
93 Payload,
94 Option<GasLimit>,
95 Value,
96 Option<MessageDetails>,
97 ) {
98 (
99 self.id,
100 self.source,
101 self.destination,
102 self.payload,
103 self.gas_limit,
104 self.value,
105 self.details,
106 )
107 }
108
109 pub fn into_stored(self) -> StoredMessage {
111 self.into()
112 }
113
114 pub fn id(&self) -> MessageId {
116 self.id
117 }
118
119 pub fn source(&self) -> ActorId {
121 self.source
122 }
123
124 pub fn destination(&self) -> ActorId {
126 self.destination
127 }
128
129 pub fn payload_bytes(&self) -> &[u8] {
131 self.payload.inner()
132 }
133
134 pub fn gas_limit(&self) -> Option<GasLimit> {
136 self.gas_limit
137 }
138
139 pub fn value(&self) -> Value {
141 self.value
142 }
143
144 pub fn reply_details(&self) -> Option<ReplyDetails> {
146 self.details.and_then(|d| d.to_reply_details())
147 }
148
149 pub fn signal_details(&self) -> Option<SignalDetails> {
151 self.details.and_then(|d| d.to_signal_details())
152 }
153
154 pub fn is_error_reply(&self) -> bool {
156 self.details.map(|d| d.is_error_reply()).unwrap_or(false)
157 }
158
159 pub fn is_reply(&self) -> bool {
161 self.reply_details().is_some()
162 }
163}
164
165#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Decode, Encode, TypeInfo, derive_more::From)]
167#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
168pub enum MessageDetails {
169 Reply(ReplyDetails),
171 Signal(SignalDetails),
173}
174
175impl MessageDetails {
176 pub fn is_error_reply(&self) -> bool {
178 self.to_reply_details()
179 .map(|d| d.code.is_error())
180 .unwrap_or(false)
181 }
182
183 pub fn is_reply_details(&self) -> bool {
185 matches!(self, Self::Reply(_))
186 }
187
188 pub fn to_reply_details(self) -> Option<ReplyDetails> {
190 match self {
191 MessageDetails::Reply(reply) => Some(reply),
192 MessageDetails::Signal(_) => None,
193 }
194 }
195
196 pub fn is_signal_details(&self) -> bool {
198 matches!(self, Self::Signal(_))
199 }
200
201 pub fn to_signal_details(self) -> Option<SignalDetails> {
203 match self {
204 MessageDetails::Reply(_) => None,
205 MessageDetails::Signal(signal) => Some(signal),
206 }
207 }
208}
209
210#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Decode, Encode, TypeInfo)]
215#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
216pub struct ReplyDetails {
217 to: MessageId,
219 code: ReplyCode,
221}
222
223impl ReplyDetails {
224 pub fn new(to: MessageId, code: ReplyCode) -> Self {
226 Self { to, code }
227 }
228
229 pub fn to_message_id(&self) -> MessageId {
231 self.to
232 }
233
234 pub fn to_reply_code(&self) -> ReplyCode {
236 self.code
237 }
238
239 pub fn into_parts(self) -> (MessageId, ReplyCode) {
241 (self.to, self.code)
242 }
243}
244
245#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Decode, Encode, TypeInfo)]
247#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
248pub struct SignalDetails {
249 to: MessageId,
251 code: SignalCode,
253}
254
255impl SignalDetails {
256 pub fn new(to: MessageId, code: SignalCode) -> Self {
258 Self { to, code }
259 }
260
261 pub fn to_message_id(&self) -> MessageId {
263 self.to
264 }
265
266 pub fn to_signal_code(&self) -> SignalCode {
268 self.code
269 }
270
271 pub fn into_parts(self) -> (MessageId, SignalCode) {
273 (self.to, self.code)
274 }
275}
276
277#[derive(Clone, Debug, PartialEq, Eq, Decode, Encode)]
279pub struct Dispatch {
280 kind: DispatchKind,
282 message: Message,
284}
285
286impl From<Dispatch> for StoredDispatch {
287 fn from(dispatch: Dispatch) -> StoredDispatch {
288 StoredDispatch::new(dispatch.kind, dispatch.message.into(), None)
289 }
290}
291
292impl From<Dispatch> for StoredDelayedDispatch {
293 fn from(dispatch: Dispatch) -> StoredDelayedDispatch {
294 StoredDelayedDispatch::new(dispatch.kind, dispatch.message.into())
295 }
296}
297
298impl From<Dispatch> for (DispatchKind, Message) {
299 fn from(dispatch: Dispatch) -> (DispatchKind, Message) {
300 (dispatch.kind, dispatch.message)
301 }
302}
303
304impl Dispatch {
305 pub fn new(kind: DispatchKind, message: Message) -> Self {
307 Self { kind, message }
308 }
309
310 pub fn into_stored(self) -> StoredDispatch {
312 self.into()
313 }
314
315 pub fn into_stored_delayed(self) -> StoredDelayedDispatch {
317 self.into()
318 }
319
320 pub fn into_parts(self) -> (DispatchKind, Message) {
322 self.into()
323 }
324
325 pub fn kind(&self) -> DispatchKind {
327 self.kind
328 }
329
330 pub fn message(&self) -> &Message {
332 &self.message
333 }
334}
335
336impl Deref for Dispatch {
337 type Target = Message;
338
339 fn deref(&self) -> &Self::Target {
340 self.message()
341 }
342}