      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
    281
    282
    283
    284
    285
    286
    287
    288
    289
    290
    291
    292
    293
    294
    295
    296
    297
    298
    299
    300
    301
    302
    303
    304
    305
    306
    307
    308
    309
    310
    311
    312
    313
    314
    315
    316
    317
    318
    319
    320
    321
    322
    323
    324
    325
    326
    327
    328
    329
    330

    //! Elements of the WebAssembly binary format.

    use crate::rust::{fmt, vec::Vec, format, string::String};
    use crate::io;

    macro_rules! buffered_read {
    	($buffer_size: expr, $length: expr, $reader: expr) => {
    		{
    			let mut vec_buf = Vec::new();
    			let mut total_read = 0;
    			let mut buf = [0u8; $buffer_size];
    			while total_read < $length {
    				let next_to_read = if $length - total_read > $buffer_size { $buffer_size } else { $length - total_read };
    				$reader.read(&mut buf[0..next_to_read])?;
    				vec_buf.extend_from_slice(&buf[0..next_to_read]);
    				total_read += next_to_read;
    			}
    			vec_buf
    		}
    	}
    }

    mod primitives;
    mod module;
    mod section;
    mod types;
    mod import_entry;
    mod export_entry;
    mod global_entry;
    mod ops;
    mod func;
    mod segment;
    mod index_map;
    mod name_section;
    mod reloc_section;

    pub use self::module::{Module, peek_size, ImportCountType};
    pub use self::section::{
    	Section, FunctionSection, CodeSection, MemorySection, DataSection,
    	ImportSection, ExportSection, GlobalSection, TypeSection, ElementSection,
    	TableSection, CustomSection,
    };
    pub use self::import_entry::{ImportEntry, ResizableLimits, MemoryType, TableType, GlobalType, External};
    pub use self::export_entry::{ExportEntry, Internal};
    pub use self::global_entry::GlobalEntry;
    pub use self::primitives::{
    	VarUint32, VarUint7, Uint8, VarUint1, VarInt7, Uint32, VarInt32, VarInt64,
    	Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
    };
    pub use self::types::{Type, ValueType, BlockType, FunctionType, TableElementType};
    pub use self::ops::{Instruction, Instructions, InitExpr, opcodes, BrTableData};

    #[cfg(feature="atomics")]
    pub use self::ops::AtomicsInstruction;

    #[cfg(feature="simd")]
    pub use self::ops::SimdInstruction;

    #[cfg(feature="sign_ext")]
    pub use self::ops::SignExtInstruction;

    #[cfg(feature="bulk")]
    pub use self::ops::BulkInstruction;

    #[cfg(any(feature="simd", feature="atomics"))]
    pub use self::ops::MemArg;

    pub use self::func::{Func, FuncBody, Local};
    pub use self::segment::{ElementSegment, DataSegment};
    pub use self::index_map::IndexMap;
    pub use self::name_section::{
    	NameMap, NameSection, ModuleNameSubsection, FunctionNameSubsection,
    	LocalNameSubsection,
    };
    pub use self::reloc_section::{
    	RelocSection, RelocationEntry,
    };

    /// Deserialization from serial i/o.
    pub trait Deserialize : Sized {
    	/// Serialization error produced by deserialization routine.
    	type Error: From<io::Error>;
    	/// Deserialize type from serial i/o
    	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
    }

    /// Serialization to serial i/o. Takes self by value to consume less memory
    /// (parity-wasm IR is being partially freed by filling the result buffer).
    pub trait Serialize {
    	/// Serialization error produced by serialization routine.
    	type Error: From<io::Error>;
    	/// Serialize type to serial i/o
    	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
    }

    /// Deserialization/serialization error
    #[derive(Debug, Clone)]
    pub enum Error {
    	/// Unexpected end of input.
    	UnexpectedEof,
    	/// Invalid magic.
    	InvalidMagic,
    	/// Unsupported version.
    	UnsupportedVersion(u32),
    	/// Inconsistence between declared and actual length.
    	InconsistentLength {
    		/// Expected length of the definition.
    		expected: usize,
    		/// Actual length of the definition.
    		actual: usize
    	},
    	/// Other static error.
    	Other(&'static str),
    	/// Other allocated error.
    	HeapOther(String),
    	/// Invalid/unknown value type declaration.
    	UnknownValueType(i8),
    	/// Invalid/unknown table element type declaration.
    	UnknownTableElementType(i8),
    	/// Non-utf8 string.
    	NonUtf8String,
    	/// Unknown external kind code.
    	UnknownExternalKind(u8),
    	/// Unknown internal kind code.
    	UnknownInternalKind(u8),
    	/// Unknown opcode encountered.
    	UnknownOpcode(u8),
    	#[cfg(feature="simd")]
    	/// Unknown SIMD opcode encountered.
    	UnknownSimdOpcode(u32),
    	/// Invalid VarUint1 value.
    	InvalidVarUint1(u8),
    	/// Invalid VarInt32 value.
    	InvalidVarInt32,
    	/// Invalid VarInt64 value.
    	InvalidVarInt64,
    	/// Invalid VarUint32 value.
    	InvalidVarUint32,
    	/// Invalid VarUint64 value.
    	InvalidVarUint64,
    	/// Inconsistent metadata.
    	InconsistentMetadata,
    	/// Invalid section id.
    	InvalidSectionId(u8),
    	/// Sections are out of order.
    	SectionsOutOfOrder,
    	/// Duplicated sections.
    	DuplicatedSections(u8),
    	/// Invalid memory reference (should be 0).
    	InvalidMemoryReference(u8),
    	/// Invalid table reference (should be 0).
    	InvalidTableReference(u8),
    	/// Invalid value used for flags in limits type.
    	InvalidLimitsFlags(u8),
    	/// Unknown function form (should be 0x60).
    	UnknownFunctionForm(u8),
    	/// Invalid varint7 (should be in -64..63 range).
    	InvalidVarInt7(u8),
    	/// Number of function body entries and signatures does not match.
    	InconsistentCode,
    	/// Only flags 0, 1, and 2 are accepted on segments.
    	InvalidSegmentFlags(u32),
    	/// Sum of counts of locals is greater than 2^32.
    	TooManyLocals,
    	/// Duplicated name subsections.
    	DuplicatedNameSubsections(u8),
    	/// Unknown name subsection type.
    	UnknownNameSubsectionType(u8),
    }

    impl fmt::Display for Error {
    	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
    		match *self {
    			Error::UnexpectedEof => write!(f, "Unexpected end of input"),
    			Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
    			Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
    			Error::InconsistentLength { expected, actual } => {
    				write!(f, "Expected length {}, found {}", expected, actual)
    			}
    			Error::Other(msg) => write!(f, "{}", msg),
    			Error::HeapOther(ref msg) => write!(f, "{}", msg),
    			Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
    			Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
    			Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
    			Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
    			Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
    			Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
    			#[cfg(feature="simd")]
    			Error::UnknownSimdOpcode(opcode) => write!(f, "Unknown SIMD opcode {}", opcode),
    			Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
    			Error::InvalidVarInt7(val) => write!(f, "Not a signed 7-bit integer: {}", val),
    			Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
    			Error::InvalidVarUint32 => write!(f, "Not an unsigned 32-bit integer"),
    			Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
    			Error::InvalidVarUint64 => write!(f, "Not an unsigned 64-bit integer"),
    			Error::InconsistentMetadata =>  write!(f, "Inconsistent metadata"),
    			Error::InvalidSectionId(ref id) =>  write!(f, "Invalid section id: {}", id),
    			Error::SectionsOutOfOrder =>  write!(f, "Sections out of order"),
    			Error::DuplicatedSections(ref id) =>  write!(f, "Duplicated sections ({})", id),
    			Error::InvalidMemoryReference(ref mem_ref) =>  write!(f, "Invalid memory reference ({})", mem_ref),
    			Error::InvalidTableReference(ref table_ref) =>  write!(f, "Invalid table reference ({})", table_ref),
    			Error::InvalidLimitsFlags(ref flags) =>  write!(f, "Invalid limits flags ({})", flags),
    			Error::UnknownFunctionForm(ref form) =>  write!(f, "Unknown function form ({})", form),
    			Error::InconsistentCode =>  write!(f, "Number of function body entries and signatures does not match"),
    			Error::InvalidSegmentFlags(n) =>  write!(f, "Invalid segment flags: {}", n),
    			Error::TooManyLocals => write!(f, "Too many locals"),
    			Error::DuplicatedNameSubsections(n) =>  write!(f, "Duplicated name subsections: {}", n),
    			Error::UnknownNameSubsectionType(n) => write!(f, "Unknown subsection type: {}", n),
    		}
    	}
    }

    #[cfg(feature = "std")]
    impl ::std::error::Error for Error {
    	fn description(&self) -> &str {
    		match *self {
    			Error::UnexpectedEof => "Unexpected end of input",
    			Error::InvalidMagic => "Invalid magic number at start of file",
    			Error::UnsupportedVersion(_) => "Unsupported wasm version",
    			Error::InconsistentLength { .. } => "Inconsistent length",
    			Error::Other(msg) => msg,
    			Error::HeapOther(ref msg) => &msg[..],
    			Error::UnknownValueType(_) => "Invalid or unknown value type",
    			Error::UnknownTableElementType(_) => "Unknown table element type",
    			Error::NonUtf8String => "Non-UTF-8 string",
    			Error::UnknownExternalKind(_) => "Unknown external kind",
    			Error::UnknownInternalKind(_) => "Unknown internal kind",
    			Error::UnknownOpcode(_) => "Unknown opcode",
    			#[cfg(feature="simd")]
    			Error::UnknownSimdOpcode(_) => "Unknown SIMD opcode",
    			Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
    			Error::InvalidVarInt32 => "Not a signed 32-bit integer",
    			Error::InvalidVarInt7(_) => "Not a signed 7-bit integer",
    			Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
    			Error::InvalidVarInt64 => "Not a signed 64-bit integer",
    			Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
    			Error::InconsistentMetadata => "Inconsistent metadata",
    			Error::InvalidSectionId(_) =>  "Invalid section id",
    			Error::SectionsOutOfOrder =>  "Sections out of order",
    			Error::DuplicatedSections(_) =>  "Duplicated section",
    			Error::InvalidMemoryReference(_) =>  "Invalid memory reference",
    			Error::InvalidTableReference(_) =>  "Invalid table reference",
    			Error::InvalidLimitsFlags(_) => "Invalid limits flags",
    			Error::UnknownFunctionForm(_) =>  "Unknown function form",
    			Error::InconsistentCode =>  "Number of function body entries and signatures does not match",
    			Error::InvalidSegmentFlags(_) =>  "Invalid segment flags",
    			Error::TooManyLocals => "Too many locals",
    			Error::DuplicatedNameSubsections(_) =>  "Duplicated name subsections",
    			Error::UnknownNameSubsectionType(_) => "Unknown name subsections type",
    		}
    	}
    }

    impl From<io::Error> for Error {
    	fn from(err: io::Error) -> Self {
    		Error::HeapOther(format!("I/O Error: {:?}", err))
    	}
    }

    // These are emitted by section parsers, such as `parse_names` and `parse_reloc`.
    impl From<(Vec<(usize, Error)>, Module)> for Error {
    	fn from(err: (Vec<(usize, Error)>, Module)) -> Self {
    		let ret = err.0.iter()
    			.fold(
    				String::new(),
    				|mut acc, item| { acc.push_str(&format!("In section {}: {}\n", item.0, item.1)); acc }
    			);
    		Error::HeapOther(ret)
    	}
    }

    /// Unparsed part of the module/section.
    pub struct Unparsed(pub Vec<u8>);

    impl Deserialize for Unparsed {
    	type Error = Error;

    	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
    		let len = VarUint32::deserialize(reader)?.into();
    		let mut vec = vec![0u8; len];
    		reader.read(&mut vec[..])?;
    		Ok(Unparsed(vec))
    	}
    }

    impl From<Unparsed> for Vec<u8> {
    	fn from(u: Unparsed) -> Vec<u8> {
    		u.0
    	}
    }

    /// Deserialize deserializable type from buffer.
    pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
    	let mut reader = io::Cursor::new(contents);
    	let result = T::deserialize(&mut reader)?;
    	if reader.position() != contents.len() {
    		// It's a TrailingData, since if there is not enough data then
    		// UnexpectedEof must have been returned earlier in T::deserialize.
    		return Err(io::Error::TrailingData.into())
    	}
    	Ok(result)
    }

    /// Create buffer with serialized value.
    pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
    	let mut buf = Vec::new();
    	val.serialize(&mut buf)?;
    	Ok(buf)
    }

    /// Deserialize module from the file.
    #[cfg(feature = "std")]
    pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
    	let mut f = ::std::fs::File::open(p)
    		.map_err(|e| Error::HeapOther(format!("Can't read from the file: {:?}", e)))?;

    	Module::deserialize(&mut f)
    }

    /// Serialize module to the file
    #[cfg(feature = "std")]
    pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error> {
    	let mut io = ::std::fs::File::create(p)
    		.map_err(|e|
    			Error::HeapOther(format!("Can't create the file: {:?}", e))
    		)?;

    	module.serialize(&mut io)?;
    	Ok(())
    }

# Help

## Keyboard Shortcuts

`?`
  Show this help dialog
`S`
  Focus the search field
`↑`
  Move up in search results
`↓`
  Move down in search results
`↹`
  Switch tab
`⏎`
  Go to active search result
`+`
  Expand all sections
`-`
  Collapse all sections

## Search Tricks

Prefix searches with a type followed by a colon (e.g., `fn:`) to restrict the search to a given type.

Accepted types are: `fn`, `mod`, `struct`, `enum`, `trait`, `type`, `macro`, and `const`.

Search functions by type signature (e.g., `vec -> usize` or `* -> vec`)

Search multiple things at once by splitting your query with comma (e.g., `str,u8` or `String,struct:Vec,test`)