typhoon_accounts/
lib.rs

1#![no_std]
2
3pub use {accounts::*, discriminator::*, programs::*};
4use {
5    bytemuck::{AnyBitPattern, NoUninit},
6    pinocchio::{
7        account_info::{AccountInfo, Ref, RefMut},
8        pubkey::Pubkey,
9    },
10    sealed::Sealed,
11    typhoon_errors::Error,
12};
13
14mod accounts;
15mod discriminator;
16mod programs;
17
18pub trait FromAccountInfo<'a>: Sized {
19    fn try_from_info(info: &'a AccountInfo) -> Result<Self, Error>;
20}
21
22pub trait ReadableAccount: AsRef<AccountInfo> {
23    type DataUnchecked: ?Sized;
24    type Data<'a>
25    where
26        Self: 'a;
27
28    #[inline(always)]
29    fn key(&self) -> &Pubkey {
30        self.as_ref().key()
31    }
32
33    #[inline(always)]
34    fn is_owned_by(&self, owner: &Pubkey) -> bool {
35        self.as_ref().is_owned_by(owner)
36    }
37
38    #[inline(always)]
39    fn lamports(&self) -> Result<Ref<'_, u64>, Error> {
40        self.as_ref().try_borrow_lamports().map_err(Into::into)
41    }
42
43    fn data<'a>(&'a self) -> Result<Self::Data<'a>, Error>;
44
45    fn data_unchecked(&self) -> Result<&Self::DataUnchecked, Error>;
46}
47
48pub trait WritableAccount: ReadableAccount + Sealed {
49    type DataMut<'a>
50    where
51        Self: 'a;
52
53    #[inline(always)]
54    fn assign(&self, new_owner: &Pubkey) {
55        unsafe {
56            self.as_ref().assign(new_owner);
57        }
58    }
59
60    #[inline(always)]
61    fn resize(&self, new_len: usize) -> Result<(), Error> {
62        self.as_ref().resize(new_len).map_err(Into::into)
63    }
64
65    #[inline(always)]
66    fn mut_lamports(&self) -> Result<RefMut<'_, u64>, Error> {
67        self.as_ref().try_borrow_mut_lamports().map_err(Into::into)
68    }
69
70    fn mut_data<'a>(&'a self) -> Result<Self::DataMut<'a>, Error>;
71}
72
73pub trait SignerAccount: ReadableAccount + Sealed {}
74
75mod sealed {
76    use {
77        super::{Mut, ReadableAccount, Signer},
78        crate::SignerCheck,
79        pinocchio::account_info::AccountInfo,
80    };
81
82    pub trait Sealed {}
83
84    impl<T> Sealed for Mut<T> where T: ReadableAccount + AsRef<AccountInfo> {}
85    impl<T, C> Sealed for Signer<'_, T, C>
86    where
87        T: ReadableAccount,
88        C: SignerCheck,
89    {
90    }
91}
92
93pub trait ProgramId {
94    const ID: Pubkey;
95}
96
97pub trait ProgramIds {
98    const IDS: &'static [Pubkey];
99}
100
101pub trait Owner {
102    const OWNER: Pubkey;
103}
104
105pub trait Owners {
106    const OWNERS: &'static [Pubkey];
107}
108
109pub trait Discriminator {
110    const DISCRIMINATOR: &'static [u8];
111}
112
113pub trait RefFromBytes {
114    fn read(data: &[u8]) -> Option<&Self>;
115    fn read_mut(data: &mut [u8]) -> Option<&mut Self>;
116}
117
118impl<T> RefFromBytes for T
119where
120    T: Discriminator + AnyBitPattern + NoUninit,
121{
122    fn read(data: &[u8]) -> Option<&Self> {
123        let dis_len = T::DISCRIMINATOR.len();
124        let total_len = dis_len + core::mem::size_of::<T>();
125
126        if data.len() < total_len {
127            return None;
128        }
129
130        let data_ptr = data[dis_len..total_len].as_ptr();
131
132        if data_ptr.align_offset(core::mem::align_of::<T>()) != 0 {
133            return None;
134        }
135
136        Some(unsafe { &*(data_ptr as *const T) })
137    }
138
139    fn read_mut(data: &mut [u8]) -> Option<&mut Self> {
140        let dis_len = T::DISCRIMINATOR.len();
141        let total_len = dis_len + core::mem::size_of::<T>();
142
143        if data.len() < total_len {
144            return None;
145        }
146
147        let data_ptr = data[dis_len..total_len].as_mut_ptr();
148
149        if data_ptr.align_offset(core::mem::align_of::<T>()) != 0 {
150            return None;
151        }
152
153        Some(unsafe { &mut *(data_ptr as *mut T) })
154    }
155}
156
157pub trait FromRaw<'a> {
158    fn from_raw(info: &'a AccountInfo) -> Self;
159}