uip-solana-sdk 0.16.0

Universal Interoperability Protocol Solana SDK
Documentation
use solana_program::pubkey::Pubkey;

use crate::utils::split_at_checked;

/// Trait for types that can be deserialized by reference from a byte slice
/// without cloning data from the underlying buffer.
pub(crate) trait DeserializeRef<'a>: Sized {
    /// Deserialize an instance of `Self` by borrowing from the front of `slice`.
    /// On success, advances `*slice` past the consumed bytes and returns
    /// `Some(Self)`. Returns `None` if there are not enough bytes or the data
    /// is malformed.
    fn deserialize_ref(slice: &mut &'a [u8]) -> Option<Self>;
}

/// Non-owned Message Data and message hash.
pub struct MessageDataRef<'a> {
    /// The hash of the message.
    pub msg_hash: &'a [u8; 32],

    pub total_fee: u128,
    /// The encoded target function selector.
    pub selector: &'a [u8; 32],
    /// Sender contract address.
    pub sender_addr: &'a [u8],
    /// Destination contract address.
    pub dest_addr: Pubkey,
    /// The message payload.
    pub payload: &'a [u8],
    /// Reserved field for future use.
    pub reserved: &'a [u8],
    /// Additional transmitter parameters.
    pub transmitter_params: &'a [u8],

    /// Source chain identifier.
    pub src_chain_id: u128,
    /// Proposal transaction block number.
    pub src_block_number: u128,
    /// Proposal transaction ID.
    pub src_op_tx_id: &'a [[u8; 32]; 2],
}

impl<'a> DeserializeRef<'a> for MessageDataRef<'a> {
    fn deserialize_ref(data: &mut &'a [u8]) -> Option<Self> {
        let mut read_data = |count| {
            let (left, right) = split_at_checked(data, count)?;
            *data = right;
            Some(left)
        };

        let msg_hash = read_data(32)?.try_into().unwrap();

        let total_fee = u128::from_le_bytes(read_data(16)?.try_into().unwrap());
        let selector = read_data(32)?.try_into().unwrap();

        let sender_len = u32::from_le_bytes(read_data(4)?.try_into().unwrap()) as usize;
        let sender_addr = read_data(sender_len)?;

        let dest_addr = Pubkey::new_from_array(read_data(32)?.try_into().unwrap());

        let payload_len = u32::from_le_bytes(read_data(4)?.try_into().unwrap()) as usize;
        let payload = read_data(payload_len)?;

        let reserved_len = u32::from_le_bytes(read_data(4)?.try_into().unwrap()) as usize;
        let reserved = read_data(reserved_len)?;

        let transmitter_len = u32::from_le_bytes(read_data(4)?.try_into().unwrap()) as usize;
        let transmitter_params = read_data(transmitter_len)?;

        let src_chain_id = u128::from_le_bytes(read_data(16)?.try_into().unwrap());

        let src_block_number = u128::from_le_bytes(read_data(16)?.try_into().unwrap());
        let src_op_tx_id: &[u8; 64] = read_data(64)?.try_into().unwrap();
        let src_op_tx_id: &[[u8; 32]; 2] = bytemuck::cast_ref(src_op_tx_id);

        Some(MessageDataRef {
            payload,
            src_chain_id,
            sender_addr,
            msg_hash,
            total_fee,
            selector,
            dest_addr,
            reserved,
            transmitter_params,
            src_block_number,
            src_op_tx_id,
        })
    }
}