#![warn(missing_docs)]
#![cfg_attr(not(feature = "std"), no_std)]
#![allow(clippy::len_without_is_empty)]
#[cfg(not(feature = "std"))]
#[macro_use]
extern crate alloc;
#[cfg(feature = "std")]
extern crate std as alloc;
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
use core::fmt;
#[cfg(feature = "std")]
use std::error;
#[derive(Debug)]
pub enum Error {
Validation(String),
Instantiation(String),
Function(String),
Table(String),
Memory(String),
Global(String),
Value(String),
Trap(Trap),
Host(Box<dyn HostError>),
}
impl Error {
pub fn host<T>(host_error: T) -> Self
where
T: HostError + Sized,
{
Self::Host(Box::new(host_error))
}
pub fn as_host_error(&self) -> Option<&dyn HostError> {
match self {
Self::Host(host_error) => Some(&**host_error),
Self::Trap(Trap::Host(host_error)) => Some(&**host_error),
_ => None,
}
}
pub fn into_host_error(self) -> Option<Box<dyn HostError>> {
match self {
Error::Host(host_error) => Some(host_error),
Self::Trap(Trap::Host(host_error)) => Some(host_error),
_ => None,
}
}
pub fn try_into_host_error(self) -> Result<Box<dyn HostError>, Self> {
match self {
Error::Host(host_error) => Ok(host_error),
Self::Trap(Trap::Host(host_error)) => Ok(host_error),
other => Err(other),
}
}
}
impl From<Error> for String {
fn from(error: Error) -> Self {
match error {
Error::Validation(message) => message,
Error::Instantiation(message) => message,
Error::Function(message) => message,
Error::Table(message) => message,
Error::Memory(message) => message,
Error::Global(message) => message,
Error::Value(message) => message,
Error::Trap(trap) => format!("trap: {trap:?}"),
Error::Host(error) => format!("user: {error}"),
}
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Validation(ref s) => write!(f, "Validation: {}", s),
Error::Instantiation(ref s) => write!(f, "Instantiation: {}", s),
Error::Function(ref s) => write!(f, "Function: {}", s),
Error::Table(ref s) => write!(f, "Table: {}", s),
Error::Memory(ref s) => write!(f, "Memory: {}", s),
Error::Global(ref s) => write!(f, "Global: {}", s),
Error::Value(ref s) => write!(f, "Value: {}", s),
Error::Trap(ref s) => write!(f, "Trap: {:?}", s),
Error::Host(ref e) => write!(f, "User: {}", e),
}
}
}
#[cfg(feature = "std")]
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Validation(ref s) => s,
Error::Instantiation(ref s) => s,
Error::Function(ref s) => s,
Error::Table(ref s) => s,
Error::Memory(ref s) => s,
Error::Global(ref s) => s,
Error::Value(ref s) => s,
Error::Trap(_) => "Trap",
Error::Host(_) => "Host error",
}
}
}
impl From<Trap> for Error {
fn from(e: Trap) -> Error {
Error::Trap(e)
}
}
impl From<validation::Error> for Error {
fn from(e: validation::Error) -> Error {
Error::Validation(e.to_string())
}
}
mod func;
mod global;
mod host;
mod imports;
mod isa;
mod memory;
mod module;
mod prepare;
mod pwasm;
mod runner;
mod table;
mod types;
pub use self::{
func::{FuncInstance, FuncInvocation, FuncRef, ResumableError},
global::{GlobalInstance, GlobalRef},
host::{Externals, NopExternals, RuntimeArgs},
imports::{ImportResolver, ImportsBuilder, ModuleImportResolver},
memory::{MemoryInstance, MemoryRef, LINEAR_MEMORY_PAGE_SIZE},
module::{ExternVal, ModuleInstance, ModuleRef, NotStartedModuleRef},
runner::{StackRecycler, DEFAULT_CALL_STACK_LIMIT, DEFAULT_VALUE_STACK_LIMIT},
table::{TableInstance, TableRef},
types::{GlobalDescriptor, MemoryDescriptor, Signature, TableDescriptor},
};
#[doc(inline)]
pub use casper_wasmi_core::Value as RuntimeValue;
pub use casper_wasmi_core::{
memory_units,
FromValue,
HostError,
LittleEndianConvert,
Trap,
TrapCode,
ValueType,
};
pub(crate) mod value {
pub use casper_wasmi_core::{
ArithmeticOps,
ExtendInto,
Float,
FromValue,
Integer,
LittleEndianConvert,
TransmuteInto,
TryTruncateInto,
WrapInto,
};
}
pub mod nan_preserving_float {
pub use casper_wasmi_core::{F32, F64};
}
pub struct Module {
code_map: Vec<isa::Instructions>,
module: casper_wasm::elements::Module,
}
impl Module {
#[deprecated(note = "Please use `Module::from_casper_wasm_module` instead")]
#[inline]
pub fn from_parity_wasm_module(module: casper_wasm::elements::Module) -> Result<Module, Error> {
Self::from_casper_wasm_module(module)
}
pub fn from_casper_wasm_module(module: casper_wasm::elements::Module) -> Result<Module, Error> {
let prepare::CompiledModule { code_map, module } = prepare::compile_module(module)?;
Ok(Module { code_map, module })
}
pub fn deny_floating_point(&self) -> Result<(), Error> {
prepare::deny_floating_point(&self.module).map_err(Into::into)
}
pub fn from_buffer<B: AsRef<[u8]>>(buffer: B) -> Result<Module, Error> {
let module = casper_wasm::elements::deserialize_buffer(buffer.as_ref())
.map_err(|e: casper_wasm::elements::Error| Error::Validation(e.to_string()))?;
Module::from_casper_wasm_module(module)
}
pub(crate) fn module(&self) -> &casper_wasm::elements::Module {
&self.module
}
pub(crate) fn code(&self) -> &Vec<isa::Instructions> {
&self.code_map
}
}