1#![no_std]
2
3pub use {accounts::*, discriminator::*, programs::*};
4use {
5 solana_account_view::{AccountView, Ref, RefMut},
6 solana_address::Address,
7 solana_program_error::ProgramError,
8 typhoon_errors::Error,
9 typhoon_traits::{Accessor, DataStrategy, Discriminator, MutAccessor},
10};
11
12mod accounts;
13mod discriminator;
14mod programs;
15
16pub trait FromAccountInfo<'a>: Sized {
17 fn try_from_info(info: &'a AccountView) -> Result<Self, Error>;
18}
19
20pub trait ReadableAccount: AsRef<AccountView> {
21 #[inline(always)]
22 fn address(&self) -> &Address {
23 self.as_ref().address()
24 }
25
26 #[inline(always)]
27 fn owned_by(&self, owner: &Address) -> bool {
28 self.as_ref().owned_by(owner)
29 }
30
31 #[inline(always)]
32 fn lamports(&self) -> u64 {
33 self.as_ref().lamports()
34 }
35
36 #[inline(always)]
37 fn raw_data(&self) -> Result<Ref<'_, [u8]>, ProgramError> {
38 self.as_ref().try_borrow()
39 }
40}
41
42pub trait WritableAccount: ReadableAccount {
43 #[inline(always)]
44 fn assign(&self, new_owner: &Address) {
45 unsafe {
46 self.as_ref().assign(new_owner);
47 }
48 }
49
50 #[inline(always)]
51 fn resize(&self, new_len: usize) -> Result<(), Error> {
52 self.as_ref().resize(new_len).map_err(Into::into)
53 }
54
55 #[inline(always)]
56 fn set_lamports(&self, lamports: u64) {
57 self.as_ref().set_lamports(lamports);
58 }
59
60 #[inline(always)]
61 fn raw_mut_data(&self) -> Result<RefMut<'_, [u8]>, ProgramError> {
62 self.as_ref().try_borrow_mut()
63 }
64}
65
66pub trait SignerAccount: ReadableAccount {}
67
68pub trait AccountData: ReadableAccount {
69 type Data: Discriminator + DataStrategy;
70}
71
72pub trait ReadableAccountData: AccountData {
73 #[inline(always)]
74 fn data(&self) -> Result<Ref<'_, Self::Data>, ProgramError>
75 where
76 <Self::Data as DataStrategy>::Strategy:
77 for<'a> Accessor<'a, Self::Data, Data = &'a Self::Data>,
78 {
79 Ref::try_map(self.as_ref().try_borrow()?, |data| {
80 <<Self::Data as DataStrategy>::Strategy as Accessor<'_, Self::Data>>::access(
81 &data[Self::Data::DISCRIMINATOR.len()..],
82 )
83 })
84 .map_err(|_| ProgramError::InvalidAccountData)
85 }
86
87 #[inline(always)]
88 fn data_owned(&self) -> Result<Self::Data, ProgramError>
89 where
90 <Self::Data as DataStrategy>::Strategy: for<'a> Accessor<'a, Self::Data, Data = Self::Data>,
91 {
92 self.as_ref().check_borrow()?;
93 let data = unsafe { self.as_ref().borrow_unchecked() };
94 <<Self::Data as DataStrategy>::Strategy as Accessor<'_, Self::Data>>::access(
95 &data[Self::Data::DISCRIMINATOR.len()..],
96 )
97 }
98
99 #[inline(always)]
100 fn data_unchecked(
101 &self,
102 ) -> Result<
103 <<Self::Data as DataStrategy>::Strategy as Accessor<'_, Self::Data>>::Data,
104 ProgramError,
105 >
106 where
107 <Self::Data as DataStrategy>::Strategy: for<'a> Accessor<'a, Self::Data>,
108 {
109 let data = unsafe { self.as_ref().borrow_unchecked() };
110 <<Self::Data as DataStrategy>::Strategy as Accessor<'_, Self::Data>>::access(
111 &data[Self::Data::DISCRIMINATOR.len()..],
112 )
113 }
114}
115
116impl<T> ReadableAccountData for T where T: AccountData {}
117
118pub trait WritableAccountData: AccountData + WritableAccount {
119 #[inline(always)]
120 fn mut_data(&self) -> Result<RefMut<'_, Self::Data>, Error>
121 where
122 <Self::Data as DataStrategy>::Strategy:
123 for<'a> MutAccessor<'a, Self::Data, Data = &'a mut Self::Data>,
124 {
125 RefMut::try_map(self.as_ref().try_borrow_mut()?, |data| {
126 <<Self::Data as DataStrategy>::Strategy as MutAccessor<'_, Self::Data>>::access_mut(
127 &mut data[Self::Data::DISCRIMINATOR.len()..],
128 )
129 })
130 .map_err(|_| ProgramError::InvalidAccountData.into())
131 }
132}
133
134impl<T> WritableAccountData for T where T: AccountData + WritableAccount {}
135
136pub trait FromRaw<'a> {
137 fn from_raw(info: &'a AccountView) -> Self;
138}