Skip to main content

typhoon_accounts/
lib.rs

1#![no_std]
2
3pub use {accounts::*, discriminator::*, programs::*};
4use {
5    bytemuck::{AnyBitPattern, NoUninit},
6    solana_account_view::AccountView,
7    solana_address::Address,
8    typhoon_errors::Error,
9    typhoon_traits::Discriminator,
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    type DataUnchecked: ?Sized;
22    type Data<'a>
23    where
24        Self: 'a;
25
26    #[inline(always)]
27    fn address(&self) -> &Address {
28        self.as_ref().address()
29    }
30
31    #[inline(always)]
32    fn owned_by(&self, owner: &Address) -> bool {
33        self.as_ref().owned_by(owner)
34    }
35
36    #[inline(always)]
37    fn lamports(&self) -> u64 {
38        self.as_ref().lamports()
39    }
40
41    fn data<'a>(&'a self) -> Result<Self::Data<'a>, Error>;
42
43    fn data_unchecked(&self) -> Result<&Self::DataUnchecked, Error>;
44}
45
46pub trait WritableAccount: ReadableAccount {
47    type DataMut<'a>
48    where
49        Self: 'a;
50
51    #[inline(always)]
52    fn assign(&self, new_owner: &Address) {
53        unsafe {
54            self.as_ref().assign(new_owner);
55        }
56    }
57
58    #[inline(always)]
59    fn resize(&self, new_len: usize) -> Result<(), Error> {
60        self.as_ref().resize(new_len).map_err(Into::into)
61    }
62
63    #[inline(always)]
64    fn set_lamports(&self, lamports: u64) {
65        self.as_ref().set_lamports(lamports);
66    }
67
68    fn mut_data<'a>(&'a self) -> Result<Self::DataMut<'a>, Error>;
69}
70
71pub trait SignerAccount: ReadableAccount {}
72
73pub trait RefFromBytes {
74    fn read(data: &[u8]) -> Option<&Self>;
75    fn read_mut(data: &mut [u8]) -> Option<&mut Self>;
76}
77
78impl<T> RefFromBytes for T
79where
80    T: Discriminator + AnyBitPattern + NoUninit,
81{
82    fn read(data: &[u8]) -> Option<&Self> {
83        let dis_len = T::DISCRIMINATOR.len();
84        let total_len = dis_len + core::mem::size_of::<T>();
85
86        if data.len() < total_len {
87            return None;
88        }
89
90        let data_ptr = data[dis_len..total_len].as_ptr();
91
92        if data_ptr.align_offset(core::mem::align_of::<T>()) != 0 {
93            return None;
94        }
95
96        Some(unsafe { &*(data_ptr as *const T) })
97    }
98
99    fn read_mut(data: &mut [u8]) -> Option<&mut Self> {
100        let dis_len = T::DISCRIMINATOR.len();
101        let total_len = dis_len + core::mem::size_of::<T>();
102
103        if data.len() < total_len {
104            return None;
105        }
106
107        let data_ptr = data[dis_len..total_len].as_mut_ptr();
108
109        if data_ptr.align_offset(core::mem::align_of::<T>()) != 0 {
110            return None;
111        }
112
113        Some(unsafe { &mut *(data_ptr as *mut T) })
114    }
115}
116
117pub trait FromRaw<'a> {
118    fn from_raw(info: &'a AccountView) -> Self;
119}