1use super::common::ReplyDetails;
20use crate::{
21 buffer::Payload,
22 ids::{ActorId, MessageId, prelude::*},
23 message::{
24 Dispatch, DispatchKind, GasLimit, Message, Packet, StoredDispatch, StoredMessage, Value,
25 },
26};
27use gear_core_errors::{ErrorReplyReason, ReplyCode, SuccessReplyReason};
28
29#[derive(Clone, Debug, PartialEq, Eq)]
32pub struct ReplyMessage {
33 id: MessageId,
35 payload: Payload,
37 gas_limit: Option<GasLimit>,
39 value: Value,
41 code: ReplyCode,
43}
44
45impl ReplyMessage {
46 pub fn from_packet(id: MessageId, packet: ReplyPacket) -> Self {
48 Self {
49 id,
50 payload: packet.payload,
51 gas_limit: packet.gas_limit,
52 value: packet.value,
53 code: packet.code,
54 }
55 }
56
57 pub fn system(
59 origin_msg_id: MessageId,
60 payload: Payload,
61 value: Value,
62 err: impl Into<ErrorReplyReason>,
63 ) -> Self {
64 let id = MessageId::generate_reply(origin_msg_id);
65 let packet = ReplyPacket::system(payload, value, err);
66
67 Self::from_packet(id, packet)
68 }
69
70 pub fn auto(origin_msg_id: MessageId) -> Self {
72 let id = MessageId::generate_reply(origin_msg_id);
73 let packet = ReplyPacket::auto();
74
75 Self::from_packet(id, packet)
76 }
77
78 pub fn into_message(
80 self,
81 program_id: ActorId,
82 destination: ActorId,
83 origin_msg_id: MessageId,
84 ) -> Message {
85 Message::new(
86 self.id,
87 program_id,
88 destination,
89 self.payload,
90 self.gas_limit,
91 self.value,
92 Some(ReplyDetails::new(origin_msg_id, self.code).into()),
93 )
94 }
95
96 pub fn into_stored(
98 self,
99 program_id: ActorId,
100 destination: ActorId,
101 origin_msg_id: MessageId,
102 ) -> StoredMessage {
103 self.into_message(program_id, destination, origin_msg_id)
104 .into()
105 }
106
107 pub fn into_dispatch(
109 self,
110 source: ActorId,
111 destination: ActorId,
112 origin_msg_id: MessageId,
113 ) -> Dispatch {
114 Dispatch::new(
115 DispatchKind::Reply,
116 self.into_message(source, destination, origin_msg_id),
117 )
118 }
119
120 pub fn into_stored_dispatch(
122 self,
123 source: ActorId,
124 destination: ActorId,
125 origin_msg_id: MessageId,
126 ) -> StoredDispatch {
127 self.into_dispatch(source, destination, origin_msg_id)
128 .into()
129 }
130
131 pub fn id(&self) -> MessageId {
133 self.id
134 }
135
136 pub fn payload_bytes(&self) -> &[u8] {
138 &self.payload
139 }
140
141 pub fn gas_limit(&self) -> Option<GasLimit> {
143 self.gas_limit
144 }
145
146 pub fn value(&self) -> Value {
148 self.value
149 }
150
151 pub fn code(&self) -> ReplyCode {
153 self.code
154 }
155}
156
157#[derive(Clone, Debug, PartialEq, Eq)]
161pub struct ReplyPacket {
162 payload: Payload,
164 gas_limit: Option<GasLimit>,
166 value: Value,
168 code: ReplyCode,
170}
171
172#[cfg(test)]
173impl Default for ReplyPacket {
174 fn default() -> Self {
175 Self::auto()
176 }
177}
178
179impl ReplyPacket {
180 pub fn new(payload: Payload, value: Value) -> Self {
182 Self {
183 payload,
184 gas_limit: None,
185 value,
186 code: ReplyCode::Success(SuccessReplyReason::Manual),
187 }
188 }
189
190 pub fn new_with_gas(payload: Payload, gas_limit: GasLimit, value: Value) -> Self {
192 Self {
193 payload,
194 gas_limit: Some(gas_limit),
195 value,
196 code: ReplyCode::Success(SuccessReplyReason::Manual),
197 }
198 }
199
200 pub fn maybe_with_gas(payload: Payload, gas_limit: Option<GasLimit>, value: Value) -> Self {
202 match gas_limit {
203 None => Self::new(payload, value),
204 Some(gas_limit) => Self::new_with_gas(payload, gas_limit, value),
205 }
206 }
207
208 pub fn system(payload: Payload, value: Value, err: impl Into<ErrorReplyReason>) -> Self {
212 Self {
213 payload,
214 gas_limit: None,
215 value,
216 code: ReplyCode::error(err),
217 }
218 }
219
220 pub fn auto() -> Self {
222 Self {
223 payload: Default::default(),
224 gas_limit: Some(0),
225 value: 0,
226 code: ReplyCode::Success(SuccessReplyReason::Auto),
227 }
228 }
229
230 pub(super) fn try_prepend(&mut self, mut data: Payload) -> Result<(), Payload> {
232 if data.try_extend_from_slice(self.payload_bytes()).is_err() {
233 Err(data)
234 } else {
235 self.payload = data;
236 Ok(())
237 }
238 }
239
240 pub fn code(&self) -> ReplyCode {
242 self.code
243 }
244}
245
246impl Packet for ReplyPacket {
247 fn payload_bytes(&self) -> &[u8] {
248 &self.payload
249 }
250
251 fn payload_len(&self) -> u32 {
252 self.payload.len_u32()
253 }
254
255 fn gas_limit(&self) -> Option<GasLimit> {
256 self.gas_limit
257 }
258
259 fn value(&self) -> Value {
260 self.value
261 }
262
263 fn kind() -> DispatchKind {
264 DispatchKind::Reply
265 }
266}