use pinocchio::{account_info::AccountInfo, program_error::ProgramError, ProgramResult};
pub trait InstructionProcessor<'a, Ix, T>: Sized {
fn from_accounts(accounts: &'a [AccountInfo]) -> Result<Self, ProgramError>;
fn try_process(&self, instruction: Ix) -> ProgramResult {
self.log_ix();
let validations_result = self.validations(&instruction)?;
self.process(instruction, validations_result)
}
fn process(&self, instruction: Ix, validations_result: Option<T>) -> ProgramResult;
fn validations(&self, instruction: &Ix) -> Result<Option<T>, ProgramError>;
fn log_ix(&self);
}
#[cfg(test)]
mod test {
use pinocchio::msg;
use super::*;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum TestInstruction {
Hello { msg: Vec<u8> },
Init { force: bool },
}
pub struct HelloAccounts<'a> {
payer: &'a AccountInfo,
msg: &'a AccountInfo,
system_program: &'a AccountInfo,
}
pub struct HelloAccountsValidationResult {
pub nocne: u8,
}
impl<'a> TryFrom<&'a [AccountInfo]> for HelloAccounts<'a> {
type Error = ProgramError;
fn try_from(accounts: &'a [AccountInfo]) -> Result<Self, Self::Error> {
let [payer, msg, system_program] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
Ok(Self {
payer,
msg,
system_program,
})
}
}
impl<'a> InstructionProcessor<'a, TestInstruction, ()> for HelloAccounts<'a> {
fn from_accounts(accounts: &'a [AccountInfo]) -> Result<Self, ProgramError> {
HelloAccounts::try_from(accounts)
}
fn process(
&self,
instruction: TestInstruction,
validations_result: Option<()>,
) -> ProgramResult {
Ok(())
}
fn validations(&self, instruction: &TestInstruction) -> Result<Option<()>, ProgramError> {
Ok(None)
}
fn log_ix(&self) {
msg!("Instruction: HelloAccounts")
}
}
impl<'a> InstructionProcessor<'a, TestInstruction, HelloAccountsValidationResult>
for HelloAccounts<'a>
{
fn from_accounts(accounts: &'a [AccountInfo]) -> Result<Self, ProgramError> {
HelloAccounts::try_from(accounts)
}
fn process(
&self,
instruction: TestInstruction,
validations_result: Option<HelloAccountsValidationResult>,
) -> ProgramResult {
Ok(())
}
fn validations(
&self,
instruction: &TestInstruction,
) -> Result<Option<HelloAccountsValidationResult>, ProgramError> {
Ok(None)
}
fn log_ix(&self) {
msg!("Instruction: HelloAccounts")
}
}
}