solana_program/
program_pack.rs

1//! The [`Pack`] serialization trait.
2
3use crate::program_error::ProgramError;
4
5/// Check if a program account state is initialized
6pub trait IsInitialized {
7    /// Is initialized
8    fn is_initialized(&self) -> bool;
9}
10
11/// Implementors must have a known size
12pub trait Sealed: Sized {}
13
14/// Safely and efficiently (de)serialize account state
15pub trait Pack: Sealed {
16    /// The length, in bytes, of the packed representation
17    const LEN: usize;
18    #[doc(hidden)]
19    fn pack_into_slice(&self, dst: &mut [u8]);
20    #[doc(hidden)]
21    fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError>;
22
23    /// Get the packed length
24    fn get_packed_len() -> usize {
25        Self::LEN
26    }
27
28    /// Unpack from slice and check if initialized
29    fn unpack(input: &[u8]) -> Result<Self, ProgramError>
30    where
31        Self: IsInitialized,
32    {
33        let value = Self::unpack_unchecked(input)?;
34        if value.is_initialized() {
35            Ok(value)
36        } else {
37            Err(ProgramError::UninitializedAccount)
38        }
39    }
40
41    /// Unpack from slice without checking if initialized
42    fn unpack_unchecked(input: &[u8]) -> Result<Self, ProgramError> {
43        if input.len() != Self::LEN {
44            return Err(ProgramError::InvalidAccountData);
45        }
46        Self::unpack_from_slice(input)
47    }
48
49    /// Pack into slice
50    fn pack(src: Self, dst: &mut [u8]) -> Result<(), ProgramError> {
51        if dst.len() != Self::LEN {
52            return Err(ProgramError::InvalidAccountData);
53        }
54        src.pack_into_slice(dst);
55        Ok(())
56    }
57}