use std::error::Error;
use solana_program::account_info::{Account, AccountInfo, IntoAccountInfo};
use solana_program::pubkey::Pubkey;
use crate::accounts::devol_account::DevolAccount;
use crate::dvl_error::DvlError;
use crate::errors::{AccountTag, ContractError};
pub trait DevolIndexedAccount : DevolAccount {
#[inline(always)]
fn id_offset() -> usize { 40 }
#[inline(always)]
fn check_id(account_info: &AccountInfo, id: Option<u32>) -> Result<(), DvlError> {
if let Some(id) = id {
let tag = AccountTag::from_u8(Self::expected_tag());
let read_id = unsafe { *(account_info.data.borrow().as_ptr().add(Self::id_offset()) as *const u32) };
if read_id != id as u32 {
return Err(DvlError::new_with_account(tag, ContractError::InvalidAccountId));
}
}
Ok(())
}
#[inline(always)]
fn check_all(account_info: &AccountInfo, root_addr: &Pubkey, program_id: &Pubkey, id: Option<u32>) -> Result<(), DvlError> {
Self::check_basic(account_info, root_addr, program_id)?;
Self::check_id(account_info, id)?;
Ok(())
}
#[inline(always)]
fn from_account_info<'a>(
account_info: &'a AccountInfo,
root_addr: &Pubkey,
program_id: &Pubkey,
id: Option<u32>,
) -> Result<&'a Self, DvlError>
where
Self: Sized,
{
let account = Self::from_account_info_basic(account_info,root_addr,program_id)?;
Self::check_id(account_info, id)?;
Ok(account)
}
#[inline(always)]
fn from_account_info_mut<'a>(
account_info: &'a AccountInfo,
root_addr: &Pubkey,
program_id: &Pubkey,
id: Option<u32>,
) -> Result<&'a mut Self, DvlError>
where
Self: Sized,
{
let account = Self::from_account_info_mut_basic(account_info,root_addr,program_id)?;
Self::check_id(account_info, id)?;
Ok(account)
}
#[inline(always)]
fn from_account(
key: &Pubkey,
account: &mut impl Account,
root_addr: &Pubkey,
program_id: &Pubkey,
id: Option<u32>,
) -> Result<Box<Self>, Box<dyn Error>>
where
Self: Sized + Copy
{
let account_info = (key, account).into_account_info();
let account_ref = Self::from_account_info(&account_info, root_addr, program_id, id)?;
Ok(Box::new(*account_ref))
}
}