use pinocchio::program_error::ProgramError;
pub trait Account {}
pub trait Instruction {}
use crate::trace;
pub trait Discriminator {
fn discriminator() -> u8;
}
pub trait AccountDeserialize {
fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError>;
fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError>;
}
impl<T> AccountDeserialize for T
where
T: Discriminator + Account,
{
#[inline]
fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError> {
if data.len() != core::mem::size_of::<Self>() {
return Err(trace(
"Account has wrong length",
ProgramError::InvalidAccountData,
));
}
if Self::discriminator().ne(&data[0]) {
return Err(trace(
"Account has wrong discriminator",
ProgramError::InvalidAccountData,
));
}
if (data.as_ptr() as usize) % core::mem::align_of::<Self>() != 0 {
return Err(trace(
"Account has wrong alignment",
ProgramError::InvalidAccountData,
));
}
Ok(unsafe { &*(data.as_ptr() as *const Self) })
}
#[inline]
fn try_from_bytes_mut(data: &mut [u8]) -> Result<&mut Self, ProgramError> {
if data.len() != core::mem::size_of::<Self>() {
return Err(trace(
"Account has wrong length",
ProgramError::InvalidAccountData,
));
}
if Self::discriminator().ne(&data[0]) {
return Err(trace(
"Account has wrong discriminator",
ProgramError::InvalidAccountData,
));
}
if (data.as_ptr() as usize) % core::mem::align_of::<Self>() != 0 {
return Err(trace(
"Account has wrong alignment",
ProgramError::InvalidAccountData,
));
}
Ok(unsafe { &mut *(data.as_mut_ptr() as *mut Self) })
}
}
pub trait InstructionDeserialize {
fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError>;
}
impl<T> InstructionDeserialize for T
where
T: Instruction,
{
#[inline]
fn try_from_bytes(data: &[u8]) -> Result<&Self, ProgramError> {
if data.len() != core::mem::size_of::<Self>() {
return Err(ProgramError::InvalidInstructionData);
}
if (data.as_ptr() as usize) % core::mem::align_of::<Self>() != 0 {
return Err(ProgramError::InvalidInstructionData);
}
Ok(unsafe { &*(data.as_ptr() as *const Self) })
}
}
pub trait AccountHeaderDeserialize {
fn try_header_from_bytes(data: &[u8]) -> Result<(&Self, &[u8]), ProgramError>;
fn try_header_from_bytes_mut(data: &mut [u8]) -> Result<(&mut Self, &mut [u8]), ProgramError>;
}
impl<T> AccountHeaderDeserialize for T
where
T: Discriminator + Account,
{
#[inline]
fn try_header_from_bytes(data: &[u8]) -> Result<(&Self, &[u8]), ProgramError> {
if data.len() < core::mem::size_of::<Self>() {
return Err(ProgramError::InvalidAccountData);
}
if Self::discriminator().ne(&data[0]) {
return Err(ProgramError::InvalidAccountData);
}
let (header, body) = data.split_at(core::mem::size_of::<Self>());
if (header.as_ptr() as usize) % core::mem::align_of::<Self>() != 0 {
return Err(ProgramError::InvalidAccountData);
}
Ok((unsafe { &*(header.as_ptr() as *const Self) }, body))
}
#[inline]
fn try_header_from_bytes_mut(data: &mut [u8]) -> Result<(&mut Self, &mut [u8]), ProgramError> {
if data.len() < core::mem::size_of::<Self>() {
return Err(ProgramError::InvalidAccountData);
}
if Self::discriminator().ne(&data[0]) {
return Err(ProgramError::InvalidAccountData);
}
let (header, body) = data.split_at_mut(core::mem::size_of::<Self>());
if (header.as_ptr() as usize) % core::mem::align_of::<Self>() != 0 {
return Err(ProgramError::InvalidAccountData);
}
Ok((unsafe { &mut *(header.as_mut_ptr() as *mut Self) }, body))
}
}
pub trait InstructionHeaderDeserialize {
fn try_header_from_bytes(data: &[u8]) -> Result<(&Self, &[u8]), ProgramError>;
}
impl<T> InstructionHeaderDeserialize for T
where
T: Instruction,
{
#[inline]
fn try_header_from_bytes(data: &[u8]) -> Result<(&Self, &[u8]), ProgramError> {
if data.len() < core::mem::size_of::<Self>() {
return Err(ProgramError::InvalidInstructionData);
}
let (header, body) = data.split_at(core::mem::size_of::<Self>());
if (header.as_ptr() as usize) % core::mem::align_of::<Self>() != 0 {
return Err(ProgramError::InvalidInstructionData);
}
Ok((unsafe { &*(header.as_ptr() as *const Self) }, body))
}
}