use auto_impl::auto_impl;
use interpreter::{
instructions::{instruction_table, InstructionTable},
Host, Instruction, InterpreterTypes,
};
use std::boxed::Box;
#[auto_impl(&, Arc, Rc)]
pub trait InstructionProvider {
type Context;
type InterpreterTypes: InterpreterTypes;
fn instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context>;
}
pub struct EthInstructions<WIRE: InterpreterTypes, HOST> {
pub instruction_table: Box<InstructionTable<WIRE, HOST>>,
}
impl<WIRE, HOST> Clone for EthInstructions<WIRE, HOST>
where
WIRE: InterpreterTypes,
{
fn clone(&self) -> Self {
Self {
instruction_table: self.instruction_table.clone(),
}
}
}
impl<WIRE, HOST> EthInstructions<WIRE, HOST>
where
WIRE: InterpreterTypes,
HOST: Host,
{
pub fn new_mainnet() -> Self {
Self::new(instruction_table::<WIRE, HOST>())
}
pub fn new(base_table: InstructionTable<WIRE, HOST>) -> Self {
Self {
instruction_table: Box::new(base_table),
}
}
pub fn insert_instruction(&mut self, opcode: u8, instruction: Instruction<WIRE, HOST>) {
self.instruction_table[opcode as usize] = instruction;
}
}
impl<IT, CTX> InstructionProvider for EthInstructions<IT, CTX>
where
IT: InterpreterTypes,
CTX: Host,
{
type InterpreterTypes = IT;
type Context = CTX;
fn instruction_table(&self) -> &InstructionTable<Self::InterpreterTypes, Self::Context> {
&self.instruction_table
}
}
impl<WIRE, HOST> Default for EthInstructions<WIRE, HOST>
where
WIRE: InterpreterTypes,
HOST: Host,
{
fn default() -> Self {
Self::new_mainnet()
}
}