use alloc::vec::Vec;
use codec::Decode;
use corevm_engine::{InnerVm, OuterVm};
use corevm_host::PageSegment;
use jam_pvm_common::{
refine::{
export_slice, expunge, foreign_lookup, invoke, machine, peek_into, poke, void, zero, Fetch,
},
ApiError, InvokeOutcome,
};
use jam_types::{Hash, ServiceId, SignedGas, WorkPackage};
#[derive(Default)]
pub struct JamOuterVm;
impl OuterVm for JamOuterVm {
type InnerVm = JamInnerVm;
fn import(&mut self, i: usize) -> Option<PageSegment> {
let mut segment = PageSegment::null();
Fetch::OurImport(i).fetch_into(segment.as_mut(), 0)?;
Some(segment)
}
fn export(&mut self, segment: &[u8]) -> Result<(), ApiError> {
export_slice(segment)?;
Ok(())
}
fn lookup(&mut self, service_id: ServiceId, hash: &Hash) -> Option<Vec<u8>> {
foreign_lookup(service_id, hash)
}
fn get_export_count(&mut self) -> u16 {
let work_package = Fetch::WorkPackage.fetch().expect("Failed to fetch work package");
let work_package =
WorkPackage::decode(&mut &work_package[..]).expect("Failed to decode work package");
assert_eq!(1, work_package.items.len());
work_package.items[0].export_count
}
fn get_auth_output_len(&mut self) -> u32 {
let auth_output = Fetch::AuthTrace.fetch().expect("Failed to fetch auth output");
auth_output.len() as u32
}
fn machine(&mut self, code: &[u8], program_counter: u64) -> Result<Self::InnerVm, ApiError> {
Ok(JamInnerVm(machine(code, program_counter)?))
}
}
pub struct JamInnerVm(pub u64);
impl InnerVm for JamInnerVm {
fn void(&mut self, page: u64, num_pages: u64) -> Result<(), ApiError> {
void(self.0, page, num_pages)
}
fn zero(&mut self, page: u64, num_pages: u64) -> Result<(), ApiError> {
zero(self.0, page, num_pages)
}
fn poke(&mut self, outer_src: &[u8], inner_dst: u64) -> Result<(), ApiError> {
poke(self.0, outer_src, inner_dst)
}
fn peek_into(&mut self, outer_dst: &mut [u8], inner_src: u64) -> Result<(), ApiError> {
peek_into(self.0, outer_dst, inner_src)
}
fn expunge(self) -> Result<u64, ApiError> {
expunge(self.0)
}
fn invoke(
&mut self,
gas: SignedGas,
regs: [u64; 13],
) -> Result<(InvokeOutcome, SignedGas, [u64; 13]), ApiError> {
invoke(self.0, gas, regs)
}
}