// Copyright 2018 Parity Technologies (UK) Ltd.
// This file is part of Substrate.
// Substrate is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Substrate is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Substrate. If not, see .
extern crate wasmi;
use rstd::collections::btree_map::BTreeMap;
use rstd::fmt;
use self::wasmi::{
Externals, FuncInstance, FuncRef, GlobalDescriptor, GlobalRef, ImportResolver,
MemoryDescriptor, MemoryInstance, MemoryRef, Module, ModuleInstance, ModuleRef,
RuntimeArgs, RuntimeValue, Signature, TableDescriptor, TableRef, Trap, TrapKind
};
use self::wasmi::memory_units::Pages;
use super::{Error, TypedValue, ReturnValue, HostFuncType, HostError};
#[derive(Clone)]
pub struct Memory {
memref: MemoryRef,
}
impl Memory {
pub fn new(initial: u32, maximum: Option) -> Result {
Ok(Memory {
memref: MemoryInstance::alloc(
Pages(initial as usize),
maximum.map(|m| Pages(m as usize)),
).map_err(|_| Error::Module)?,
})
}
pub fn get(&self, ptr: u32, buf: &mut [u8]) -> Result<(), Error> {
self.memref.get_into(ptr, buf).map_err(|_| Error::OutOfBounds)?;
Ok(())
}
pub fn set(&self, ptr: u32, value: &[u8]) -> Result<(), Error> {
self.memref.set(ptr, value).map_err(|_| Error::OutOfBounds)?;
Ok(())
}
}
struct HostFuncIndex(usize);
struct DefinedHostFunctions {
funcs: Vec>,
}
impl Clone for DefinedHostFunctions {
fn clone(&self) -> DefinedHostFunctions {
DefinedHostFunctions {
funcs: self.funcs.clone(),
}
}
}
impl DefinedHostFunctions {
fn new() -> DefinedHostFunctions {
DefinedHostFunctions {
funcs: Vec::new(),
}
}
fn define(&mut self, f: HostFuncType) -> HostFuncIndex {
let idx = self.funcs.len();
self.funcs.push(f);
HostFuncIndex(idx)
}
}
#[derive(Debug)]
struct DummyHostError;
impl fmt::Display for DummyHostError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "DummyHostError")
}
}
impl self::wasmi::HostError for DummyHostError {
}
fn from_runtime_value(v: RuntimeValue) -> TypedValue {
match v {
RuntimeValue::I32(v) => TypedValue::I32(v),
RuntimeValue::I64(v) => TypedValue::I64(v),
RuntimeValue::F32(v) => TypedValue::F32(v.to_bits() as i32),
RuntimeValue::F64(v) => TypedValue::F64(v.to_bits() as i64),
}
}
fn to_runtime_value(v: TypedValue) -> RuntimeValue {
use self::wasmi::nan_preserving_float::{F32, F64};
match v {
TypedValue::I32(v) => RuntimeValue::I32(v as i32),
TypedValue::I64(v) => RuntimeValue::I64(v as i64),
TypedValue::F32(v_bits) => RuntimeValue::F32(F32::from_bits(v_bits as u32)),
TypedValue::F64(v_bits) => RuntimeValue::F64(F64::from_bits(v_bits as u64)),
}
}
struct GuestExternals<'a, T: 'a> {
state: &'a mut T,
defined_host_functions: &'a DefinedHostFunctions,
}
impl<'a, T> Externals for GuestExternals<'a, T> {
fn invoke_index(
&mut self,
index: usize,
args: RuntimeArgs,
) -> Result