1use 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
13pub type InstructionResult<T> = Result<T, InstructionError>;
15
16pub type InterpreterResult<T> = Result<T, InstructionError>;
18
19#[derive(Debug)]
22pub struct WasmValueNativeCastError {
23 pub from: InterfaceType,
25
26 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#[derive(Debug)]
43pub struct InstructionError {
44 pub instruction: Instruction,
46
47 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#[derive(Debug)]
75pub enum InstructionErrorKind {
76 InvocationInputIsMissing {
78 index: u32,
80 },
81
82 ToNative(WasmValueNativeCastError),
84
85 LoweringLifting {
87 from: InterfaceType,
89
90 to: InterfaceType,
92 },
93
94 InvalidValueOnTheStack {
97 expected_type: InterfaceType,
99
100 received_type: InterfaceType,
102 },
103
104 StackIsTooSmall {
107 needed: usize,
109 },
110
111 LocalOrImportIsMissing {
113 function_index: u32,
115 },
116
117 LocalOrImportSignatureMismatch {
120 function_index: u32,
122
123 expected: (Vec<InterfaceType>, Vec<InterfaceType>),
125
126 received: (Vec<InterfaceType>, Vec<InterfaceType>),
128 },
129
130 LocalOrImportCall {
132 function_index: u32,
134 },
135
136 MemoryIsMissing {
138 memory_index: u32,
140 },
141
142 MemoryOutOfBoundsAccess {
144 index: usize,
146
147 length: usize,
149 },
150
151 String(string::FromUtf8Error),
153
154 NegativeValue {
156 subject: &'static str,
158 },
159
160 TypeIsMissing {
162 type_index: u32,
164 },
165
166 InvalidTypeKind {
168 expected_kind: TypeKind,
170
171 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}