1use crate::backend::ExceptionCode;
4use crate::types::{FuncSig, GlobalDescriptor, MemoryDescriptor, TableDescriptor, Type};
5use core::borrow::Borrow;
6use std::any::Any;
7
8pub type Result<T> = std::result::Result<T, Error>;
10pub type CompileResult<T> = std::result::Result<T, CompileError>;
13pub type LinkResult<T> = std::result::Result<T, Vec<LinkError>>;
16pub type RuntimeResult<T> = std::result::Result<T, RuntimeError>;
19pub type CallResult<T> = std::result::Result<T, CallError>;
22pub type ResolveResult<T> = std::result::Result<T, ResolveError>;
25pub type ParseResult<T> = std::result::Result<T, ParseError>;
28
29#[derive(Debug, Clone)]
35pub enum CompileError {
36 ValidationError {
38 msg: String,
40 },
41 InternalError {
43 msg: String,
45 },
46}
47
48impl PartialEq for CompileError {
49 fn eq(&self, _other: &CompileError) -> bool {
50 false
51 }
52}
53
54impl std::fmt::Display for CompileError {
55 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
56 match self {
57 CompileError::InternalError { msg } => {
58 write!(f, "Internal compiler error: \"{}\"", msg)
59 }
60 CompileError::ValidationError { msg } => write!(f, "Validation error \"{}\"", msg),
61 }
62 }
63}
64
65impl std::error::Error for CompileError {}
66
67#[derive(Debug, Clone)]
72pub enum LinkError {
73 IncorrectImportType {
75 namespace: String,
77 name: String,
79 expected: String,
81 found: String,
83 },
84 IncorrectImportSignature {
86 namespace: String,
88 name: String,
90 expected: FuncSig,
92 found: FuncSig,
94 },
95 ImportNotFound {
97 namespace: String,
99 name: String,
101 },
102 IncorrectMemoryDescriptor {
104 namespace: String,
106 name: String,
108 expected: MemoryDescriptor,
110 found: MemoryDescriptor,
112 },
113 IncorrectTableDescriptor {
115 namespace: String,
117 name: String,
119 expected: TableDescriptor,
121 found: TableDescriptor,
123 },
124 IncorrectGlobalDescriptor {
126 namespace: String,
128 name: String,
130 expected: GlobalDescriptor,
132 found: GlobalDescriptor,
134 },
135 Generic {
137 message: String,
139 },
140}
141
142impl PartialEq for LinkError {
143 fn eq(&self, _other: &LinkError) -> bool {
144 false
145 }
146}
147
148impl std::fmt::Display for LinkError {
149 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
150 match self {
151 LinkError::ImportNotFound {namespace, name} => write!(f, "Import not found, namespace: {}, name: {}", namespace, name),
152 LinkError::IncorrectGlobalDescriptor {namespace, name,expected,found} => {
153 write!(f, "Incorrect global descriptor, namespace: {}, name: {}, expected global descriptor: {:?}, found global descriptor: {:?}", namespace, name, expected, found)
154 },
155 LinkError::IncorrectImportSignature{namespace, name,expected,found} => {
156 write!(f, "Incorrect import signature, namespace: {}, name: {}, expected signature: {}, found signature: {}", namespace, name, expected, found)
157 }
158 LinkError::IncorrectImportType{namespace, name,expected,found} => {
159 write!(f, "Incorrect import type, namespace: {}, name: {}, expected type: {}, found type: {}", namespace, name, expected, found)
160 }
161 LinkError::IncorrectMemoryDescriptor{namespace, name,expected,found} => {
162 write!(f, "Incorrect memory descriptor, namespace: {}, name: {}, expected memory descriptor: {:?}, found memory descriptor: {:?}", namespace, name, expected, found)
163 },
164 LinkError::IncorrectTableDescriptor{namespace, name,expected,found} => {
165 write!(f, "Incorrect table descriptor, namespace: {}, name: {}, expected table descriptor: {:?}, found table descriptor: {:?}", namespace, name, expected, found)
166 },
167 LinkError::Generic { message } => {
168 write!(f, "{}", message)
169 },
170 }
171 }
172}
173
174impl std::error::Error for LinkError {}
175
176#[derive(Debug)]
178pub enum InvokeError {
179 FailedWithNoError,
182 UnknownTrap {
184 address: usize,
186 signal: &'static str,
188 },
189 TrapCode {
191 code: ExceptionCode,
193 srcloc: u32,
195 },
196 UnknownTrapCode {
199 trap_code: String,
201 srcloc: u32,
203 },
204 EarlyTrap(Box<RuntimeError>),
206 Breakpoint(Box<RuntimeError>),
209}
210
211impl From<InvokeError> for RuntimeError {
212 fn from(other: InvokeError) -> RuntimeError {
213 match other {
214 InvokeError::EarlyTrap(re) | InvokeError::Breakpoint(re) => *re,
215 _ => RuntimeError::InvokeError(other),
216 }
217 }
218}
219
220impl std::error::Error for InvokeError {}
221
222impl std::fmt::Display for InvokeError {
223 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
224 match self {
225 InvokeError::FailedWithNoError => write!(f, "Invoke failed with no error"),
226 InvokeError::UnknownTrap { address, signal } => write!(
227 f,
228 "An unknown trap (`{}`) occured at 0x{:X}",
229 signal, address
230 ),
231 InvokeError::TrapCode { code, srcloc } => {
232 write!(f, "A `{}` trap was thrown at code offset {}", code, srcloc)
233 }
234 InvokeError::UnknownTrapCode { trap_code, srcloc } => write!(
235 f,
236 "A trap with an unknown trap code (`{}`) was thrown at code offset {}",
237 trap_code, srcloc
238 ),
239 InvokeError::EarlyTrap(rte) => write!(f, "Early trap: {}", rte),
240 InvokeError::Breakpoint(rte) => write!(f, "Breakpoint hit: {}", rte),
241 }
242 }
243}
244
245#[derive(Debug)]
252pub enum RuntimeError {
253 InvokeError(InvokeError),
255 Metering(Box<dyn Any + Send>),
259 InstanceImage(Box<dyn Any + Send>),
263 User(Box<dyn Any + Send>),
267}
268
269impl PartialEq for RuntimeError {
270 fn eq(&self, _other: &RuntimeError) -> bool {
271 false
272 }
273}
274
275impl std::error::Error for RuntimeError {}
276
277impl std::fmt::Display for RuntimeError {
278 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
279 match self {
280 RuntimeError::InvokeError(ie) => write!(f, "Error when calling invoke: {}", ie),
281 RuntimeError::Metering(_) => write!(f, "unknown metering error type"),
282 RuntimeError::InstanceImage(_) => write!(
283 f,
284 "Execution interrupted by a suspend signal: instance image returned"
285 ),
286 RuntimeError::User(user_error) => {
287 write!(f, "User supplied error: ")?;
288 if let Some(s) = user_error.downcast_ref::<String>() {
289 write!(f, "\"{}\"", s)
290 } else if let Some(s) = user_error.downcast_ref::<&str>() {
291 write!(f, "\"{}\"", s)
292 } else if let Some(n) = user_error.downcast_ref::<i32>() {
293 write!(f, "{}", n)
294 } else {
295 write!(f, "unknown user error type")
296 }
297 }
298 }
299 }
300}
301
302#[derive(Debug, Clone)]
307pub enum ResolveError {
308 Signature {
310 expected: FuncSig,
312 found: Vec<Type>,
314 },
315 ExportNotFound {
317 name: String,
319 },
320 ExportWrongType {
322 name: String,
324 },
325}
326
327impl PartialEq for ResolveError {
328 fn eq(&self, _other: &ResolveError) -> bool {
329 false
330 }
331}
332
333impl std::fmt::Display for ResolveError {
334 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
335 match self {
336 ResolveError::ExportNotFound { name } => write!(f, "Export not found: {}", name),
337 ResolveError::ExportWrongType { name } => write!(f, "Export wrong type: {}", name),
338 ResolveError::Signature { expected, found } => {
339 let found = found
340 .as_slice()
341 .iter()
342 .map(|p| p.to_string())
343 .collect::<Vec<_>>()
344 .join(", ");
345 let expected: &FuncSig = expected.borrow();
346 write!(
347 f,
348 "Parameters of type [{}] did not match signature {}",
349 found, expected
350 )
351 }
352 }
353 }
354}
355
356impl std::error::Error for ResolveError {}
357
358pub enum CallError {
366 Resolve(ResolveError),
368 Runtime(RuntimeError),
370}
371
372impl PartialEq for CallError {
373 fn eq(&self, _other: &CallError) -> bool {
374 false
375 }
376}
377
378impl std::fmt::Display for CallError {
379 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
380 match self {
381 CallError::Resolve(resolve_error) => write!(f, "Call error: {}", resolve_error),
382 CallError::Runtime(runtime_error) => write!(f, "Call error: {}", runtime_error),
383 }
384 }
385}
386
387impl std::fmt::Debug for CallError {
388 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
389 match self {
390 CallError::Resolve(resolve_err) => write!(f, "ResolveError: {:?}", resolve_err),
391 CallError::Runtime(runtime_err) => write!(f, "RuntimeError: {:?}", runtime_err),
392 }
393 }
394}
395
396impl std::error::Error for CallError {}
397
398#[derive(Debug, Clone)]
401pub enum CreationError {
402 UnableToCreateMemory,
404 UnableToCreateTable,
406 InvalidDescriptor(String),
408}
409
410impl PartialEq for CreationError {
411 fn eq(&self, _other: &CreationError) -> bool {
412 false
413 }
414}
415
416impl std::fmt::Display for CreationError {
417 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
418 match self {
419 CreationError::UnableToCreateMemory => write!(f, "Unable to Create Memory"),
420 CreationError::UnableToCreateTable => write!(f, "Unable to Create Table"),
421 CreationError::InvalidDescriptor(msg) => write!(
422 f,
423 "Unable to create because the supplied descriptor is invalid: \"{}\"",
424 msg
425 ),
426 }
427 }
428}
429
430impl std::error::Error for CreationError {}
431
432#[derive(Debug)]
438pub enum Error {
439 CompileError(CompileError),
441 LinkError(Vec<LinkError>),
443 RuntimeError(RuntimeError),
445 ResolveError(ResolveError),
447 CallError(CallError),
449 CreationError(CreationError),
451}
452
453impl PartialEq for Error {
454 fn eq(&self, _other: &Error) -> bool {
455 false
456 }
457}
458
459impl From<CompileError> for Error {
460 fn from(compile_err: CompileError) -> Self {
461 Error::CompileError(compile_err)
462 }
463}
464
465impl From<RuntimeError> for Error {
466 fn from(runtime_err: RuntimeError) -> Self {
467 Error::RuntimeError(runtime_err)
468 }
469}
470
471impl From<ResolveError> for Error {
472 fn from(resolve_err: ResolveError) -> Self {
473 Error::ResolveError(resolve_err)
474 }
475}
476
477impl From<CallError> for Error {
478 fn from(call_err: CallError) -> Self {
479 Error::CallError(call_err)
480 }
481}
482
483impl From<CreationError> for Error {
484 fn from(creation_err: CreationError) -> Self {
485 Error::CreationError(creation_err)
486 }
487}
488
489impl From<Vec<LinkError>> for Error {
490 fn from(link_errs: Vec<LinkError>) -> Self {
491 Error::LinkError(link_errs)
492 }
493}
494
495impl From<RuntimeError> for CallError {
496 fn from(runtime_err: RuntimeError) -> Self {
497 CallError::Runtime(runtime_err)
498 }
499}
500
501impl From<ResolveError> for CallError {
502 fn from(resolve_err: ResolveError) -> Self {
503 CallError::Resolve(resolve_err)
504 }
505}
506
507impl std::fmt::Display for Error {
508 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
509 match self {
510 Error::CompileError(err) => write!(f, "compile error: {}", err),
511 Error::LinkError(errs) => {
512 if errs.len() == 1 {
513 write!(f, "link error: {}", errs[0])
514 } else {
515 write!(f, "{} link errors:", errs.len())?;
516 for (i, err) in errs.iter().enumerate() {
517 write!(f, " ({} of {}) {}", i + 1, errs.len(), err)?;
518 }
519 Ok(())
520 }
521 }
522 Error::RuntimeError(err) => write!(f, "runtime error: {}", err),
523 Error::ResolveError(err) => write!(f, "resolve error: {}", err),
524 Error::CallError(err) => write!(f, "call error: {}", err),
525 Error::CreationError(err) => write!(f, "creation error: {}", err),
526 }
527 }
528}
529
530impl std::error::Error for Error {}
531
532#[derive(Debug)]
534pub enum GrowError {
535 MemoryGrowError,
537 TableGrowError,
539 ExceededMaxPages(PageError),
541 ExceededMaxPagesForMemory(usize, usize),
543 CouldNotProtectMemory(MemoryProtectionError),
545 CouldNotCreateMemory(MemoryCreationError),
547}
548
549impl std::fmt::Display for GrowError {
550 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
551 match self {
552 GrowError::MemoryGrowError => write!(f, "Unable to grow memory"),
553 GrowError::TableGrowError => write!(f, "Unable to grow table"),
554 GrowError::ExceededMaxPages(e) => write!(f, "Grow Error: {}", e),
555 GrowError::ExceededMaxPagesForMemory(left, added) => write!(f, "Failed to add pages because would exceed maximum number of pages for the memory. Left: {}, Added: {}", left, added),
556 GrowError::CouldNotCreateMemory(e) => write!(f, "Grow Error: {}", e),
557 GrowError::CouldNotProtectMemory(e) => write!(f, "Grow Error: {}", e),
558 }
559 }
560}
561
562impl std::error::Error for GrowError {}
563
564#[derive(Debug)]
566pub enum PageError {
567 ExceededMaxPages(usize, usize, usize),
570}
571
572impl std::fmt::Display for PageError {
573 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
574 match self {
575 PageError::ExceededMaxPages(left, right, added) => write!(f, "Failed to add pages because would exceed maximum number of pages. Left: {}, Right: {}, Pages added: {}", left, right, added),
576 }
577 }
578}
579impl std::error::Error for PageError {}
580
581impl Into<GrowError> for PageError {
582 fn into(self) -> GrowError {
583 GrowError::ExceededMaxPages(self)
584 }
585}
586
587#[derive(Debug)]
589pub enum MemoryCreationError {
590 VirtualMemoryAllocationFailed(usize, String),
592 CouldNotCreateMemoryFromFile(std::io::Error),
594}
595
596impl std::fmt::Display for MemoryCreationError {
597 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
598 match self {
599 MemoryCreationError::VirtualMemoryAllocationFailed(size, msg) => write!(
600 f,
601 "Allocation virtual memory with size {} failed. \nErrno message: {}",
602 size, msg
603 ),
604 MemoryCreationError::CouldNotCreateMemoryFromFile(e) => write!(f, "IO Error: {}", e),
605 }
606 }
607}
608impl std::error::Error for MemoryCreationError {}
609
610impl Into<GrowError> for MemoryCreationError {
611 fn into(self) -> GrowError {
612 GrowError::CouldNotCreateMemory(self)
613 }
614}
615
616impl From<std::io::Error> for MemoryCreationError {
617 fn from(io_error: std::io::Error) -> Self {
618 MemoryCreationError::CouldNotCreateMemoryFromFile(io_error)
619 }
620}
621
622#[derive(Debug)]
624pub enum MemoryProtectionError {
625 ProtectionFailed(usize, usize, String),
627}
628
629impl std::fmt::Display for MemoryProtectionError {
630 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
631 match self {
632 MemoryProtectionError::ProtectionFailed(start, size, msg) => write!(
633 f,
634 "Allocation virtual memory starting at {} with size {} failed. \nErrno message: {}",
635 start, size, msg
636 ),
637 }
638 }
639}
640impl std::error::Error for MemoryProtectionError {}
641
642impl Into<GrowError> for MemoryProtectionError {
643 fn into(self) -> GrowError {
644 GrowError::CouldNotProtectMemory(self)
645 }
646}
647
648#[derive(Debug)]
650pub enum ParseError {
651 BinaryReadError,
653}
654
655impl From<wasmparser::BinaryReaderError> for ParseError {
656 fn from(_: wasmparser::BinaryReaderError) -> Self {
657 ParseError::BinaryReadError
658 }
659}