use crate::{
account_set::{
AccountSetCleanup, AccountSetDecode, AccountSetValidate, ClientAccountSet, CpiAccountSet,
DynamicCpiAccountSetLen,
},
prelude::*,
};
use derive_more::{Deref, DerefMut};
#[derive(AccountSet, Debug, Deref, DerefMut, Clone)]
#[account_set(
skip_cpi_account_set,
skip_client_account_set,
skip_default_decode,
skip_default_idl
)]
#[validate(generics = [<A> where T: AccountSetValidate<A>, A: Clone], arg = A)]
#[cleanup(generics = [<A> where T: AccountSetCleanup<A>, A: Clone], arg = A)]
pub struct Rest<T>(
#[validate(arg = (arg,))]
#[cleanup(arg = (arg,))]
Vec<T>,
);
unsafe impl<T> CpiAccountSet for Rest<T>
where
T: CpiAccountSet,
{
type ContainsOption = T::ContainsOption;
type CpiAccounts = Vec<T::CpiAccounts>;
type AccountLen = DynamicCpiAccountSetLen;
#[inline]
fn to_cpi_accounts(&self) -> Self::CpiAccounts {
CpiAccountSet::to_cpi_accounts(&self.0)
}
fn write_account_infos<'a>(
program: Option<&'a AccountInfo>,
accounts: &'a Self::CpiAccounts,
index: &mut usize,
infos: &mut [std::mem::MaybeUninit<&'a AccountInfo>],
) -> Result<()> {
<Vec<T>>::write_account_infos(program, accounts, index, infos)
}
fn write_account_metas<'a>(
program_id: &'a Pubkey,
accounts: &'a Self::CpiAccounts,
index: &mut usize,
metas: &mut [std::mem::MaybeUninit<pinocchio::instruction::AccountMeta<'a>>],
) {
<Vec<T>>::write_account_metas(program_id, accounts, index, metas);
}
}
impl<T> ClientAccountSet for Rest<T>
where
T: ClientAccountSet,
{
type ClientAccounts = Vec<T::ClientAccounts>;
const MIN_LEN: usize = 0;
#[inline]
fn extend_account_metas(
program_id: &Pubkey,
accounts: &Self::ClientAccounts,
metas: &mut Vec<AccountMeta>,
) {
<Vec<T>>::extend_account_metas(program_id, accounts, metas);
}
}
impl<'a, A, T> AccountSetDecode<'a, A> for Rest<T>
where
T: AccountSetDecode<'a, A>,
A: Clone,
{
fn decode_accounts(
accounts: &mut &'a [AccountInfo],
decode_input: A,
ctx: &mut Context,
) -> Result<Self> {
let mut out = vec![];
while !accounts.is_empty() {
out.push(T::decode_accounts(accounts, decode_input.clone(), ctx)?);
}
Ok(Self(out))
}
}
#[cfg(all(feature = "idl", not(target_os = "solana")))]
mod idl_impl {
use super::*;
use crate::idl::AccountSetToIdl;
impl<T, A> AccountSetToIdl<A> for Rest<T>
where
T: AccountSetToIdl<A>,
A: Clone,
{
fn account_set_to_idl(
idl_definition: &mut star_frame::__private::macro_prelude::IdlDefinition,
arg: A,
) -> star_frame::IdlResult<star_frame::__private::macro_prelude::IdlAccountSetDef> {
<Vec<T> as AccountSetToIdl<_>>::account_set_to_idl(idl_definition, (.., arg))
}
}
}