use hopper_runtime::error::ProgramError;
use hopper_runtime::{AccountView, Address};
use crate::account::{FixedLayout, Pod, VerifiedAccount, VerifiedAccountMut};
use crate::check;
use crate::check::modifier::HopperLayout;
pub struct HopperAccount<'a, T: Pod + FixedLayout + HopperLayout> {
view: &'a AccountView,
#[allow(dead_code)] program_id: &'a Address,
_marker: core::marker::PhantomData<T>,
}
impl<'a, T: Pod + FixedLayout + HopperLayout> HopperAccount<'a, T> {
#[inline]
pub fn from_account(
account: &'a AccountView,
program_id: &'a Address,
) -> Result<Self, ProgramError> {
check::check_owner(account, program_id)?;
let data = account.try_borrow()?;
crate::account::check_header(&data, T::DISC, T::VERSION, &T::LAYOUT_ID)?;
check::check_size(&data, T::LEN_WITH_HEADER)?;
Ok(Self {
view: account,
program_id,
_marker: core::marker::PhantomData,
})
}
#[inline]
pub fn from_account_mut(
account: &'a AccountView,
program_id: &'a Address,
) -> Result<Self, ProgramError> {
check::check_writable(account)?;
Self::from_account(account, program_id)
}
#[inline]
pub fn read(&self) -> Result<VerifiedAccount<'a, T>, ProgramError> {
let data = self.view.try_borrow()?;
VerifiedAccount::from_ref(data)
}
#[inline]
pub fn write(&self) -> Result<VerifiedAccountMut<'a, T>, ProgramError> {
let data = self.view.try_borrow_mut()?;
VerifiedAccountMut::from_ref_mut(data)
}
#[inline(always)]
pub fn address(&self) -> &Address {
self.view.address()
}
#[inline(always)]
pub unsafe fn owner(&self) -> &Address {
unsafe { self.view.owner() }
}
#[inline(always)]
pub fn to_account_view(&self) -> &'a AccountView {
self.view
}
#[inline(always)]
pub fn lamports(&self) -> u64 {
self.view.lamports()
}
}