2020-09-17 21:10:02 -06:00
|
|
|
//! State transition types
|
|
|
|
|
|
|
|
use crate::program_error::ProgramError;
|
|
|
|
|
|
|
|
/// Check if a program account state is initialized
|
|
|
|
pub trait IsInitialized {
|
|
|
|
/// Is initialized
|
|
|
|
fn is_initialized(&self) -> bool;
|
|
|
|
}
|
|
|
|
|
2020-10-29 14:16:01 -07:00
|
|
|
/// Implementors must have a known size
|
2020-09-17 21:10:02 -06:00
|
|
|
pub trait Sealed: Sized {}
|
|
|
|
|
|
|
|
/// Safely and efficiently (de)serialize account state
|
|
|
|
pub trait Pack: Sealed {
|
|
|
|
/// The length, in bytes, of the packed representation
|
|
|
|
const LEN: usize;
|
|
|
|
#[doc(hidden)]
|
|
|
|
fn pack_into_slice(&self, dst: &mut [u8]);
|
|
|
|
#[doc(hidden)]
|
|
|
|
fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError>;
|
|
|
|
|
|
|
|
/// Get the packed length
|
|
|
|
fn get_packed_len() -> usize {
|
|
|
|
Self::LEN
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Unpack from slice and check if initialized
|
|
|
|
fn unpack(input: &[u8]) -> Result<Self, ProgramError>
|
|
|
|
where
|
|
|
|
Self: IsInitialized,
|
|
|
|
{
|
|
|
|
let value = Self::unpack_unchecked(input)?;
|
|
|
|
if value.is_initialized() {
|
|
|
|
Ok(value)
|
|
|
|
} else {
|
|
|
|
Err(ProgramError::UninitializedAccount)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Unpack from slice without checking if initialized
|
|
|
|
fn unpack_unchecked(input: &[u8]) -> Result<Self, ProgramError> {
|
|
|
|
if input.len() != Self::LEN {
|
|
|
|
return Err(ProgramError::InvalidAccountData);
|
|
|
|
}
|
2021-01-23 11:55:15 -08:00
|
|
|
Self::unpack_from_slice(input)
|
2020-09-17 21:10:02 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Pack into slice
|
|
|
|
fn pack(src: Self, dst: &mut [u8]) -> Result<(), ProgramError> {
|
|
|
|
if dst.len() != Self::LEN {
|
|
|
|
return Err(ProgramError::InvalidAccountData);
|
|
|
|
}
|
|
|
|
src.pack_into_slice(dst);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
}
|