Skip to main content

gear_core/message/
user.rs

1// Copyright (C) Gear Technologies Inc.
2// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
3
4use super::{MessageDetails, StoredMessage};
5use crate::{
6    buffer::Payload,
7    ids::{ActorId, MessageId},
8    message::{ReplyDetails, Value},
9};
10use core::convert::TryFrom;
11use gear_core_errors::ReplyCode;
12use parity_scale_codec::{Decode, Encode};
13use scale_decode::DecodeAsType;
14use scale_encode::EncodeAsType;
15use scale_info::TypeInfo;
16
17/// Message sent to user and deposited as event.
18#[derive(
19    Clone, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo,
20)]
21#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
22pub struct UserMessage {
23    /// Message id.
24    id: MessageId,
25    /// Message source.
26    source: ActorId,
27    /// Message destination.
28    destination: ActorId,
29    /// Message payload.
30    payload: Payload,
31    /// Message value.
32    #[codec(compact)]
33    value: Value,
34    /// Message details: reply message ID and reply code if exists.
35    details: Option<ReplyDetails>,
36}
37
38impl UserMessage {
39    /// Create new UserMessage.
40    pub fn new(
41        id: MessageId,
42        source: ActorId,
43        destination: ActorId,
44        payload: Payload,
45        value: Value,
46        details: Option<ReplyDetails>,
47    ) -> Self {
48        Self {
49            id,
50            source,
51            destination,
52            payload,
53            value,
54            details,
55        }
56    }
57
58    /// Message id.
59    pub fn id(&self) -> MessageId {
60        self.id
61    }
62
63    /// Message source.
64    pub fn source(&self) -> ActorId {
65        self.source
66    }
67
68    /// Message destination.
69    pub fn destination(&self) -> ActorId {
70        self.destination
71    }
72
73    /// Message payload bytes.
74    pub fn payload_bytes(&self) -> &[u8] {
75        &self.payload
76    }
77
78    /// Message value.
79    pub fn value(&self) -> Value {
80        self.value
81    }
82
83    /// Message reply details.
84    pub fn details(&self) -> Option<ReplyDetails> {
85        self.details
86    }
87
88    /// Returns `ReplyCode` of message if reply.
89    pub fn reply_code(&self) -> Option<ReplyCode> {
90        self.details.map(|d| d.to_reply_code())
91    }
92}
93
94#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
95pub struct FromStoredMessageError;
96
97impl TryFrom<StoredMessage> for UserMessage {
98    type Error = FromStoredMessageError;
99
100    fn try_from(stored: StoredMessage) -> Result<Self, Self::Error> {
101        let some_details = stored.details.is_some();
102        let details = stored.details.and_then(|d| d.to_reply_details());
103
104        if details.is_none() && some_details {
105            return Err(FromStoredMessageError);
106        }
107
108        Ok(Self {
109            id: stored.id,
110            source: stored.source,
111            destination: stored.destination,
112            payload: stored.payload,
113            value: stored.value,
114            details,
115        })
116    }
117}
118
119impl From<UserMessage> for StoredMessage {
120    fn from(user: UserMessage) -> Self {
121        let details = user.details.map(MessageDetails::Reply);
122
123        StoredMessage {
124            id: user.id,
125            source: user.source,
126            destination: user.destination,
127            payload: user.payload,
128            value: user.value,
129            details,
130        }
131    }
132}
133
134/// Message sent to user and added to mailbox.
135///
136/// May be represented only with `DispatchKind::Handle`,
137/// so does not contain message details.
138#[derive(
139    Clone, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo,
140)]
141pub struct UserStoredMessage {
142    /// Message id.
143    id: MessageId,
144    /// Message source.
145    source: ActorId,
146    /// Message destination.
147    destination: ActorId,
148    /// Message payload.
149    payload: Payload,
150    /// Message value.
151    #[codec(compact)]
152    value: Value,
153}
154
155impl UserStoredMessage {
156    /// Create new UserStoredMessage.
157    pub fn new(
158        id: MessageId,
159        source: ActorId,
160        destination: ActorId,
161        payload: Payload,
162        value: Value,
163    ) -> Self {
164        Self {
165            id,
166            source,
167            destination,
168            payload,
169            value,
170        }
171    }
172
173    /// Message id.
174    pub fn id(&self) -> MessageId {
175        self.id
176    }
177
178    /// Message source.
179    pub fn source(&self) -> ActorId {
180        self.source
181    }
182
183    /// Message destination.
184    pub fn destination(&self) -> ActorId {
185        self.destination
186    }
187
188    /// Message payload bytes.
189    pub fn payload_bytes(&self) -> &[u8] {
190        &self.payload
191    }
192
193    /// Message value.
194    pub fn value(&self) -> Value {
195        self.value
196    }
197}
198
199#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
200pub struct UserStoredMessageConvertError;
201
202impl TryFrom<StoredMessage> for UserStoredMessage {
203    type Error = UserStoredMessageConvertError;
204
205    fn try_from(stored: StoredMessage) -> Result<Self, Self::Error> {
206        if stored.details().is_some() {
207            return Err(UserStoredMessageConvertError);
208        }
209
210        Ok(Self {
211            id: stored.id,
212            source: stored.source,
213            destination: stored.destination,
214            payload: stored.payload,
215            value: stored.value,
216        })
217    }
218}
219
220impl TryFrom<UserMessage> for UserStoredMessage {
221    type Error = UserStoredMessageConvertError;
222
223    fn try_from(user: UserMessage) -> Result<Self, Self::Error> {
224        if user.details().is_some() {
225            return Err(UserStoredMessageConvertError);
226        }
227
228        Ok(Self {
229            id: user.id,
230            source: user.source,
231            destination: user.destination,
232            payload: user.payload,
233            value: user.value,
234        })
235    }
236}
237
238impl From<UserStoredMessage> for StoredMessage {
239    fn from(user_stored: UserStoredMessage) -> Self {
240        StoredMessage {
241            id: user_stored.id,
242            source: user_stored.source,
243            destination: user_stored.destination,
244            payload: user_stored.payload,
245            value: user_stored.value,
246            details: None,
247        }
248    }
249}