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}