Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions pinocchio/interface/src/state/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ unsafe impl Transmutable for Account {
const LEN: usize = core::mem::size_of::<Account>();
}

impl super::sealed::Sealed for Account {}

impl Initializable for Account {
#[inline(always)]
fn is_initialized(&self) -> Result<bool, ProgramError> {
Expand Down
2 changes: 2 additions & 0 deletions pinocchio/interface/src/state/mint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ unsafe impl Transmutable for Mint {
const LEN: usize = core::mem::size_of::<Mint>();
}

impl super::sealed::Sealed for Mint {}

impl Initializable for Mint {
#[inline(always)]
fn is_initialized(&self) -> Result<bool, ProgramError> {
Expand Down
22 changes: 21 additions & 1 deletion pinocchio/interface/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ pub type COption<T> = ([u8; 4], T);
/// It is up to the type implementing this trait to guarantee that the cast is
/// safe, i.e., the fields of the type are well aligned and there are no padding
/// bytes.
pub unsafe trait Transmutable {
pub unsafe trait Transmutable: sealed::Sealed {
/// The length of the type.
///
/// This must be equal to the size of each individual field in the type.
Expand Down Expand Up @@ -57,6 +57,13 @@ pub unsafe fn load<T: Initializable + Transmutable>(bytes: &[u8]) -> Result<&T,
/// The caller must ensure that `bytes` contains a valid representation of `T`.
#[inline(always)]
pub unsafe fn load_unchecked<T: Transmutable>(bytes: &[u8]) -> Result<&T, ProgramError> {
const {
assert!(
core::mem::align_of::<T>() == 1,
"<T> must have minimum alignment of 1"
);
};

if unlikely(bytes.len() != T::LEN) {
return Err(ProgramError::InvalidAccountData);
}
Expand Down Expand Up @@ -93,8 +100,21 @@ pub unsafe fn load_mut<T: Initializable + Transmutable>(
pub unsafe fn load_mut_unchecked<T: Transmutable>(
bytes: &mut [u8],
) -> Result<&mut T, ProgramError> {
const {
assert!(
core::mem::align_of::<T>() == 1,
"<T> must have minimum alignment of 1"
);
};

if unlikely(bytes.len() != T::LEN) {
return Err(ProgramError::InvalidAccountData);
}
Ok(&mut *(bytes.as_mut_ptr() as *mut T))
}

/// Private module to seal the `Transmutable` trait.
mod sealed {
/// Sealed trait to prevent external implementation of `Transmutable`.
pub trait Sealed {}
}
2 changes: 2 additions & 0 deletions pinocchio/interface/src/state/multisig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ unsafe impl Transmutable for Multisig {
const LEN: usize = core::mem::size_of::<Multisig>();
}

impl super::sealed::Sealed for Multisig {}

impl Initializable for Multisig {
#[inline(always)]
fn is_initialized(&self) -> Result<bool, ProgramError> {
Expand Down
Loading