Skip to main content

typhoon_accounts/accounts/
interface.rs

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