gear_core/message/
handle.rs

1// This file is part of Gear.
2
3// Copyright (C) 2022-2025 Gear Technologies Inc.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19use crate::{
20    buffer::Payload,
21    ids::{ActorId, MessageId},
22    message::{
23        Dispatch, DispatchKind, GasLimit, Message, Packet, StoredDispatch, StoredMessage, Value,
24    },
25};
26
27/// Message for Handle entry point.
28/// Represents a standard message that sends between actors.
29#[derive(Clone, Debug, PartialEq, Eq)]
30pub struct HandleMessage {
31    /// Message id.
32    id: MessageId,
33    /// Message destination.
34    destination: ActorId,
35    /// Message payload.
36    payload: Payload,
37    /// Message optional gas limit.
38    gas_limit: Option<GasLimit>,
39    /// Message value.
40    value: Value,
41}
42
43impl HandleMessage {
44    /// Create HandleMessage from HandlePacket.
45    pub fn from_packet(id: MessageId, packet: HandlePacket) -> Self {
46        Self {
47            id,
48            destination: packet.destination,
49            payload: packet.payload,
50            gas_limit: packet.gas_limit,
51            value: packet.value,
52        }
53    }
54
55    /// Convert HandleMessage into Message.
56    pub fn into_message(self, source: ActorId) -> Message {
57        Message::new(
58            self.id,
59            source,
60            self.destination,
61            self.payload,
62            self.gas_limit,
63            self.value,
64            None,
65        )
66    }
67
68    /// Convert HandleMessage into StoredMessage.
69    pub fn into_stored(self, source: ActorId) -> StoredMessage {
70        self.into_message(source).into()
71    }
72
73    /// Convert HandleMessage into Dispatch.
74    pub fn into_dispatch(self, source: ActorId) -> Dispatch {
75        Dispatch::new(DispatchKind::Handle, self.into_message(source))
76    }
77
78    /// Convert HandleMessage into StoredDispatch.
79    pub fn into_stored_dispatch(self, source: ActorId) -> StoredDispatch {
80        self.into_dispatch(source).into()
81    }
82
83    /// Message id.
84    pub fn id(&self) -> MessageId {
85        self.id
86    }
87
88    /// Message destination.
89    pub fn destination(&self) -> ActorId {
90        self.destination
91    }
92
93    /// Message payload bytes.
94    pub fn payload_bytes(&self) -> &[u8] {
95        &self.payload
96    }
97
98    /// Message optional gas limit.
99    pub fn gas_limit(&self) -> Option<GasLimit> {
100        self.gas_limit
101    }
102
103    /// Message value.
104    pub fn value(&self) -> Value {
105        self.value
106    }
107}
108
109/// Handle message packet.
110///
111/// This structure is preparation for future HandleMessage sending. Has no message id.
112#[derive(Clone, Debug, PartialEq, Eq)]
113#[cfg_attr(any(feature = "mock", test), derive(Default))]
114pub struct HandlePacket {
115    /// Packet destination.
116    destination: ActorId,
117    /// Packet payload.
118    payload: Payload,
119    /// Packet optional gas limit.
120    gas_limit: Option<GasLimit>,
121    /// Packet value.
122    value: Value,
123}
124
125impl HandlePacket {
126    /// Create new packet without gas.
127    pub fn new(destination: ActorId, payload: Payload, value: Value) -> Self {
128        Self {
129            destination,
130            payload,
131            gas_limit: None,
132            value,
133        }
134    }
135
136    /// Create new packet with gas.
137    pub fn new_with_gas(
138        destination: ActorId,
139        payload: Payload,
140        gas_limit: GasLimit,
141        value: Value,
142    ) -> Self {
143        Self {
144            destination,
145            payload,
146            gas_limit: Some(gas_limit),
147            value,
148        }
149    }
150
151    /// Create new packet with optional gas.
152    pub fn maybe_with_gas(
153        destination: ActorId,
154        payload: Payload,
155        gas_limit: Option<GasLimit>,
156        value: Value,
157    ) -> Self {
158        match gas_limit {
159            None => Self::new(destination, payload, value),
160            Some(gas_limit) => Self::new_with_gas(destination, payload, gas_limit, value),
161        }
162    }
163
164    /// Prepend payload.
165    pub(super) fn try_prepend(&mut self, mut data: Payload) -> Result<(), Payload> {
166        if data.try_extend_from_slice(self.payload_bytes()).is_err() {
167            Err(data)
168        } else {
169            self.payload = data;
170            Ok(())
171        }
172    }
173
174    /// Packet destination.
175    pub fn destination(&self) -> ActorId {
176        self.destination
177    }
178}
179
180impl Packet for HandlePacket {
181    fn payload_bytes(&self) -> &[u8] {
182        &self.payload
183    }
184
185    fn payload_len(&self) -> u32 {
186        self.payload.len_u32()
187    }
188
189    fn gas_limit(&self) -> Option<GasLimit> {
190        self.gas_limit
191    }
192
193    fn value(&self) -> Value {
194        self.value
195    }
196
197    fn kind() -> DispatchKind {
198        DispatchKind::Handle
199    }
200}