use {
super::GeneratorResult,
crate::{
accounts::Account,
constraints::{ConstraintInit, ConstraintInitIfNeeded},
context::Context,
visitor::ContextVisitor,
StagedGenerator,
},
proc_macro2::TokenStream,
quote::quote,
};
struct AccountGenerator<'a> {
account: &'a Account,
has_init: bool,
has_init_if_needed: bool,
}
impl<'a> AccountGenerator<'a> {
pub fn new(account: &'a Account) -> Self {
Self {
account,
has_init: false,
has_init_if_needed: false,
}
}
pub fn generate(&self) -> Result<TokenStream, syn::Error> {
let name = &self.account.name;
let name_str = name.to_string();
if self.has_init {
Ok(quote! {
let #name = <Mut<SystemAccount> as FromAccountInfo>::try_from_info(#name).trace_account(#name_str)?;
})
} else if self.has_init_if_needed {
Ok(quote! {
let #name = <Mut<UncheckedAccount> as FromAccountInfo>::try_from_info(#name).trace_account(#name_str)?;
})
} else {
let account_ty = &self.account.ty;
Ok(quote! {
let #name = <#account_ty as FromAccountInfo>::try_from_info(#name).trace_account(#name_str)?;
})
}
}
}
impl ContextVisitor for AccountGenerator<'_> {
fn visit_init(&mut self, _constraint: &ConstraintInit) -> Result<(), syn::Error> {
self.has_init = true;
Ok(())
}
fn visit_init_if_needed(
&mut self,
_constraint: &ConstraintInitIfNeeded,
) -> Result<(), syn::Error> {
self.has_init_if_needed = true;
Ok(())
}
}
pub struct AssignGenerator<'a>(&'a Context);
impl<'a> AssignGenerator<'a> {
pub fn new(context: &'a Context) -> Self {
AssignGenerator(context)
}
}
impl StagedGenerator for AssignGenerator<'_> {
fn append(&mut self, context: &mut GeneratorResult) -> Result<(), syn::Error> {
for account in &self.0.accounts {
let mut generator = AccountGenerator::new(account);
generator.visit_account(account)?;
context.inside.extend(generator.generate()?);
}
Ok(())
}
}