typhoon_accounts/accounts/
program.rs1use {
2 crate::{FromAccountInfo, ReadableAccount},
3 core::marker::PhantomData,
4 pinocchio::hint::unlikely,
5 solana_account_view::{AccountView, Ref},
6 solana_address::address_eq,
7 solana_program_error::ProgramError,
8 typhoon_errors::Error,
9 typhoon_traits::ProgramId,
10};
11
12pub struct Program<'a, T> {
17 info: &'a AccountView,
18 _phantom: PhantomData<T>,
19}
20
21impl<'a, T> FromAccountInfo<'a> for Program<'a, T>
22where
23 T: ProgramId,
24{
25 #[inline]
26 fn try_from_info(info: &'a AccountView) -> Result<Self, Error> {
27 if unlikely(!address_eq(info.address(), &T::ID)) {
29 return Err(ProgramError::IncorrectProgramId.into());
30 }
31
32 if !info.executable() {
33 return Err(ProgramError::InvalidAccountOwner.into());
34 }
35
36 Ok(Program {
37 info,
38 _phantom: PhantomData,
39 })
40 }
41}
42
43impl<'a, T> From<Program<'a, T>> for &'a AccountView {
44 #[inline(always)]
45 fn from(value: Program<'a, T>) -> Self {
46 value.info
47 }
48}
49
50impl<T> AsRef<AccountView> for Program<'_, T> {
51 #[inline(always)]
52 fn as_ref(&self) -> &AccountView {
53 self.info
54 }
55}
56
57impl<T> ReadableAccount for Program<'_, T> {
58 type DataUnchecked = [u8];
59 type Data<'a>
60 = Ref<'a, [u8]>
61 where
62 Self: 'a;
63
64 #[inline(always)]
65 fn data<'a>(&'a self) -> Result<Self::Data<'a>, Error> {
66 self.info.try_borrow().map_err(Into::into)
67 }
68
69 #[inline]
70 fn data_unchecked(&self) -> Result<&Self::DataUnchecked, Error> {
71 Ok(unsafe { self.info.borrow_unchecked() })
72 }
73}