spl_token_interface/state/
mod.rs

1use pinocchio::program_error::ProgramError;
2
3pub mod account;
4pub mod account_state;
5pub mod mint;
6pub mod multisig;
7
8/// Type alias for fields represented as `COption`.
9pub type COption<T> = ([u8; 4], T);
10
11/// Marker trait for types that can cast from a raw pointer.
12///
13/// It is up to the type implementing this trait to guarantee that the cast is safe,
14/// i.e., that the fields of the type are well aligned and there are no padding bytes.
15pub trait RawType {
16    /// The length of the type.
17    ///
18    /// This must be equal to the size of each individual field in the type.
19    const LEN: usize;
20}
21
22/// Trait to represent a type that can be initialized.
23pub trait Initializable {
24    /// Return `true` if the object is initialized.
25    fn is_initialized(&self) -> bool;
26}
27
28/// Return a reference for an initialized `T` from the given bytes.
29///
30/// # Safety
31///
32/// The caller must ensure that `bytes` contains a valid representation of `T`.
33#[inline(always)]
34pub unsafe fn load<T: Initializable + RawType>(bytes: &[u8]) -> Result<&T, ProgramError> {
35    load_unchecked(bytes).and_then(|t: &T| {
36        // checks if the data is initialized
37        if t.is_initialized() {
38            Ok(t)
39        } else {
40            Err(ProgramError::UninitializedAccount)
41        }
42    })
43}
44
45/// Return a `T` reference from the given bytes.
46///
47/// This function does not check if the data is initialized.
48///
49/// # Safety
50///
51/// The caller must ensure that `bytes` contains a valid representation of `T`.
52#[inline(always)]
53pub unsafe fn load_unchecked<T: RawType>(bytes: &[u8]) -> Result<&T, ProgramError> {
54    if bytes.len() != T::LEN {
55        return Err(ProgramError::InvalidAccountData);
56    }
57    Ok(&*(bytes.as_ptr() as *const T))
58}
59
60/// Return a mutable reference for an initialized `T` from the given bytes.
61///
62/// # Safety
63///
64/// The caller must ensure that `bytes` contains a valid representation of `T`.
65#[inline(always)]
66pub unsafe fn load_mut<T: Initializable + RawType>(
67    bytes: &mut [u8],
68) -> Result<&mut T, ProgramError> {
69    load_mut_unchecked(bytes).and_then(|t: &mut T| {
70        // checks if the data is initialized
71        if t.is_initialized() {
72            Ok(t)
73        } else {
74            Err(ProgramError::UninitializedAccount)
75        }
76    })
77}
78
79/// Return a mutable `T` reference from the given bytes.
80///
81/// This function does not check if the data is initialized.
82///
83/// # Safety
84///
85/// The caller must ensure that `bytes` contains a valid representation of `T`.
86#[inline(always)]
87pub unsafe fn load_mut_unchecked<T: RawType>(bytes: &mut [u8]) -> Result<&mut T, ProgramError> {
88    if bytes.len() != T::LEN {
89        return Err(ProgramError::InvalidAccountData);
90    }
91    Ok(&mut *(bytes.as_mut_ptr() as *mut T))
92}