2019-04-22 18:42:52 +00:00
use crate ::types ::{ FuncSig , GlobalDescriptor , MemoryDescriptor , TableDescriptor , Type } ;
2019-02-15 02:19:18 +00:00
use core ::borrow ::Borrow ;
2019-03-12 08:51:54 +00:00
use std ::any ::Any ;
2019-01-18 18:54:16 +00:00
2019-02-02 23:28:50 +00:00
pub type Result < T > = std ::result ::Result < T , Error > ;
pub type CompileResult < T > = std ::result ::Result < T , CompileError > ;
2019-01-18 21:44:44 +00:00
pub type LinkResult < T > = std ::result ::Result < T , Vec < LinkError > > ;
2019-02-02 23:28:50 +00:00
pub type RuntimeResult < T > = std ::result ::Result < T , RuntimeError > ;
pub type CallResult < T > = std ::result ::Result < T , CallError > ;
pub type ResolveResult < T > = std ::result ::Result < T , ResolveError > ;
2019-03-12 17:45:44 +00:00
pub type ParseResult < T > = std ::result ::Result < T , ParseError > ;
2019-01-18 18:54:16 +00:00
/// This is returned when the chosen compiler is unable to
/// successfully compile the provided webassembly module into
/// a `Module`.
///
/// Comparing two `CompileError`s always evaluates to false.
#[ derive(Debug, Clone) ]
pub enum CompileError {
ValidationError { msg : String } ,
InternalError { msg : String } ,
}
impl PartialEq for CompileError {
fn eq ( & self , _other : & CompileError ) -> bool {
false
}
}
2019-02-15 05:08:35 +00:00
impl std ::fmt ::Display for CompileError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
CompileError ::InternalError { msg } = > {
write! ( f , " Internal compiler error: \" {} \" " , msg )
}
CompileError ::ValidationError { msg } = > write! ( f , " Validation error \" {} \" " , msg ) ,
}
}
}
impl std ::error ::Error for CompileError { }
2019-01-18 18:54:16 +00:00
/// This is returned when the runtime is unable to
/// correctly link the module with the provided imports.
///
/// Comparing two `LinkError`s always evaluates to false.
#[ derive(Debug, Clone) ]
pub enum LinkError {
IncorrectImportType {
namespace : String ,
name : String ,
expected : String ,
found : String ,
} ,
IncorrectImportSignature {
namespace : String ,
name : String ,
2019-02-08 22:19:58 +00:00
expected : FuncSig ,
found : FuncSig ,
2019-01-18 18:54:16 +00:00
} ,
ImportNotFound {
namespace : String ,
name : String ,
} ,
2019-01-29 21:04:42 +00:00
IncorrectMemoryDescriptor {
2019-01-18 18:54:16 +00:00
namespace : String ,
name : String ,
2019-01-29 21:04:42 +00:00
expected : MemoryDescriptor ,
found : MemoryDescriptor ,
2019-01-18 18:54:16 +00:00
} ,
2019-01-29 21:04:42 +00:00
IncorrectTableDescriptor {
2019-01-18 18:54:16 +00:00
namespace : String ,
name : String ,
2019-01-29 21:04:42 +00:00
expected : TableDescriptor ,
found : TableDescriptor ,
2019-01-18 18:54:16 +00:00
} ,
2019-01-29 21:04:42 +00:00
IncorrectGlobalDescriptor {
2019-01-18 18:54:16 +00:00
namespace : String ,
name : String ,
2019-01-29 21:04:42 +00:00
expected : GlobalDescriptor ,
found : GlobalDescriptor ,
2019-01-18 18:54:16 +00:00
} ,
}
impl PartialEq for LinkError {
fn eq ( & self , _other : & LinkError ) -> bool {
false
}
}
2019-02-15 02:40:52 +00:00
impl std ::fmt ::Display for LinkError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
LinkError ::ImportNotFound { namespace , name } = > write! ( f , " Import not found, namespace: {}, name: {} " , namespace , name ) ,
LinkError ::IncorrectGlobalDescriptor { namespace , name , expected , found } = > {
write! ( f , " Incorrect global descriptor, namespace: {}, name: {}, expected global descriptor: {:?}, found global descriptor: {:?} " , namespace , name , expected , found )
} ,
LinkError ::IncorrectImportSignature { namespace , name , expected , found } = > {
write! ( f , " Incorrect import signature, namespace: {}, name: {}, expected signature: {}, found signature: {} " , namespace , name , expected , found )
}
LinkError ::IncorrectImportType { namespace , name , expected , found } = > {
write! ( f , " Incorrect import type, namespace: {}, name: {}, expected type: {}, found type: {} " , namespace , name , expected , found )
}
LinkError ::IncorrectMemoryDescriptor { namespace , name , expected , found } = > {
write! ( f , " Incorrect memory descriptor, namespace: {}, name: {}, expected memory descriptor: {:?}, found memory descriptor: {:?} " , namespace , name , expected , found )
} ,
LinkError ::IncorrectTableDescriptor { namespace , name , expected , found } = > {
write! ( f , " Incorrect table descriptor, namespace: {}, name: {}, expected table descriptor: {:?}, found table descriptor: {:?} " , namespace , name , expected , found )
} ,
}
}
}
impl std ::error ::Error for LinkError { }
2019-01-18 18:54:16 +00:00
/// This is the error type returned when calling
/// a webassembly function.
///
/// The main way to do this is `Instance.call`.
///
/// Comparing two `RuntimeError`s always evaluates to false.
pub enum RuntimeError {
2019-03-04 20:57:26 +00:00
Trap { msg : Box < str > } ,
2019-04-22 18:42:52 +00:00
Error { data : Box < dyn Any > } ,
2019-01-18 18:54:16 +00:00
}
impl PartialEq for RuntimeError {
fn eq ( & self , _other : & RuntimeError ) -> bool {
false
}
}
2019-02-15 16:15:57 +00:00
impl std ::fmt ::Display for RuntimeError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
2019-03-04 20:57:26 +00:00
RuntimeError ::Trap { ref msg } = > {
write! ( f , " WebAssembly trap occured during runtime: {} " , msg )
2019-02-15 16:15:57 +00:00
}
2019-04-22 18:42:52 +00:00
RuntimeError ::Error { data } = > {
2019-04-22 22:06:40 +00:00
if let Some ( s ) = data . downcast_ref ::< String > ( ) {
write! ( f , " \" {} \" " , s )
2019-04-02 00:50:53 +00:00
} else if let Some ( s ) = data . downcast_ref ::< & str > ( ) {
2019-04-22 22:06:40 +00:00
write! ( f , " \" {} \" " , s )
2019-04-02 00:50:53 +00:00
} else {
2019-04-22 22:06:40 +00:00
write! ( f , " unknown error " )
}
2019-04-02 00:50:53 +00:00
}
2019-02-15 16:15:57 +00:00
}
}
}
2019-04-02 00:50:53 +00:00
impl std ::fmt ::Debug for RuntimeError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
write! ( f , " {} " , self )
}
}
2019-02-15 16:15:57 +00:00
impl std ::error ::Error for RuntimeError { }
2019-01-23 23:30:35 +00:00
/// This error type is produced by resolving a wasm function
/// given its name.
///
/// Comparing two `ResolveError`s always evaluates to false.
#[ derive(Debug, Clone) ]
pub enum ResolveError {
2019-02-08 22:19:58 +00:00
Signature { expected : FuncSig , found : Vec < Type > } ,
ExportNotFound { name : String } ,
ExportWrongType { name : String } ,
2019-01-23 23:30:35 +00:00
}
impl PartialEq for ResolveError {
fn eq ( & self , _other : & ResolveError ) -> bool {
false
}
}
2019-02-15 02:19:18 +00:00
impl std ::fmt ::Display for ResolveError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
ResolveError ::ExportNotFound { name } = > write! ( f , " Export not found: {} " , name ) ,
ResolveError ::ExportWrongType { name } = > write! ( f , " Export wrong type: {} " , name ) ,
ResolveError ::Signature { expected , found } = > {
let found = found
. as_slice ( )
. iter ( )
. map ( | p | p . to_string ( ) )
. collect ::< Vec < _ > > ( )
. join ( " , " ) ;
let expected : & FuncSig = expected . borrow ( ) ;
write! (
f ,
" Parameters of type [{}] did not match signature {} " ,
found , expected
)
}
}
}
}
impl std ::error ::Error for ResolveError { }
2019-01-18 18:54:16 +00:00
/// This error type is produced by calling a wasm function
/// exported from a module.
///
/// If the module traps in some way while running, this will
/// be the `CallError::Runtime(RuntimeError)` variant.
///
/// Comparing two `CallError`s always evaluates to false.
pub enum CallError {
2019-01-23 23:30:35 +00:00
Resolve ( ResolveError ) ,
2019-01-18 18:54:16 +00:00
Runtime ( RuntimeError ) ,
}
impl PartialEq for CallError {
fn eq ( & self , _other : & CallError ) -> bool {
false
}
}
2019-02-15 16:15:57 +00:00
impl std ::fmt ::Display for CallError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
CallError ::Resolve ( resolve_error ) = > write! ( f , " Call error: {} " , resolve_error ) ,
CallError ::Runtime ( runtime_error ) = > write! ( f , " Call error: {} " , runtime_error ) ,
}
}
}
2019-04-02 00:50:53 +00:00
impl std ::fmt ::Debug for CallError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
CallError ::Resolve ( resolve_err ) = > write! ( f , " ResolveError: {:?} " , resolve_err ) ,
CallError ::Runtime ( runtime_err ) = > write! ( f , " RuntimeError: {:?} " , runtime_err ) ,
}
}
}
2019-02-16 01:16:19 +00:00
impl std ::error ::Error for CallError { }
2019-01-29 23:44:15 +00:00
/// This error type is produced when creating something,
/// like a `Memory` or a `Table`.
#[ derive(Debug, Clone) ]
pub enum CreationError {
UnableToCreateMemory ,
UnableToCreateTable ,
2019-02-15 21:14:42 +00:00
InvalidDescriptor ( String ) ,
2019-01-29 23:44:15 +00:00
}
impl PartialEq for CreationError {
fn eq ( & self , _other : & CreationError ) -> bool {
false
}
}
2019-02-15 03:22:19 +00:00
impl std ::fmt ::Display for CreationError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
CreationError ::UnableToCreateMemory = > write! ( f , " Unable to Create Memory " ) ,
CreationError ::UnableToCreateTable = > write! ( f , " Unable to Create Table " ) ,
2019-02-15 21:14:42 +00:00
CreationError ::InvalidDescriptor ( msg ) = > write! (
f ,
" Unable to create because the supplied descriptor is invalid: \" {} \" " ,
msg
) ,
2019-02-15 03:22:19 +00:00
}
}
}
impl std ::error ::Error for CreationError { }
2019-01-18 18:54:16 +00:00
/// The amalgamation of all errors that can occur
/// during the compilation, instantiation, or execution
/// of a webassembly module.
///
/// Comparing two `Error`s always evaluates to false.
2019-03-04 20:57:26 +00:00
#[ derive(Debug) ]
2019-01-18 18:54:16 +00:00
pub enum Error {
CompileError ( CompileError ) ,
2019-01-18 21:44:44 +00:00
LinkError ( Vec < LinkError > ) ,
2019-01-18 18:54:16 +00:00
RuntimeError ( RuntimeError ) ,
2019-01-24 18:51:20 +00:00
ResolveError ( ResolveError ) ,
2019-01-18 18:54:16 +00:00
CallError ( CallError ) ,
2019-01-29 23:44:15 +00:00
CreationError ( CreationError ) ,
2019-01-18 18:54:16 +00:00
}
impl PartialEq for Error {
fn eq ( & self , _other : & Error ) -> bool {
false
}
}
2019-02-02 23:28:50 +00:00
impl From < CompileError > for Error {
2019-01-23 23:30:35 +00:00
fn from ( compile_err : CompileError ) -> Self {
2019-02-02 23:28:50 +00:00
Error ::CompileError ( compile_err )
2019-01-23 23:30:35 +00:00
}
}
2019-02-02 23:28:50 +00:00
impl From < RuntimeError > for Error {
2019-01-23 23:30:35 +00:00
fn from ( runtime_err : RuntimeError ) -> Self {
2019-02-02 23:28:50 +00:00
Error ::RuntimeError ( runtime_err )
2019-01-23 23:30:35 +00:00
}
}
2019-02-03 00:02:28 +00:00
impl From < ResolveError > for Error {
fn from ( resolve_err : ResolveError ) -> Self {
Error ::ResolveError ( resolve_err )
}
}
2019-02-02 23:28:50 +00:00
impl From < CallError > for Error {
2019-01-23 23:30:35 +00:00
fn from ( call_err : CallError ) -> Self {
2019-02-02 23:28:50 +00:00
Error ::CallError ( call_err )
2019-01-23 23:30:35 +00:00
}
}
2019-02-02 23:28:50 +00:00
impl From < CreationError > for Error {
2019-01-29 23:44:15 +00:00
fn from ( creation_err : CreationError ) -> Self {
2019-02-02 23:28:50 +00:00
Error ::CreationError ( creation_err )
}
}
impl From < Vec < LinkError > > for Error {
fn from ( link_errs : Vec < LinkError > ) -> Self {
Error ::LinkError ( link_errs )
2019-01-29 23:44:15 +00:00
}
}
2019-02-02 23:28:50 +00:00
impl From < RuntimeError > for CallError {
2019-01-23 23:30:35 +00:00
fn from ( runtime_err : RuntimeError ) -> Self {
2019-02-02 23:28:50 +00:00
CallError ::Runtime ( runtime_err )
2019-01-23 23:30:35 +00:00
}
}
2019-02-02 23:28:50 +00:00
impl From < ResolveError > for CallError {
2019-01-23 23:30:35 +00:00
fn from ( resolve_err : ResolveError ) -> Self {
2019-02-02 23:28:50 +00:00
CallError ::Resolve ( resolve_err )
2019-01-23 23:30:35 +00:00
}
}
2019-02-15 16:15:57 +00:00
impl std ::fmt ::Display for Error {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
2019-02-23 09:00:03 +00:00
match self {
Error ::CompileError ( err ) = > write! ( f , " compile error: {} " , err ) ,
Error ::LinkError ( errs ) = > {
if errs . len ( ) = = 1 {
write! ( f , " link error: {} " , errs [ 0 ] )
} else {
write! ( f , " {} link errors: " , errs . len ( ) ) ? ;
for ( i , err ) in errs . iter ( ) . enumerate ( ) {
write! ( f , " ({} of {}) {} " , i + 1 , errs . len ( ) , err ) ? ;
}
Ok ( ( ) )
}
2019-02-25 20:25:28 +00:00
}
2019-02-23 09:00:03 +00:00
Error ::RuntimeError ( err ) = > write! ( f , " runtime error: {} " , err ) ,
Error ::ResolveError ( err ) = > write! ( f , " resolve error: {} " , err ) ,
Error ::CallError ( err ) = > write! ( f , " call error: {} " , err ) ,
Error ::CreationError ( err ) = > write! ( f , " creation error: {} " , err ) ,
}
2019-02-15 16:15:57 +00:00
}
}
impl std ::error ::Error for Error { }
2019-02-23 06:18:59 +00:00
#[ derive(Debug) ]
pub enum GrowError {
MemoryGrowError ,
TableGrowError ,
ExceededMaxPages ( PageError ) ,
ExceededMaxPagesForMemory ( usize , usize ) ,
CouldNotProtectMemory ( MemoryProtectionError ) ,
CouldNotCreateMemory ( MemoryCreationError ) ,
}
impl std ::fmt ::Display for GrowError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
GrowError ::MemoryGrowError = > write! ( f , " Unable to grow memory " ) ,
GrowError ::TableGrowError = > write! ( f , " Unable to grow table " ) ,
GrowError ::ExceededMaxPages ( e ) = > write! ( f , " Grow Error: {} " , e ) ,
GrowError ::ExceededMaxPagesForMemory ( left , added ) = > write! ( f , " Failed to add pages because would exceed maximum number of pages for the memory. Left: {}, Added: {} " , left , added ) ,
GrowError ::CouldNotCreateMemory ( e ) = > write! ( f , " Grow Error: {} " , e ) ,
GrowError ::CouldNotProtectMemory ( e ) = > write! ( f , " Grow Error: {} " , e ) ,
}
}
}
impl std ::error ::Error for GrowError { }
#[ derive(Debug) ]
pub enum PageError {
// left, right, added
ExceededMaxPages ( usize , usize , usize ) ,
}
impl std ::fmt ::Display for PageError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
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 ) ,
}
}
}
impl std ::error ::Error for PageError { }
impl Into < GrowError > for PageError {
fn into ( self ) -> GrowError {
GrowError ::ExceededMaxPages ( self )
}
}
#[ derive(Debug) ]
pub enum MemoryCreationError {
VirtualMemoryAllocationFailed ( usize , String ) ,
CouldNotCreateMemoryFromFile ( std ::io ::Error ) ,
}
impl std ::fmt ::Display for MemoryCreationError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
MemoryCreationError ::VirtualMemoryAllocationFailed ( size , msg ) = > write! (
f ,
" Allocation virtual memory with size {} failed. \n Errno message: {} " ,
size , msg
) ,
MemoryCreationError ::CouldNotCreateMemoryFromFile ( e ) = > write! ( f , " IO Error: {} " , e ) ,
}
}
}
impl std ::error ::Error for MemoryCreationError { }
impl Into < GrowError > for MemoryCreationError {
fn into ( self ) -> GrowError {
GrowError ::CouldNotCreateMemory ( self )
}
}
impl From < std ::io ::Error > for MemoryCreationError {
fn from ( io_error : std ::io ::Error ) -> Self {
MemoryCreationError ::CouldNotCreateMemoryFromFile ( io_error )
}
}
#[ derive(Debug) ]
pub enum MemoryProtectionError {
ProtectionFailed ( usize , usize , String ) ,
}
impl std ::fmt ::Display for MemoryProtectionError {
fn fmt ( & self , f : & mut std ::fmt ::Formatter ) -> std ::fmt ::Result {
match self {
MemoryProtectionError ::ProtectionFailed ( start , size , msg ) = > write! (
f ,
" Allocation virtual memory starting at {} with size {} failed. \n Errno message: {} " ,
start , size , msg
) ,
}
}
}
impl std ::error ::Error for MemoryProtectionError { }
impl Into < GrowError > for MemoryProtectionError {
fn into ( self ) -> GrowError {
GrowError ::CouldNotProtectMemory ( self )
}
}
2019-03-12 17:45:44 +00:00
#[ derive(Debug) ]
pub enum ParseError {
BinaryReadError ,
}
impl From < wasmparser ::BinaryReaderError > for ParseError {
fn from ( _ : wasmparser ::BinaryReaderError ) -> Self {
ParseError ::BinaryReadError
}
}