Skip to main content

solana_program_pack/
lib.rs

1//! The [`Pack`] serialization trait
2//! This is a specific serialization API that is used by many older programs in
3//! the [Solana Program Library][spl] to manage account state. It is not generally
4//! recommended for new code since it does not define a language-independent
5//! serialization format.
6//!
7//! [spl]: https://github.com/solana-labs/solana-program-library
8#![no_std]
9#![cfg_attr(docsrs, feature(doc_cfg))]
10
11use solana_program_error::ProgramError;
12
13/// Check if a program account state is initialized
14pub trait IsInitialized {
15    /// Is initialized
16    fn is_initialized(&self) -> bool;
17}
18
19/// Implementors must have a known size
20pub trait Sealed: Sized {}
21
22/// Safely and efficiently (de)serialize account state
23pub trait Pack: Sealed {
24    /// The length, in bytes, of the packed representation
25    const LEN: usize;
26    #[doc(hidden)]
27    fn pack_into_slice(&self, dst: &mut [u8]);
28    #[doc(hidden)]
29    fn unpack_from_slice(src: &[u8]) -> Result<Self, ProgramError>;
30
31    /// Get the packed length
32    fn get_packed_len() -> usize {
33        Self::LEN
34    }
35
36    /// Unpack from slice and check if initialized
37    fn unpack(input: &[u8]) -> Result<Self, ProgramError>
38    where
39        Self: IsInitialized,
40    {
41        let value = Self::unpack_unchecked(input)?;
42        if value.is_initialized() {
43            Ok(value)
44        } else {
45            Err(ProgramError::UninitializedAccount)
46        }
47    }
48
49    /// Unpack from slice without checking if initialized
50    fn unpack_unchecked(input: &[u8]) -> Result<Self, ProgramError> {
51        if input.len() != Self::LEN {
52            return Err(ProgramError::InvalidAccountData);
53        }
54        Self::unpack_from_slice(input)
55    }
56
57    /// Pack into slice
58    fn pack(src: Self, dst: &mut [u8]) -> Result<(), ProgramError> {
59        if dst.len() != Self::LEN {
60            return Err(ProgramError::InvalidAccountData);
61        }
62        src.pack_into_slice(dst);
63        Ok(())
64    }
65}