mirror of
https://github.com/fluencelabs/interface-types
synced 2025-04-25 15:52:13 +00:00
220 lines
6.2 KiB
Rust
220 lines
6.2 KiB
Rust
|
//! The error module contains all the data structures that represent
|
||
|
//! an error.
|
||
|
|
||
|
use crate::{ast::InterfaceType, interpreter::Instruction};
|
||
|
use std::{
|
||
|
fmt::{self, Display, Formatter},
|
||
|
result::Result,
|
||
|
string::{self, ToString},
|
||
|
};
|
||
|
|
||
|
/// A type alias for instruction's results.
|
||
|
pub type InstructionResult<T> = Result<T, InstructionError>;
|
||
|
|
||
|
/// A type alias for the interpreter result.
|
||
|
pub type InterpreterResult<T> = Result<T, InstructionError>;
|
||
|
|
||
|
/// Structure to represent errors when casting from an `InterfaceType`
|
||
|
/// to a native value.
|
||
|
#[derive(Debug)]
|
||
|
pub struct WasmValueNativeCastError {
|
||
|
/// The initial type.
|
||
|
pub from: InterfaceType,
|
||
|
|
||
|
/// The targeted type.
|
||
|
///
|
||
|
/// `InterfaceType` is used to represent the native type by
|
||
|
/// associativity.
|
||
|
pub to: InterfaceType,
|
||
|
}
|
||
|
|
||
|
/// Structure to represent the errors for instructions.
|
||
|
#[derive(Debug)]
|
||
|
pub struct InstructionError {
|
||
|
/// The instruction that raises the error.
|
||
|
pub instruction: Instruction,
|
||
|
|
||
|
/// The error kind.
|
||
|
pub error_kind: InstructionErrorKind,
|
||
|
}
|
||
|
|
||
|
impl InstructionError {
|
||
|
pub(crate) fn new(instruction: Instruction, error_kind: InstructionErrorKind) -> Self {
|
||
|
Self {
|
||
|
instruction,
|
||
|
error_kind,
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
impl Display for InstructionError {
|
||
|
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
|
||
|
write!(
|
||
|
formatter,
|
||
|
"`{}` {}",
|
||
|
(&self.instruction).to_string(),
|
||
|
self.error_kind
|
||
|
)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/// The kind of instruction errors.
|
||
|
#[derive(Debug)]
|
||
|
pub enum InstructionErrorKind {
|
||
|
/// The instruction needs to read an invocation input at index `index`, but it's missing.
|
||
|
InvocationInputIsMissing {
|
||
|
/// The invocation input index.
|
||
|
index: u32,
|
||
|
},
|
||
|
|
||
|
/// Failed to cast from a WIT value to a native value.
|
||
|
ToNative(WasmValueNativeCastError),
|
||
|
|
||
|
/// Failed to cast from `from` to `to`.
|
||
|
LoweringLifting {
|
||
|
/// The initial type.
|
||
|
from: InterfaceType,
|
||
|
|
||
|
/// The targeted type.
|
||
|
to: InterfaceType,
|
||
|
},
|
||
|
|
||
|
/// Read a value from the stack, but it doesn't have the expected
|
||
|
/// type.
|
||
|
InvalidValueOnTheStack {
|
||
|
/// The expected type.
|
||
|
expected_type: InterfaceType,
|
||
|
|
||
|
/// The received type.
|
||
|
received_type: InterfaceType,
|
||
|
},
|
||
|
|
||
|
/// Need to read some values from the stack, but it doesn't
|
||
|
/// contain enough data.
|
||
|
StackIsTooSmall {
|
||
|
/// The number of values that were needed.
|
||
|
needed: usize,
|
||
|
},
|
||
|
|
||
|
/// The local or import function doesn't exist.
|
||
|
LocalOrImportIsMissing {
|
||
|
/// The local or import function index.
|
||
|
function_index: u32,
|
||
|
},
|
||
|
|
||
|
/// Values given to a local or import function doesn't match the
|
||
|
/// function signature.
|
||
|
LocalOrImportSignatureMismatch {
|
||
|
/// The local or import function index.
|
||
|
function_index: u32,
|
||
|
|
||
|
/// The expected signature.
|
||
|
expected: (Vec<InterfaceType>, Vec<InterfaceType>),
|
||
|
|
||
|
/// The received signature.
|
||
|
received: (Vec<InterfaceType>, Vec<InterfaceType>),
|
||
|
},
|
||
|
|
||
|
/// Failed to call a local or import function.
|
||
|
LocalOrImportCall {
|
||
|
/// The local or import function index that has been called.
|
||
|
function_index: u32,
|
||
|
},
|
||
|
|
||
|
/// The memory doesn't exist.
|
||
|
MemoryIsMissing {
|
||
|
/// The memory indeX.
|
||
|
memory_index: u32,
|
||
|
},
|
||
|
|
||
|
/// Tried to read out of bounds of the memory.
|
||
|
MemoryOutOfBoundsAccess {
|
||
|
/// The access index.
|
||
|
index: usize,
|
||
|
|
||
|
/// The memory length.
|
||
|
length: usize,
|
||
|
},
|
||
|
|
||
|
/// The string contains invalid UTF-8 encoding.
|
||
|
String(string::FromUtf8Error),
|
||
|
}
|
||
|
|
||
|
impl Display for InstructionErrorKind {
|
||
|
fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
|
||
|
match self {
|
||
|
Self::InvocationInputIsMissing { index } => write!(
|
||
|
formatter,
|
||
|
"cannot access invocation inputs #{} because it doesn't exist",
|
||
|
index
|
||
|
),
|
||
|
|
||
|
Self::ToNative(WasmValueNativeCastError { from, .. }) => write!(
|
||
|
formatter,
|
||
|
"failed to cast the WIT value `{:?}` to its native type",
|
||
|
from,
|
||
|
),
|
||
|
|
||
|
Self::LoweringLifting { from, to } => {
|
||
|
write!(formatter, "failed to cast `{:?}` to `{:?}`", from, to)
|
||
|
}
|
||
|
|
||
|
Self::InvalidValueOnTheStack {
|
||
|
expected_type,
|
||
|
received_type,
|
||
|
} => write!(
|
||
|
formatter,
|
||
|
"read a value of type `{:?}` from the stack, but the type `{:?}` was expected",
|
||
|
received_type, expected_type,
|
||
|
),
|
||
|
|
||
|
Self::StackIsTooSmall { needed } => write!(
|
||
|
formatter,
|
||
|
"needed to read `{}` value(s) from the stack, but it doesn't contain enough data",
|
||
|
needed
|
||
|
),
|
||
|
|
||
|
Self::LocalOrImportIsMissing { function_index } => write!(
|
||
|
formatter,
|
||
|
"the local or import function `{}` doesn't exist",
|
||
|
function_index
|
||
|
),
|
||
|
|
||
|
Self::LocalOrImportSignatureMismatch { function_index, expected, received } => write!(
|
||
|
formatter,
|
||
|
"the local or import function `{}` has the signature `{:?} -> {:?}` but it received values of kind `{:?} -> {:?}`",
|
||
|
function_index,
|
||
|
expected.0,
|
||
|
expected.1,
|
||
|
received.0,
|
||
|
received.1,
|
||
|
),
|
||
|
|
||
|
Self::LocalOrImportCall { function_index } => write!(
|
||
|
formatter,
|
||
|
"failed while calling the local or import function `{}`",
|
||
|
function_index
|
||
|
),
|
||
|
|
||
|
Self::MemoryIsMissing { memory_index } => write!(
|
||
|
formatter,
|
||
|
"memory `{}` does not exist",
|
||
|
memory_index,
|
||
|
),
|
||
|
|
||
|
Self::MemoryOutOfBoundsAccess { index, length } => write!(
|
||
|
formatter,
|
||
|
"read out of the memory bounds (index {} > memory length {})",
|
||
|
index,
|
||
|
length,
|
||
|
),
|
||
|
|
||
|
Self::String(error) => write!(
|
||
|
formatter,
|
||
|
"{}",
|
||
|
error
|
||
|
),
|
||
|
}
|
||
|
}
|
||
|
}
|