use crate::{ExternType, Pages};
use std::io;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum SerializeError {
#[error(transparent)]
Io(#[from] io::Error),
#[error("{0}")]
Generic(String),
}
#[derive(Error, Debug)]
pub enum DeserializeError {
#[error(transparent)]
Io(#[from] io::Error),
#[error("{0}")]
Generic(String),
#[error("incompatible binary: {0}")]
Incompatible(String),
#[error("corrupted binary: {0}")]
CorruptedBinary(String),
#[error(transparent)]
Compiler(#[from] CompileError),
#[error("invalid input bytes: expected {expected} bytes, got {got}")]
InvalidByteLength {
expected: usize,
got: usize,
},
}
#[derive(Error, Debug, Clone, PartialEq, Eq, Hash)]
pub enum MemoryError {
#[error("Error when allocating memory: {0}")]
Region(String),
#[error("The memory could not grow: current size {} pages, requested increase: {} pages", current.0, attempted_delta.0)]
CouldNotGrow {
current: Pages,
attempted_delta: Pages,
},
#[error("The memory is invalid because {}", reason)]
InvalidMemory {
reason: String,
},
#[error("The minimum requested ({} pages) memory is greater than the maximum allowed memory ({} pages)", min_requested.0, max_allowed.0)]
MinimumMemoryTooLarge {
min_requested: Pages,
max_allowed: Pages,
},
#[error("The maximum requested memory ({} pages) is greater than the maximum allowed memory ({} pages)", max_requested.0, max_allowed.0)]
MaximumMemoryTooLarge {
max_requested: Pages,
max_allowed: Pages,
},
#[error("A user-defined error occurred: {0}")]
Generic(String),
}
#[derive(Error, Debug)]
pub enum ImportError {
#[error("incompatible import type. Expected {0:?} but received {1:?}")]
IncompatibleType(ExternType, ExternType),
#[error("unknown import. Expected {0:?}")]
UnknownImport(ExternType),
#[error("memory error. {0}")]
MemoryError(String),
}
#[derive(Error, Debug)]
pub enum PreInstantiationError {
#[error("module compiled with CPU feature that is missing from host")]
CpuFeature(String),
}
use crate::lib::std::string::String;
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(Error))]
pub enum CompileError {
#[cfg_attr(feature = "std", error("WebAssembly translation error: {0}"))]
Wasm(WasmError),
#[cfg_attr(feature = "std", error("Compilation error: {0}"))]
Codegen(String),
#[cfg_attr(feature = "std", error("Validation error: {0}"))]
Validate(String),
#[cfg_attr(feature = "std", error("Feature {0} is not yet supported"))]
UnsupportedFeature(String),
#[cfg_attr(feature = "std", error("The target {0} is not yet supported (see https://docs.wasmer.io/ecosystem/wasmer/wasmer-features)"))]
UnsupportedTarget(String),
#[cfg_attr(feature = "std", error("Insufficient resources: {0}"))]
Resource(String),
}
impl From<WasmError> for CompileError {
fn from(original: WasmError) -> Self {
Self::Wasm(original)
}
}
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(Error))]
#[cfg_attr(feature = "std", error("Error in middleware {name}: {message}"))]
pub struct MiddlewareError {
pub name: String,
pub message: String,
}
impl MiddlewareError {
pub fn new<A: Into<String>, B: Into<String>>(name: A, message: B) -> Self {
Self {
name: name.into(),
message: message.into(),
}
}
}
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(Error))]
pub enum WasmError {
#[cfg_attr(
feature = "std",
error("Invalid input WebAssembly code at offset {offset}: {message}")
)]
InvalidWebAssembly {
message: String,
offset: usize,
},
#[cfg_attr(feature = "std", error("Unsupported feature: {0}"))]
Unsupported(String),
#[cfg_attr(feature = "std", error("Implementation limit exceeded"))]
ImplLimitExceeded,
#[cfg_attr(feature = "std", error("{0}"))]
Middleware(MiddlewareError),
#[cfg_attr(feature = "std", error("{0}"))]
Generic(String),
}
impl From<MiddlewareError> for WasmError {
fn from(original: MiddlewareError) -> Self {
Self::Middleware(original)
}
}
#[derive(Debug)]
#[cfg_attr(feature = "std", derive(Error))]
pub enum ParseCpuFeatureError {
#[cfg_attr(feature = "std", error("CpuFeature {0} not recognized"))]
Missing(String),
}
pub type WasmResult<T> = Result<T, WasmError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn middleware_error_can_be_created() {
let msg = String::from("Something went wrong");
let error = MiddlewareError::new("manipulator3000", msg);
assert_eq!(error.name, "manipulator3000");
assert_eq!(error.message, "Something went wrong");
}
#[test]
fn middleware_error_be_converted_to_wasm_error() {
let error = WasmError::from(MiddlewareError::new("manipulator3000", "foo"));
match error {
WasmError::Middleware(MiddlewareError { name, message }) => {
assert_eq!(name, "manipulator3000");
assert_eq!(message, "foo");
}
err => panic!("Unexpected error: {:?}", err),
}
}
}