wasmer_interface_types/
errors.rs

1//! The error module contains all the data structures that represent
2//! an error.
3
4use crate::{ast::TypeKind, interpreter::Instruction, types::InterfaceType};
5use std::{
6    error::Error,
7    fmt::{self, Display, Formatter},
8    num::TryFromIntError,
9    result::Result,
10    string::{self, ToString},
11};
12
13/// A type alias for instruction's results.
14pub type InstructionResult<T> = Result<T, InstructionError>;
15
16/// A type alias for the interpreter result.
17pub type InterpreterResult<T> = Result<T, InstructionError>;
18
19/// Structure to represent errors when casting from an `InterfaceType`
20/// to a native value.
21#[derive(Debug)]
22pub struct WasmValueNativeCastError {
23    /// The initial type.
24    pub from: InterfaceType,
25
26    /// The targeted type.
27    ///
28    /// `InterfaceType` is used to represent the native type by
29    /// associativity.
30    pub to: InterfaceType,
31}
32
33impl Error for WasmValueNativeCastError {}
34
35impl Display for WasmValueNativeCastError {
36    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
37        write!(formatter, "{:?}", self)
38    }
39}
40
41/// Structure to represent the errors for instructions.
42#[derive(Debug)]
43pub struct InstructionError {
44    /// The instruction that raises the error.
45    pub instruction: Instruction,
46
47    /// The error kind.
48    pub error_kind: InstructionErrorKind,
49}
50
51impl InstructionError {
52    pub(crate) fn new(instruction: Instruction, error_kind: InstructionErrorKind) -> Self {
53        Self {
54            instruction,
55            error_kind,
56        }
57    }
58}
59
60impl Error for InstructionError {}
61
62impl Display for InstructionError {
63    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
64        write!(
65            formatter,
66            "`{}` {}",
67            (&self.instruction).to_string(),
68            self.error_kind
69        )
70    }
71}
72
73/// The kind of instruction errors.
74#[derive(Debug)]
75pub enum InstructionErrorKind {
76    /// The instruction needs to read an invocation input at index `index`, but it's missing.
77    InvocationInputIsMissing {
78        /// The invocation input index.
79        index: u32,
80    },
81
82    /// Failed to cast from a WIT value to a native value.
83    ToNative(WasmValueNativeCastError),
84
85    /// Failed to cast from `from` to `to`.
86    LoweringLifting {
87        /// The initial type.
88        from: InterfaceType,
89
90        /// The targeted type.
91        to: InterfaceType,
92    },
93
94    /// Read a value from the stack, but it doesn't have the expected
95    /// type.
96    InvalidValueOnTheStack {
97        /// The expected type.
98        expected_type: InterfaceType,
99
100        /// The received type.
101        received_type: InterfaceType,
102    },
103
104    /// Need to read some values from the stack, but it doesn't
105    /// contain enough data.
106    StackIsTooSmall {
107        /// The number of values that were needed.
108        needed: usize,
109    },
110
111    /// The local or import function doesn't exist.
112    LocalOrImportIsMissing {
113        /// The local or import function index.
114        function_index: u32,
115    },
116
117    /// Values given to a local or import function doesn't match the
118    /// function signature.
119    LocalOrImportSignatureMismatch {
120        /// The local or import function index.
121        function_index: u32,
122
123        /// The expected signature.
124        expected: (Vec<InterfaceType>, Vec<InterfaceType>),
125
126        /// The received signature.
127        received: (Vec<InterfaceType>, Vec<InterfaceType>),
128    },
129
130    /// Failed to call a local or import function.
131    LocalOrImportCall {
132        /// The local or import function index that has been called.
133        function_index: u32,
134    },
135
136    /// The memory doesn't exist.
137    MemoryIsMissing {
138        /// The memory indeX.
139        memory_index: u32,
140    },
141
142    /// Tried to read out of bounds of the memory.
143    MemoryOutOfBoundsAccess {
144        /// The access index.
145        index: usize,
146
147        /// The memory length.
148        length: usize,
149    },
150
151    /// The string contains invalid UTF-8 encoding.
152    String(string::FromUtf8Error),
153
154    /// Out of range integral type conversion attempted.
155    NegativeValue {
156        /// The variable name that triggered the error.
157        subject: &'static str,
158    },
159
160    /// The type doesn't exist.
161    TypeIsMissing {
162        /// The type index.
163        type_index: u32,
164    },
165
166    /// Read a type that has an unexpected type.
167    InvalidTypeKind {
168        /// The expected kind.
169        expected_kind: TypeKind,
170
171        /// The received kind.
172        received_kind: TypeKind,
173    },
174}
175
176impl Error for InstructionErrorKind {}
177
178impl Display for InstructionErrorKind {
179    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
180        match self {
181            Self::InvocationInputIsMissing { index } => write!(
182                formatter,
183                "cannot access invocation inputs #{} because it doesn't exist",
184                index
185            ),
186
187            Self::ToNative(WasmValueNativeCastError { from, .. }) => write!(
188                formatter,
189                "failed to cast the WIT value `{:?}` to its native type",
190                from,
191            ),
192
193            Self::LoweringLifting { from, to } => {
194                write!(formatter, "failed to cast `{:?}` to `{:?}`", from, to)
195            }
196
197            Self::InvalidValueOnTheStack {
198                expected_type,
199                received_type,
200            } => write!(
201                formatter,
202                "read a value of type `{:?}` from the stack, but the type `{:?}` was expected",
203                received_type, expected_type,
204            ),
205
206            Self::StackIsTooSmall { needed } => write!(
207                formatter,
208                "needed to read `{}` value(s) from the stack, but it doesn't contain enough data",
209                needed
210            ),
211
212            Self::LocalOrImportIsMissing { function_index } => write!(
213                formatter,
214                "the local or import function `{}` doesn't exist",
215                function_index
216            ),
217
218            Self::LocalOrImportSignatureMismatch { function_index, expected, received } => write!(
219                formatter,
220                "the local or import function `{}` has the signature `{:?} -> {:?}` but it received values of kind `{:?} -> {:?}`",
221                function_index, expected.0, expected.1, received.0, received.1,
222            ),
223
224            Self::LocalOrImportCall  { function_index } => write!(
225                formatter,
226                "failed while calling the local or import function `{}`",
227                function_index
228            ),
229
230            Self::MemoryIsMissing { memory_index } => write!(
231                formatter,
232                "memory `{}` does not exist",
233                memory_index,
234            ),
235
236            Self::MemoryOutOfBoundsAccess { index, length } => write!(
237                formatter,
238                "read out of the memory bounds (index {} > memory length {})",
239                index, length,
240            ),
241
242            Self::String(error) => write!(formatter, "{}", error),
243
244            Self::NegativeValue { subject } => write!(
245                formatter,
246                "attempted to convert `{}` but it appears to be a negative value",
247                subject
248            ),
249
250            Self::TypeIsMissing { type_index } => write!(
251                formatter,
252                "the type `{}` doesn't exist",
253                type_index
254            ),
255
256            Self::InvalidTypeKind { expected_kind, received_kind } => write!(
257                formatter,
258                "read a type of kind `{:?}`, but the kind `{:?}` was expected",
259                received_kind, expected_kind
260            ),
261        }
262    }
263}
264
265impl From<(TryFromIntError, &'static str)> for InstructionErrorKind {
266    fn from((_, subject): (TryFromIntError, &'static str)) -> Self {
267        InstructionErrorKind::NegativeValue { subject }
268    }
269}