-
Notifications
You must be signed in to change notification settings - Fork 21
/
Copy patherror.rs
280 lines (236 loc) · 8.65 KB
/
error.rs
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use core::{fmt::Display, ops::ControlFlow};
use tinywasm_types::FuncType;
#[cfg(feature = "parser")]
pub use tinywasm_parser::ParseError;
#[cfg(feature = "async")]
use crate::coro::UnexpectedSuspendError;
use crate::interpreter;
/// Errors that can occur for `TinyWasm` operations
#[derive(Debug)]
pub enum Error {
/// A WebAssembly trap occurred
Trap(Trap),
/// A linking error occurred
Linker(LinkingError),
/// A WebAssembly feature is not supported
UnsupportedFeature(String),
/// An unknown error occurred
Other(String),
/// A host function returned an invalid value
InvalidHostFnReturn {
/// The expected type
expected: FuncType,
/// The actual value
actual: Vec<tinywasm_types::WasmValue>,
},
/// An invalid label type was encountered
InvalidLabelType,
/// The store is not the one that the module instance was instantiated in
InvalidStore,
/// ResumeArgument of wrong type was provided
InvalidResumeArgument,
/// Tried to resume on runtime when it's not suspended
InvalidResume,
/// Function unexpectedly yielded instead of returning
/// (for backwards compatibility with old api)
#[cfg(feature = "async")]
UnexpectedSuspend(UnexpectedSuspendError),
#[cfg(feature = "std")]
/// An I/O error occurred
Io(crate::std::io::Error),
#[cfg(feature = "parser")]
/// A parsing error occurred
ParseError(ParseError),
}
#[derive(Debug)]
/// Errors that can occur when linking a WebAssembly module
pub enum LinkingError {
/// An unknown import was encountered
UnknownImport {
/// The module name
module: String,
/// The import name
name: String,
},
/// A mismatched import type was encountered
IncompatibleImportType {
/// The module name
module: String,
/// The import name
name: String,
},
}
impl LinkingError {
pub(crate) fn incompatible_import_type(import: &tinywasm_types::Import) -> Self {
Self::IncompatibleImportType { module: import.module.to_string(), name: import.name.to_string() }
}
pub(crate) fn unknown_import(import: &tinywasm_types::Import) -> Self {
Self::UnknownImport { module: import.module.to_string(), name: import.name.to_string() }
}
}
#[derive(Debug)]
/// A WebAssembly trap
///
/// See <https://webassembly.github.io/spec/core/intro/overview.html#trap>
pub enum Trap {
/// An unreachable instruction was executed
Unreachable,
/// An out-of-bounds memory access occurred
MemoryOutOfBounds {
/// The offset of the access
offset: usize,
/// The size of the access
len: usize,
/// The maximum size of the memory
max: usize,
},
/// An out-of-bounds table access occurred
TableOutOfBounds {
/// The offset of the access
offset: usize,
/// The size of the access
len: usize,
/// The maximum size of the memory
max: usize,
},
/// A division by zero occurred
DivisionByZero,
/// Invalid Integer Conversion
InvalidConversionToInt,
/// Integer Overflow
IntegerOverflow,
/// Call stack overflow
CallStackOverflow,
/// An undefined element was encountered
UndefinedElement {
/// The element index
index: usize,
},
/// An uninitialized element was encountered
UninitializedElement {
/// The element index
index: usize,
},
/// Indirect call type mismatch
IndirectCallTypeMismatch {
/// The expected type
expected: FuncType,
/// The actual type
actual: FuncType,
},
}
impl Trap {
/// Get the message of the trap
pub fn message(&self) -> &'static str {
match self {
Self::Unreachable => "unreachable",
Self::MemoryOutOfBounds { .. } => "out of bounds memory access",
Self::TableOutOfBounds { .. } => "out of bounds table access",
Self::DivisionByZero => "integer divide by zero",
Self::InvalidConversionToInt => "invalid conversion to integer",
Self::IntegerOverflow => "integer overflow",
Self::CallStackOverflow => "call stack exhausted",
Self::UndefinedElement { .. } => "undefined element",
Self::UninitializedElement { .. } => "uninitialized element",
Self::IndirectCallTypeMismatch { .. } => "indirect call type mismatch",
}
}
}
impl LinkingError {
/// Get the message of the linking error
pub fn message(&self) -> &'static str {
match self {
Self::UnknownImport { .. } => "unknown import",
Self::IncompatibleImportType { .. } => "incompatible import type",
}
}
}
impl From<LinkingError> for Error {
fn from(value: LinkingError) -> Self {
Self::Linker(value)
}
}
impl From<Trap> for Error {
fn from(value: Trap) -> Self {
Self::Trap(value)
}
}
impl Display for Error {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
#[cfg(feature = "parser")]
Self::ParseError(err) => write!(f, "error parsing module: {err:?}"),
#[cfg(feature = "std")]
Self::Io(err) => write!(f, "I/O error: {err}"),
#[cfg(feature = "async")]
Self::UnexpectedSuspend(_) => write!(f, "funtion yielded instead of returning"),
Self::Trap(trap) => write!(f, "trap: {trap}"),
Self::Linker(err) => write!(f, "linking error: {err}"),
Self::InvalidLabelType => write!(f, "invalid label type"),
Self::Other(message) => write!(f, "unknown error: {message}"),
Self::UnsupportedFeature(feature) => write!(f, "unsupported feature: {feature}"),
Self::InvalidHostFnReturn { expected, actual } => {
write!(f, "invalid host function return: expected={expected:?}, actual={actual:?}")
}
Self::InvalidStore => write!(f, "invalid store"),
Self::InvalidResumeArgument => write!(f, "invalid resume argument supplied to suspended function"),
Self::InvalidResume => write!(f, "attempt to resume coroutine that has already finished"),
}
}
}
impl Display for LinkingError {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::UnknownImport { module, name } => write!(f, "unknown import: {}.{}", module, name),
Self::IncompatibleImportType { module, name } => {
write!(f, "incompatible import type: {}.{}", module, name)
}
}
}
}
impl Display for Trap {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
Self::Unreachable => write!(f, "unreachable"),
Self::MemoryOutOfBounds { offset, len, max } => {
write!(f, "out of bounds memory access: offset={offset}, len={len}, max={max}")
}
Self::TableOutOfBounds { offset, len, max } => {
write!(f, "out of bounds table access: offset={offset}, len={len}, max={max}")
}
Self::DivisionByZero => write!(f, "integer divide by zero"),
Self::InvalidConversionToInt => write!(f, "invalid conversion to integer"),
Self::IntegerOverflow => write!(f, "integer overflow"),
Self::CallStackOverflow => write!(f, "call stack exhausted"),
Self::UndefinedElement { index } => write!(f, "undefined element: index={index}"),
Self::UninitializedElement { index } => {
write!(f, "uninitialized element: index={index}")
}
Self::IndirectCallTypeMismatch { expected, actual } => {
write!(f, "indirect call type mismatch: expected={expected:?}, actual={actual:?}")
}
}
}
}
impl core::error::Error for Error {}
#[cfg(feature = "parser")]
impl From<tinywasm_parser::ParseError> for Error {
fn from(value: tinywasm_parser::ParseError) -> Self {
Self::ParseError(value)
}
}
/// A wrapper around [`core::result::Result`] for tinywasm operations
pub type Result<T, E = Error> = crate::std::result::Result<T, E>;
pub(crate) trait Controlify<T> {
fn to_cf(self) -> ControlFlow<interpreter::executor::ReasonToBreak, T>;
}
impl<T> Controlify<T> for Result<T, Error> {
fn to_cf(self) -> ControlFlow<interpreter::executor::ReasonToBreak, T> {
match self {
Ok(value) => ControlFlow::Continue(value),
Err(err) => ControlFlow::Break(interpreter::executor::ReasonToBreak::Errored(err)),
}
}
}