everscale_types/models/message/
envelope.rsuse crate::cell::*;
use crate::error::Error;
use crate::models::{Lazy, Message, MsgInfo, OwnedMessage};
use crate::num::Tokens;
use crate::util::unlikely;
use super::IntMsgInfo;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[cfg_attr(feature = "serde", serde(tag = "ty"))]
pub enum IntermediateAddr {
Regular(IntermediateAddrRegular),
Simple(IntermediateAddrSimple),
Ext(IntermediateAddrExt),
}
impl IntermediateAddr {
pub const FULL_DEST_SAME_WORKCHAIN: Self = Self::Regular(IntermediateAddrRegular {
use_dest_bits: IntermediateAddrRegular::FULL_BITS,
});
pub const FULL_SRC_SAME_WORKCHAIN: Self =
Self::Regular(IntermediateAddrRegular { use_dest_bits: 0 });
pub const FULL_MASTERCHAIN: Self = Self::Simple(IntermediateAddrSimple {
workchain: -1,
address_prefix: 0b1 << 63,
});
pub fn workchain(&self) -> Option<i32> {
match self {
IntermediateAddr::Regular(_) => None,
IntermediateAddr::Simple(simple) => Some(simple.workchain as i32),
IntermediateAddr::Ext(ext) => Some(ext.workchain),
}
}
pub fn address_prefix(&self) -> Option<u64> {
match self {
IntermediateAddr::Regular(_) => None,
IntermediateAddr::Simple(simple) => Some(simple.address_prefix),
IntermediateAddr::Ext(ext) => Some(ext.address_prefix),
}
}
}
impl From<IntermediateAddrRegular> for IntermediateAddr {
#[inline]
fn from(addr: IntermediateAddrRegular) -> Self {
IntermediateAddr::Regular(addr)
}
}
impl From<IntermediateAddrSimple> for IntermediateAddr {
#[inline]
fn from(addr: IntermediateAddrSimple) -> Self {
IntermediateAddr::Simple(addr)
}
}
impl From<IntermediateAddrExt> for IntermediateAddr {
#[inline]
fn from(addr: IntermediateAddrExt) -> Self {
IntermediateAddr::Ext(addr)
}
}
impl Store for IntermediateAddr {
fn store_into(&self, builder: &mut CellBuilder, cx: &mut dyn CellContext) -> Result<(), Error> {
match self {
IntermediateAddr::Regular(addr) => {
ok!(builder.store_bit_zero()); addr.store_into(builder, cx)
}
IntermediateAddr::Simple(addr) => {
ok!(builder.store_small_uint(0b10, 2)); addr.store_into(builder, cx)
}
IntermediateAddr::Ext(addr) => {
ok!(builder.store_small_uint(0b11, 2)); addr.store_into(builder, cx)
}
}
}
}
impl<'a> Load<'a> for IntermediateAddr {
fn load_from(slice: &mut CellSlice<'a>) -> Result<Self, Error> {
if unlikely(slice.load_bit()?) {
if unlikely(slice.load_bit()?) {
IntermediateAddrExt::load_from(slice).map(IntermediateAddr::Ext)
} else {
IntermediateAddrSimple::load_from(slice).map(IntermediateAddr::Simple)
}
} else {
IntermediateAddrRegular::load_from(slice).map(IntermediateAddr::Regular)
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[tlb(validate_with = "Self::is_valid")]
pub struct IntermediateAddrRegular {
use_dest_bits: u8,
}
impl IntermediateAddrRegular {
pub const FULL_BITS: u8 = 96;
pub const fn is_valid(&self) -> bool {
self.use_dest_bits <= Self::FULL_BITS
}
pub fn with_dest_bits(use_dest_bits: u8) -> Option<Self> {
(use_dest_bits <= Self::FULL_BITS).then_some(IntermediateAddrRegular { use_dest_bits })
}
pub fn with_src_bits(use_src_bits: u8) -> Option<Self> {
(use_src_bits <= Self::FULL_BITS).then(|| IntermediateAddrRegular {
use_dest_bits: Self::FULL_BITS - use_src_bits,
})
}
pub fn use_dest_bits(&self) -> u8 {
self.use_dest_bits
}
pub fn use_src_bits(&self) -> u8 {
Self::FULL_BITS - self.use_dest_bits
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Load, Store)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct IntermediateAddrSimple {
pub workchain: i8,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_account_prefix"))]
pub address_prefix: u64,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
pub struct IntermediateAddrExt {
pub workchain: i32,
#[cfg_attr(feature = "serde", serde(serialize_with = "serialize_account_prefix"))]
pub address_prefix: u64,
}
#[derive(Clone, Debug, Eq, PartialEq, Store, Load)]
#[cfg_attr(feature = "serde", derive(serde::Serialize))]
#[tlb(tag = "#4")]
pub struct MsgEnvelope {
pub cur_addr: IntermediateAddr,
pub next_addr: IntermediateAddr,
pub fwd_fee_remaining: Tokens,
#[cfg_attr(feature = "serde", serde(serialize_with = "Lazy::serialize_repr_hash"))]
pub message: Lazy<OwnedMessage>,
}
impl MsgEnvelope {
pub fn load_message_info(&self) -> Result<IntMsgInfo, Error> {
if let MsgInfo::Int(info) = ok!(<_>::load_from(&mut ok!(self.message.cell.as_slice()))) {
Ok(info)
} else {
Err(Error::InvalidData)
}
}
pub fn load_message(&self) -> Result<Message<'_>, Error> {
self.message.cast_ref::<Message<'_>>().load()
}
pub fn load_message_owned(&self) -> Result<OwnedMessage, Error> {
self.message.load()
}
pub fn message_hash(&self) -> &HashBytes {
self.message.cell.repr_hash()
}
pub fn collect_fee(&mut self, fee: Tokens) -> bool {
match self.fwd_fee_remaining.checked_sub(fee) {
Some(remaining) => {
self.fwd_fee_remaining = remaining;
true
}
None => false,
}
}
}
#[cfg(feature = "serde")]
fn serialize_account_prefix<S>(prefix: &u64, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&format!("{:08x}", prefix))
}