use crate::{
buffer::Payload,
ids::{ActorId, MessageId},
message::{
DispatchKind, GasLimit, StoredDelayedDispatch, StoredDispatch, StoredMessage, Value,
},
};
use core::ops::Deref;
use gear_core_errors::{ReplyCode, SignalCode};
use parity_scale_codec::{Decode, Encode};
use scale_decode::DecodeAsType;
use scale_encode::EncodeAsType;
use scale_info::TypeInfo;
#[derive(Clone, Debug, PartialEq, Eq, Decode, DecodeAsType, Encode, EncodeAsType)]
pub struct Message {
id: MessageId,
source: ActorId,
destination: ActorId,
payload: Payload,
gas_limit: Option<GasLimit>,
value: Value,
details: Option<MessageDetails>,
}
impl From<Message> for StoredMessage {
fn from(message: Message) -> StoredMessage {
StoredMessage::new(
message.id,
message.source,
message.destination,
message.payload,
message.value,
message.details,
)
}
}
impl Message {
pub fn new(
id: MessageId,
source: ActorId,
destination: ActorId,
payload: Payload,
gas_limit: Option<GasLimit>,
value: Value,
details: Option<MessageDetails>,
) -> Self {
Self {
id,
source,
destination,
payload,
gas_limit,
value,
details,
}
}
pub fn into_parts(
self,
) -> (
MessageId,
ActorId,
ActorId,
Payload,
Option<GasLimit>,
Value,
Option<MessageDetails>,
) {
(
self.id,
self.source,
self.destination,
self.payload,
self.gas_limit,
self.value,
self.details,
)
}
pub fn into_stored(self) -> StoredMessage {
self.into()
}
pub fn id(&self) -> MessageId {
self.id
}
pub fn source(&self) -> ActorId {
self.source
}
pub fn destination(&self) -> ActorId {
self.destination
}
pub fn payload_bytes(&self) -> &[u8] {
&self.payload
}
pub fn gas_limit(&self) -> Option<GasLimit> {
self.gas_limit
}
pub fn value(&self) -> Value {
self.value
}
pub fn reply_details(&self) -> Option<ReplyDetails> {
self.details.and_then(|d| d.to_reply_details())
}
pub fn signal_details(&self) -> Option<SignalDetails> {
self.details.and_then(|d| d.to_signal_details())
}
pub fn is_error_reply(&self) -> bool {
self.details.map(|d| d.is_error_reply()).unwrap_or(false)
}
pub fn is_reply(&self) -> bool {
self.reply_details().is_some()
}
}
#[derive(
Clone,
Copy,
Debug,
PartialEq,
Eq,
Hash,
Decode,
DecodeAsType,
Encode,
EncodeAsType,
TypeInfo,
derive_more::From,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub enum MessageDetails {
Reply(ReplyDetails),
Signal(SignalDetails),
}
impl MessageDetails {
pub fn is_error_reply(&self) -> bool {
self.to_reply_details()
.map(|d| d.code.is_error())
.unwrap_or(false)
}
pub fn is_reply_details(&self) -> bool {
matches!(self, Self::Reply(_))
}
pub fn to_reply_details(self) -> Option<ReplyDetails> {
match self {
MessageDetails::Reply(reply) => Some(reply),
MessageDetails::Signal(_) => None,
}
}
pub fn is_signal_details(&self) -> bool {
matches!(self, Self::Signal(_))
}
pub fn to_signal_details(self) -> Option<SignalDetails> {
match self {
MessageDetails::Reply(_) => None,
MessageDetails::Signal(signal) => Some(signal),
}
}
}
#[derive(
Clone, Copy, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct ReplyDetails {
to: MessageId,
code: ReplyCode,
}
impl ReplyDetails {
pub fn new(to: MessageId, code: ReplyCode) -> Self {
Self { to, code }
}
pub fn to_message_id(&self) -> MessageId {
self.to
}
pub fn to_reply_code(&self) -> ReplyCode {
self.code
}
pub fn into_parts(self) -> (MessageId, ReplyCode) {
(self.to, self.code)
}
}
#[derive(
Clone, Copy, Debug, PartialEq, Eq, Hash, Decode, DecodeAsType, Encode, EncodeAsType, TypeInfo,
)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub struct SignalDetails {
to: MessageId,
code: SignalCode,
}
impl SignalDetails {
pub fn new(to: MessageId, code: SignalCode) -> Self {
Self { to, code }
}
pub fn to_message_id(&self) -> MessageId {
self.to
}
pub fn to_signal_code(&self) -> SignalCode {
self.code
}
pub fn into_parts(self) -> (MessageId, SignalCode) {
(self.to, self.code)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Decode, DecodeAsType, Encode, EncodeAsType)]
pub struct Dispatch {
kind: DispatchKind,
message: Message,
}
impl From<Dispatch> for StoredDispatch {
fn from(dispatch: Dispatch) -> StoredDispatch {
StoredDispatch::new(dispatch.kind, dispatch.message.into(), None)
}
}
impl From<Dispatch> for StoredDelayedDispatch {
fn from(dispatch: Dispatch) -> StoredDelayedDispatch {
StoredDelayedDispatch::new(dispatch.kind, dispatch.message.into())
}
}
impl From<Dispatch> for (DispatchKind, Message) {
fn from(dispatch: Dispatch) -> (DispatchKind, Message) {
(dispatch.kind, dispatch.message)
}
}
impl Dispatch {
pub fn new(kind: DispatchKind, message: Message) -> Self {
Self { kind, message }
}
pub fn into_stored(self) -> StoredDispatch {
self.into()
}
pub fn into_stored_delayed(self) -> StoredDelayedDispatch {
self.into()
}
pub fn into_parts(self) -> (DispatchKind, Message) {
self.into()
}
pub fn kind(&self) -> DispatchKind {
self.kind
}
pub fn message(&self) -> &Message {
&self.message
}
}
impl Deref for Dispatch {
type Target = Message;
fn deref(&self) -> &Self::Target {
self.message()
}
}