use crate::{
ids::{MessageId, ProgramId},
message::{
common::MessageDetails, ContextStore, DispatchKind, GasLimit, IncomingDispatch,
IncomingMessage, Payload, ReplyDetails, Value,
},
};
use alloc::string::ToString;
use core::{convert::TryInto, ops::Deref};
use gear_core_errors::ReplyCode;
use scale_info::{
scale::{Decode, Encode},
TypeInfo,
};
#[derive(Clone, Default, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo)]
pub struct StoredMessage {
pub(super) id: MessageId,
pub(super) source: ProgramId,
pub(super) destination: ProgramId,
pub(super) payload: Payload,
#[codec(compact)]
pub(super) value: Value,
pub(super) details: Option<MessageDetails>,
}
impl StoredMessage {
pub fn new(
id: MessageId,
source: ProgramId,
destination: ProgramId,
payload: Payload,
value: Value,
details: Option<MessageDetails>,
) -> Self {
Self {
id,
source,
destination,
payload,
value,
details,
}
}
pub fn into_incoming(self, gas_limit: GasLimit) -> IncomingMessage {
IncomingMessage::new(
self.id,
self.source,
self.payload,
gas_limit,
self.value,
self.details,
)
}
pub fn id(&self) -> MessageId {
self.id
}
pub fn source(&self) -> ProgramId {
self.source
}
pub fn destination(&self) -> ProgramId {
self.destination
}
pub fn payload_bytes(&self) -> &[u8] {
self.payload.inner()
}
pub fn value(&self) -> Value {
self.value
}
pub fn details(&self) -> Option<MessageDetails> {
self.details
}
pub fn reply_details(&self) -> Option<ReplyDetails> {
self.details.and_then(|d| d.to_reply_details())
}
#[allow(clippy::result_large_err)]
pub fn with_string_payload<D: Decode + ToString>(self) -> Result<Self, Self> {
if let Ok(decoded) = D::decode(&mut self.payload.inner()) {
if let Ok(payload) = decoded.to_string().into_bytes().try_into() {
Ok(Self { payload, ..self })
} else {
Err(self)
}
} else {
Err(self)
}
}
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.details.map(|d| d.is_reply_details()).unwrap_or(false)
}
pub fn reply_code(&self) -> Option<ReplyCode> {
self.details
.and_then(|d| d.to_reply_details().map(|d| d.to_reply_code()))
}
}
#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, Decode, Encode, TypeInfo)]
pub struct StoredDispatch {
kind: DispatchKind,
message: StoredMessage,
context: Option<ContextStore>,
}
impl From<StoredDispatch> for (DispatchKind, StoredMessage, Option<ContextStore>) {
fn from(dispatch: StoredDispatch) -> (DispatchKind, StoredMessage, Option<ContextStore>) {
(dispatch.kind, dispatch.message, dispatch.context)
}
}
impl StoredDispatch {
pub fn new(kind: DispatchKind, message: StoredMessage, context: Option<ContextStore>) -> Self {
Self {
kind,
message,
context,
}
}
pub fn into_incoming(self, gas_limit: GasLimit) -> IncomingDispatch {
IncomingDispatch::new(
self.kind,
self.message.into_incoming(gas_limit),
self.context,
)
}
pub fn into_parts(self) -> (DispatchKind, StoredMessage, Option<ContextStore>) {
self.into()
}
pub fn kind(&self) -> DispatchKind {
self.kind
}
pub fn message(&self) -> &StoredMessage {
&self.message
}
pub fn context(&self) -> &Option<ContextStore> {
&self.context
}
}
impl Deref for StoredDispatch {
type Target = StoredMessage;
fn deref(&self) -> &Self::Target {
self.message()
}
}