1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
use alloc::string::{String, ToString};
use core::fmt;
use core::num::TryFromIntError;
/// A WebAssembly translation error.
///
/// When a WebAssembly function can't be translated, one of these error codes will be returned
/// to describe the failure.
#[derive(Debug)]
pub enum WasmError {
/// The input WebAssembly code is invalid.
///
/// This error code is used by a WebAssembly translator when it encounters invalid WebAssembly
/// code. This should never happen for validated WebAssembly code.
InvalidWebAssembly {
/// A string describing the validation error.
message: String,
/// The bytecode offset where the error occurred.
offset: usize,
},
/// A feature used by the WebAssembly code is not supported by the embedding environment.
///
/// Embedding environments may have their own limitations and feature restrictions.
Unsupported(String),
/// An implementation limit was exceeded.
///
/// Cranelift can compile very large and complicated functions, but the [implementation has
/// limits][limits] that cause compilation to fail when they are exceeded.
///
/// [limits]: https://github.com/bytecodealliance/wasmtime/blob/main/cranelift/docs/ir.md#implementation-limits
ImplLimitExceeded,
/// Any user-defined error.
User(String),
}
/// Return an `Err(WasmError::Unsupported(msg))` where `msg` the string built by calling `format!`
/// on the arguments to this macro.
#[macro_export]
macro_rules! wasm_unsupported {
($($arg:tt)*) => { $crate::WasmError::Unsupported($crate::__format!($($arg)*)) }
}
#[doc(hidden)]
pub use alloc::format as __format;
impl From<wasmparser::BinaryReaderError> for WasmError {
/// Convert from a `BinaryReaderError` to a `WasmError`.
fn from(e: wasmparser::BinaryReaderError) -> Self {
Self::InvalidWebAssembly {
message: e.message().into(),
offset: e.offset(),
}
}
}
impl From<TryFromIntError> for WasmError {
/// Convert from a `TryFromIntError` to a `WasmError`.
fn from(e: TryFromIntError) -> Self {
Self::InvalidWebAssembly {
message: e.to_string(),
offset: 0,
}
}
}
/// A convenient alias for a `Result` that uses `WasmError` as the error type.
pub type WasmResult<T> = Result<T, WasmError>;
impl fmt::Display for WasmError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
WasmError::InvalidWebAssembly { message, offset } => {
write!(
f,
"Invalid input WebAssembly code at offset {offset}: {message}"
)
}
WasmError::Unsupported(s) => {
write!(f, "Unsupported feature: {s}")
}
WasmError::ImplLimitExceeded => {
write!(f, "Implementation limit exceeded")
}
WasmError::User(s) => {
write!(f, "User error: {s}")
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for WasmError {}