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!(
152 f,
153 "Import not found, namespace: {}, name: {}",
154 namespace, name
155 ),
156 LinkError::IncorrectGlobalDescriptor {
157 namespace,
158 name,
159 expected,
160 found,
161 } => {
162 write!(f, "Incorrect global descriptor, namespace: {}, name: {}, expected global descriptor: {:?}, found global descriptor: {:?}", namespace, name, expected, found)
163 }
164 LinkError::IncorrectImportSignature {
165 namespace,
166 name,
167 expected,
168 found,
169 } => {
170 write!(f, "Incorrect import signature, namespace: {}, name: {}, expected signature: {}, found signature: {}", namespace, name, expected, found)
171 }
172 LinkError::IncorrectImportType {
173 namespace,
174 name,
175 expected,
176 found,
177 } => {
178 write!(f, "Incorrect import type, namespace: {}, name: {}, expected type: {}, found type: {}", namespace, name, expected, found)
179 }
180 LinkError::IncorrectMemoryDescriptor {
181 namespace,
182 name,
183 expected,
184 found,
185 } => {
186 write!(f, "Incorrect memory descriptor, namespace: {}, name: {}, expected memory descriptor: {:?}, found memory descriptor: {:?}", namespace, name, expected, found)
187 }
188 LinkError::IncorrectTableDescriptor {
189 namespace,
190 name,
191 expected,
192 found,
193 } => {
194 write!(f, "Incorrect table descriptor, namespace: {}, name: {}, expected table descriptor: {:?}, found table descriptor: {:?}", namespace, name, expected, found)
195 }
196 LinkError::Generic { message } => {
197 write!(f, "{}", message)
198 }
199 }
200 }
201}
202
203impl std::error::Error for LinkError {}
204
205#[derive(Debug)]
207pub enum InvokeError {
208 FailedWithNoError,
211 UnknownTrap {
213 address: usize,
215 signal: &'static str,
217 },
218 TrapCode {
220 code: ExceptionCode,
222 srcloc: u32,
224 },
225 UnknownTrapCode {
228 trap_code: String,
230 srcloc: u32,
232 },
233 EarlyTrap(Box<RuntimeError>),
235 Breakpoint(Box<RuntimeError>),
238}
239
240impl From<InvokeError> for RuntimeError {
241 fn from(other: InvokeError) -> RuntimeError {
242 match other {
243 InvokeError::EarlyTrap(re) | InvokeError::Breakpoint(re) => *re,
244 _ => RuntimeError::InvokeError(other),
245 }
246 }
247}
248
249impl std::error::Error for InvokeError {}
250
251impl std::fmt::Display for InvokeError {
252 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
253 match self {
254 InvokeError::FailedWithNoError => write!(f, "Invoke failed with no error"),
255 InvokeError::UnknownTrap { address, signal } => write!(
256 f,
257 "An unknown trap (`{}`) occured at 0x{:X}",
258 signal, address
259 ),
260 InvokeError::TrapCode { code, srcloc } => {
261 write!(f, "A `{}` trap was thrown at code offset {}", code, srcloc)
262 }
263 InvokeError::UnknownTrapCode { trap_code, srcloc } => write!(
264 f,
265 "A trap with an unknown trap code (`{}`) was thrown at code offset {}",
266 trap_code, srcloc
267 ),
268 InvokeError::EarlyTrap(rte) => write!(f, "Early trap: {}", rte),
269 InvokeError::Breakpoint(rte) => write!(f, "Breakpoint hit: {}", rte),
270 }
271 }
272}
273
274#[derive(Debug)]
281pub enum RuntimeError {
282 InvokeError(InvokeError),
284 Metering(Box<dyn Any + Send>),
288 InstanceImage(Box<dyn Any + Send>),
292 User(Box<dyn Any + Send>),
296}
297
298impl PartialEq for RuntimeError {
299 fn eq(&self, _other: &RuntimeError) -> bool {
300 false
301 }
302}
303
304impl std::error::Error for RuntimeError {}
305
306impl std::fmt::Display for RuntimeError {
307 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
308 match self {
309 RuntimeError::InvokeError(ie) => write!(f, "Error when calling invoke: {}", ie),
310 RuntimeError::Metering(_) => write!(f, "unknown metering error type"),
311 RuntimeError::InstanceImage(_) => write!(
312 f,
313 "Execution interrupted by a suspend signal: instance image returned"
314 ),
315 RuntimeError::User(user_error) => {
316 write!(f, "User supplied error: ")?;
317 if let Some(s) = user_error.downcast_ref::<String>() {
318 write!(f, "\"{}\"", s)
319 } else if let Some(s) = user_error.downcast_ref::<&str>() {
320 write!(f, "\"{}\"", s)
321 } else if let Some(n) = user_error.downcast_ref::<i32>() {
322 write!(f, "{}", n)
323 } else {
324 write!(f, "unknown user error type")
325 }
326 }
327 }
328 }
329}
330
331#[derive(Debug, Clone)]
336pub enum ResolveError {
337 Signature {
339 expected: FuncSig,
341 found: Vec<Type>,
343 },
344 ExportNotFound {
346 name: String,
348 },
349 ExportWrongType {
351 name: String,
353 },
354}
355
356impl PartialEq for ResolveError {
357 fn eq(&self, _other: &ResolveError) -> bool {
358 false
359 }
360}
361
362impl std::fmt::Display for ResolveError {
363 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
364 match self {
365 ResolveError::ExportNotFound { name } => write!(f, "Export not found: {}", name),
366 ResolveError::ExportWrongType { name } => write!(f, "Export wrong type: {}", name),
367 ResolveError::Signature { expected, found } => {
368 let found = found
369 .as_slice()
370 .iter()
371 .map(|p| p.to_string())
372 .collect::<Vec<_>>()
373 .join(", ");
374 let expected: &FuncSig = expected.borrow();
375 write!(
376 f,
377 "Parameters of type [{}] did not match signature {}",
378 found, expected
379 )
380 }
381 }
382 }
383}
384
385impl std::error::Error for ResolveError {}
386
387pub enum CallError {
395 Resolve(ResolveError),
397 Runtime(RuntimeError),
399}
400
401impl PartialEq for CallError {
402 fn eq(&self, _other: &CallError) -> bool {
403 false
404 }
405}
406
407impl std::fmt::Display for CallError {
408 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
409 match self {
410 CallError::Resolve(resolve_error) => write!(f, "Call error: {}", resolve_error),
411 CallError::Runtime(runtime_error) => write!(f, "Call error: {}", runtime_error),
412 }
413 }
414}
415
416impl std::fmt::Debug for CallError {
417 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
418 match self {
419 CallError::Resolve(resolve_err) => write!(f, "ResolveError: {:?}", resolve_err),
420 CallError::Runtime(runtime_err) => write!(f, "RuntimeError: {:?}", runtime_err),
421 }
422 }
423}
424
425impl std::error::Error for CallError {}
426
427#[derive(Debug, Clone)]
430pub enum CreationError {
431 UnableToCreateMemory,
433 UnableToCreateTable,
435 InvalidDescriptor(String),
437}
438
439impl PartialEq for CreationError {
440 fn eq(&self, _other: &CreationError) -> bool {
441 false
442 }
443}
444
445impl std::fmt::Display for CreationError {
446 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
447 match self {
448 CreationError::UnableToCreateMemory => write!(f, "Unable to Create Memory"),
449 CreationError::UnableToCreateTable => write!(f, "Unable to Create Table"),
450 CreationError::InvalidDescriptor(msg) => write!(
451 f,
452 "Unable to create because the supplied descriptor is invalid: \"{}\"",
453 msg
454 ),
455 }
456 }
457}
458
459impl std::error::Error for CreationError {}
460
461#[derive(Debug)]
467pub enum Error {
468 CompileError(CompileError),
470 LinkError(Vec<LinkError>),
472 RuntimeError(RuntimeError),
474 ResolveError(ResolveError),
476 CallError(CallError),
478 CreationError(CreationError),
480}
481
482impl PartialEq for Error {
483 fn eq(&self, _other: &Error) -> bool {
484 false
485 }
486}
487
488impl From<CompileError> for Error {
489 fn from(compile_err: CompileError) -> Self {
490 Error::CompileError(compile_err)
491 }
492}
493
494impl From<RuntimeError> for Error {
495 fn from(runtime_err: RuntimeError) -> Self {
496 Error::RuntimeError(runtime_err)
497 }
498}
499
500impl From<ResolveError> for Error {
501 fn from(resolve_err: ResolveError) -> Self {
502 Error::ResolveError(resolve_err)
503 }
504}
505
506impl From<CallError> for Error {
507 fn from(call_err: CallError) -> Self {
508 Error::CallError(call_err)
509 }
510}
511
512impl From<CreationError> for Error {
513 fn from(creation_err: CreationError) -> Self {
514 Error::CreationError(creation_err)
515 }
516}
517
518impl From<Vec<LinkError>> for Error {
519 fn from(link_errs: Vec<LinkError>) -> Self {
520 Error::LinkError(link_errs)
521 }
522}
523
524impl From<RuntimeError> for CallError {
525 fn from(runtime_err: RuntimeError) -> Self {
526 CallError::Runtime(runtime_err)
527 }
528}
529
530impl From<ResolveError> for CallError {
531 fn from(resolve_err: ResolveError) -> Self {
532 CallError::Resolve(resolve_err)
533 }
534}
535
536impl std::fmt::Display for Error {
537 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
538 match self {
539 Error::CompileError(err) => write!(f, "compile error: {}", err),
540 Error::LinkError(errs) => {
541 if errs.len() == 1 {
542 write!(f, "link error: {}", errs[0])
543 } else {
544 write!(f, "{} link errors:", errs.len())?;
545 for (i, err) in errs.iter().enumerate() {
546 write!(f, " ({} of {}) {}", i + 1, errs.len(), err)?;
547 }
548 Ok(())
549 }
550 }
551 Error::RuntimeError(err) => write!(f, "runtime error: {}", err),
552 Error::ResolveError(err) => write!(f, "resolve error: {}", err),
553 Error::CallError(err) => write!(f, "call error: {}", err),
554 Error::CreationError(err) => write!(f, "creation error: {}", err),
555 }
556 }
557}
558
559impl std::error::Error for Error {}
560
561#[derive(Debug)]
563pub enum GrowError {
564 MemoryGrowError,
566 TableGrowError,
568 ExceededMaxPages(PageError),
570 ExceededMaxPagesForMemory(usize, usize),
572 CouldNotProtectMemory(MemoryProtectionError),
574 CouldNotCreateMemory(MemoryCreationError),
576}
577
578impl std::fmt::Display for GrowError {
579 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
580 match self {
581 GrowError::MemoryGrowError => write!(f, "Unable to grow memory"),
582 GrowError::TableGrowError => write!(f, "Unable to grow table"),
583 GrowError::ExceededMaxPages(e) => write!(f, "Grow Error: {}", e),
584 GrowError::ExceededMaxPagesForMemory(left, added) => write!(f, "Failed to add pages because would exceed maximum number of pages for the memory. Left: {}, Added: {}", left, added),
585 GrowError::CouldNotCreateMemory(e) => write!(f, "Grow Error: {}", e),
586 GrowError::CouldNotProtectMemory(e) => write!(f, "Grow Error: {}", e),
587 }
588 }
589}
590
591impl std::error::Error for GrowError {}
592
593#[derive(Debug)]
595pub enum PageError {
596 ExceededMaxPages(usize, usize, usize),
599}
600
601impl std::fmt::Display for PageError {
602 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
603 match self {
604 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),
605 }
606 }
607}
608impl std::error::Error for PageError {}
609
610impl Into<GrowError> for PageError {
611 fn into(self) -> GrowError {
612 GrowError::ExceededMaxPages(self)
613 }
614}
615
616#[derive(Debug)]
618pub enum MemoryCreationError {
619 VirtualMemoryAllocationFailed(usize, String),
621 CouldNotCreateMemoryFromFile(std::io::Error),
623}
624
625impl std::fmt::Display for MemoryCreationError {
626 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
627 match self {
628 MemoryCreationError::VirtualMemoryAllocationFailed(size, msg) => write!(
629 f,
630 "Allocation virtual memory with size {} failed. \nErrno message: {}",
631 size, msg
632 ),
633 MemoryCreationError::CouldNotCreateMemoryFromFile(e) => write!(f, "IO Error: {}", e),
634 }
635 }
636}
637impl std::error::Error for MemoryCreationError {}
638
639impl Into<GrowError> for MemoryCreationError {
640 fn into(self) -> GrowError {
641 GrowError::CouldNotCreateMemory(self)
642 }
643}
644
645impl From<std::io::Error> for MemoryCreationError {
646 fn from(io_error: std::io::Error) -> Self {
647 MemoryCreationError::CouldNotCreateMemoryFromFile(io_error)
648 }
649}
650
651#[derive(Debug)]
653pub enum MemoryProtectionError {
654 ProtectionFailed(usize, usize, String),
656}
657
658impl std::fmt::Display for MemoryProtectionError {
659 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
660 match self {
661 MemoryProtectionError::ProtectionFailed(start, size, msg) => write!(
662 f,
663 "Allocation virtual memory starting at {} with size {} failed. \nErrno message: {}",
664 start, size, msg
665 ),
666 }
667 }
668}
669impl std::error::Error for MemoryProtectionError {}
670
671impl Into<GrowError> for MemoryProtectionError {
672 fn into(self) -> GrowError {
673 GrowError::CouldNotProtectMemory(self)
674 }
675}
676
677#[derive(Debug)]
679pub enum ParseError {
680 BinaryReadError,
682}
683
684impl From<wasmparser::BinaryReaderError> for ParseError {
685 fn from(_: wasmparser::BinaryReaderError) -> Self {
686 ParseError::BinaryReadError
687 }
688}