1use super::common::ReplyDetails;
5use crate::{
6 buffer::Payload,
7 ids::{ActorId, MessageId, prelude::*},
8 message::{
9 Dispatch, DispatchKind, GasLimit, Message, Packet, StoredDispatch, StoredMessage, Value,
10 },
11};
12use gear_core_errors::{ErrorReplyReason, ReplyCode, SuccessReplyReason};
13
14#[derive(Clone, Debug, PartialEq, Eq)]
17pub struct ReplyMessage {
18 id: MessageId,
20 payload: Payload,
22 gas_limit: Option<GasLimit>,
24 value: Value,
26 code: ReplyCode,
28}
29
30impl ReplyMessage {
31 pub fn from_packet(id: MessageId, packet: ReplyPacket) -> Self {
33 Self {
34 id,
35 payload: packet.payload,
36 gas_limit: packet.gas_limit,
37 value: packet.value,
38 code: packet.code,
39 }
40 }
41
42 pub fn system(
44 origin_msg_id: MessageId,
45 payload: Payload,
46 value: Value,
47 err: impl Into<ErrorReplyReason>,
48 ) -> Self {
49 let id = MessageId::generate_reply(origin_msg_id);
50 let packet = ReplyPacket::system(payload, value, err);
51
52 Self::from_packet(id, packet)
53 }
54
55 pub fn auto(origin_msg_id: MessageId) -> Self {
57 let id = MessageId::generate_reply(origin_msg_id);
58 let packet = ReplyPacket::auto();
59
60 Self::from_packet(id, packet)
61 }
62
63 pub fn into_message(
65 self,
66 program_id: ActorId,
67 destination: ActorId,
68 origin_msg_id: MessageId,
69 ) -> Message {
70 Message::new(
71 self.id,
72 program_id,
73 destination,
74 self.payload,
75 self.gas_limit,
76 self.value,
77 Some(ReplyDetails::new(origin_msg_id, self.code).into()),
78 )
79 }
80
81 pub fn into_stored(
83 self,
84 program_id: ActorId,
85 destination: ActorId,
86 origin_msg_id: MessageId,
87 ) -> StoredMessage {
88 self.into_message(program_id, destination, origin_msg_id)
89 .into()
90 }
91
92 pub fn into_dispatch(
94 self,
95 source: ActorId,
96 destination: ActorId,
97 origin_msg_id: MessageId,
98 ) -> Dispatch {
99 Dispatch::new(
100 DispatchKind::Reply,
101 self.into_message(source, destination, origin_msg_id),
102 )
103 }
104
105 pub fn into_stored_dispatch(
107 self,
108 source: ActorId,
109 destination: ActorId,
110 origin_msg_id: MessageId,
111 ) -> StoredDispatch {
112 self.into_dispatch(source, destination, origin_msg_id)
113 .into()
114 }
115
116 pub fn id(&self) -> MessageId {
118 self.id
119 }
120
121 pub fn payload_bytes(&self) -> &[u8] {
123 &self.payload
124 }
125
126 pub fn gas_limit(&self) -> Option<GasLimit> {
128 self.gas_limit
129 }
130
131 pub fn value(&self) -> Value {
133 self.value
134 }
135
136 pub fn code(&self) -> ReplyCode {
138 self.code
139 }
140}
141
142#[derive(Clone, Debug, PartialEq, Eq)]
146pub struct ReplyPacket {
147 payload: Payload,
149 gas_limit: Option<GasLimit>,
151 value: Value,
153 code: ReplyCode,
155}
156
157#[cfg(test)]
158impl Default for ReplyPacket {
159 fn default() -> Self {
160 Self::auto()
161 }
162}
163
164impl ReplyPacket {
165 pub fn new(payload: Payload, value: Value) -> Self {
167 Self {
168 payload,
169 gas_limit: None,
170 value,
171 code: ReplyCode::Success(SuccessReplyReason::Manual),
172 }
173 }
174
175 pub fn new_with_gas(payload: Payload, gas_limit: GasLimit, value: Value) -> Self {
177 Self {
178 payload,
179 gas_limit: Some(gas_limit),
180 value,
181 code: ReplyCode::Success(SuccessReplyReason::Manual),
182 }
183 }
184
185 pub fn maybe_with_gas(payload: Payload, gas_limit: Option<GasLimit>, value: Value) -> Self {
187 match gas_limit {
188 None => Self::new(payload, value),
189 Some(gas_limit) => Self::new_with_gas(payload, gas_limit, value),
190 }
191 }
192
193 pub fn system(payload: Payload, value: Value, err: impl Into<ErrorReplyReason>) -> Self {
197 Self {
198 payload,
199 gas_limit: None,
200 value,
201 code: ReplyCode::error(err),
202 }
203 }
204
205 pub fn auto() -> Self {
207 Self {
208 payload: Default::default(),
209 gas_limit: Some(0),
210 value: 0,
211 code: ReplyCode::Success(SuccessReplyReason::Auto),
212 }
213 }
214
215 pub(super) fn try_prepend(&mut self, mut data: Payload) -> Result<(), Payload> {
217 if data.try_extend_from_slice(self.payload_bytes()).is_err() {
218 Err(data)
219 } else {
220 self.payload = data;
221 Ok(())
222 }
223 }
224
225 pub fn code(&self) -> ReplyCode {
227 self.code
228 }
229}
230
231impl Packet for ReplyPacket {
232 fn payload_bytes(&self) -> &[u8] {
233 &self.payload
234 }
235
236 fn payload_len(&self) -> u32 {
237 self.payload.len_u32()
238 }
239
240 fn gas_limit(&self) -> Option<GasLimit> {
241 self.gas_limit
242 }
243
244 fn value(&self) -> Value {
245 self.value
246 }
247
248 fn kind() -> DispatchKind {
249 DispatchKind::Reply
250 }
251}