parity_wasm_cp/elements/
mod.rs

1//! Elements of the WebAssembly binary format.
2
3use std::fmt;
4use io;
5use std::vec::Vec;
6use std::string::String;
7
8macro_rules! buffered_read {
9	($buffer_size: expr, $length: expr, $reader: expr) => {
10		{
11			let mut vec_buf = Vec::new();
12			let mut total_read = 0;
13			let mut buf = [0u8; $buffer_size];
14			while total_read < $length {
15				let next_to_read = if $length - total_read > $buffer_size { $buffer_size } else { $length - total_read };
16				$reader.read(&mut buf[0..next_to_read])?;
17				vec_buf.extend_from_slice(&buf[0..next_to_read]);
18				total_read += next_to_read;
19			}
20			vec_buf
21		}
22	}
23}
24
25mod primitives;
26mod module;
27mod section;
28mod types;
29mod import_entry;
30mod export_entry;
31mod global_entry;
32mod ops;
33mod func;
34mod segment;
35mod index_map;
36mod name_section;
37mod reloc_section;
38
39pub use self::module::{Module, peek_size, ImportCountType};
40pub use self::section::{
41	Section, FunctionSection, CodeSection, MemorySection, DataSection,
42	ImportSection, ExportSection, GlobalSection, TypeSection, ElementSection,
43	TableSection, CustomSection,
44};
45pub use self::import_entry::{ImportEntry, ResizableLimits, MemoryType, TableType, GlobalType, External};
46pub use self::export_entry::{ExportEntry, Internal};
47pub use self::global_entry::GlobalEntry;
48pub use self::primitives::{
49	VarUint32, VarUint7, Uint8, VarUint1, VarInt7, Uint32, VarInt32, VarInt64,
50	Uint64, VarUint64, CountedList, CountedWriter, CountedListWriter,
51};
52pub use self::types::{Type, ValueType, BlockType, FunctionType, TableElementType};
53pub use self::ops::{Instruction, Instructions, InitExpr, opcodes};
54pub use self::func::{Func, FuncBody, Local};
55pub use self::segment::{ElementSegment, DataSegment};
56pub use self::index_map::IndexMap;
57pub use self::name_section::{
58	NameMap, NameSection, ModuleNameSection, FunctionNameSection,
59	LocalNameSection,
60};
61pub use self::reloc_section::{
62	RelocSection, RelocationEntry,
63};
64
65/// Deserialization from serial i/o
66pub trait Deserialize : Sized {
67	/// Serialization error produced by deserialization routine.
68	type Error: From<io::Error>;
69	/// Deserialize type from serial i/o
70	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
71}
72
73/// Serialization to serial i/o. Takes self by value to consume less memory
74/// (parity-wasm IR is being partially freed by filling the result buffer).
75pub trait Serialize {
76	/// Serialization error produced by serialization routine.
77	type Error: From<io::Error>;
78	/// Serialize type to serial i/o
79	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
80}
81
82/// Deserialization/serialization error
83#[derive(Debug, Clone)]
84pub enum Error {
85	/// Unexpected end of input
86	UnexpectedEof,
87	/// Invalid magic
88	InvalidMagic,
89	/// Unsupported version
90	UnsupportedVersion(u32),
91	/// Inconsistence between declared and actual length
92	InconsistentLength {
93		/// Expected length of the definition
94		expected: usize,
95		/// Actual length of the definition
96		actual: usize
97	},
98	/// Other static error
99	Other(&'static str),
100	/// Other allocated error
101	HeapOther(String),
102	/// Invalid/unknown value type declaration
103	UnknownValueType(i8),
104	/// Invalid/unknown table element type declaration
105	UnknownTableElementType(i8),
106	/// Non-utf8 string
107	NonUtf8String,
108	/// Unknown external kind code
109	UnknownExternalKind(u8),
110	/// Unknown internal kind code
111	UnknownInternalKind(u8),
112	/// Unknown opcode encountered
113	UnknownOpcode(u8),
114	/// Invalid VarUint1 value
115	InvalidVarUint1(u8),
116	/// Invalid VarInt32 value
117	InvalidVarInt32,
118	/// Invalid VarInt64 value
119	InvalidVarInt64,
120	/// Invalid VarUint32 value
121	InvalidVarUint32,
122	/// Invalid VarUint64 value
123	InvalidVarUint64,
124	/// Inconsistent metadata
125	InconsistentMetadata,
126	/// Invalid section id
127	InvalidSectionId(u8),
128	/// Sections are out of order
129	SectionsOutOfOrder,
130	/// Duplicated sections
131	DuplicatedSections(u8),
132	/// Invalid memory reference (should be 0)
133	InvalidMemoryReference(u8),
134	/// Invalid table reference (should be 0)
135	InvalidTableReference(u8),
136	/// Unknown function form (should be 0x60)
137	UnknownFunctionForm(u8),
138	/// Invalid varint7 (should be in -64..63 range)
139	InvalidVarInt7(u8),
140	/// Number of function body entries and signatures does not match
141	InconsistentCode,
142}
143
144impl fmt::Display for Error {
145	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
146		match *self {
147			Error::UnexpectedEof => write!(f, "Unexpected end of input"),
148			Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
149			Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
150			Error::InconsistentLength { expected, actual } => {
151				write!(f, "Expected length {}, found {}", expected, actual)
152			}
153			Error::Other(msg) => write!(f, "{}", msg),
154			Error::HeapOther(ref msg) => write!(f, "{}", msg),
155			Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
156			Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
157			Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
158			Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
159			Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
160			Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
161			Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
162			Error::InvalidVarInt7(val) => write!(f, "Not a signed 7-bit integer: {}", val),
163			Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
164			Error::InvalidVarUint32 => write!(f, "Not an unsigned 32-bit integer"),
165			Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
166			Error::InvalidVarUint64 => write!(f, "Not an unsigned 64-bit integer"),
167			Error::InconsistentMetadata =>  write!(f, "Inconsistent metadata"),
168			Error::InvalidSectionId(ref id) =>  write!(f, "Invalid section id: {}", id),
169			Error::SectionsOutOfOrder =>  write!(f, "Sections out of order"),
170			Error::DuplicatedSections(ref id) =>  write!(f, "Dupliated sections ({})", id),
171			Error::InvalidMemoryReference(ref mem_ref) =>  write!(f, "Invalid memory reference ({})", mem_ref),
172			Error::InvalidTableReference(ref table_ref) =>  write!(f, "Invalid table reference ({})", table_ref),
173			Error::UnknownFunctionForm(ref form) =>  write!(f, "Unknown function form ({})", form),
174			Error::InconsistentCode =>  write!(f, "Number of function body entries and signatures does not match"),
175		}
176	}
177}
178
179#[cfg(feature = "std")]
180impl ::std::error::Error for Error {
181	fn description(&self) -> &str {
182		match *self {
183			Error::UnexpectedEof => "Unexpected end of input",
184			Error::InvalidMagic => "Invalid magic number at start of file",
185			Error::UnsupportedVersion(_) => "Unsupported wasm version",
186			Error::InconsistentLength { .. } => "Inconsistent length",
187			Error::Other(msg) => msg,
188			Error::HeapOther(ref msg) => &msg[..],
189			Error::UnknownValueType(_) => "Invalid or unknown value type",
190			Error::UnknownTableElementType(_) => "Unknown table element type",
191			Error::NonUtf8String => "Non-UTF-8 string",
192			Error::UnknownExternalKind(_) => "Unknown external kind",
193			Error::UnknownInternalKind(_) => "Unknown internal kind",
194			Error::UnknownOpcode(_) => "Unknown opcode",
195			Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
196			Error::InvalidVarInt32 => "Not a signed 32-bit integer",
197			Error::InvalidVarInt7(_) => "Not a signed 7-bit integer",
198			Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
199			Error::InvalidVarInt64 => "Not a signed 64-bit integer",
200			Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
201			Error::InconsistentMetadata => "Inconsistent metadata",
202			Error::InvalidSectionId(_) =>  "Invalid section id",
203			Error::SectionsOutOfOrder =>  "Sections out of order",
204			Error::DuplicatedSections(_) =>  "Duplicated section",
205			Error::InvalidMemoryReference(_) =>  "Invalid memory reference",
206			Error::InvalidTableReference(_) =>  "Invalid table reference",
207			Error::UnknownFunctionForm(_) =>  "Unknown function form",
208			Error::InconsistentCode =>  "Number of function body entries and signatures does not match",
209		}
210	}
211}
212
213impl From<io::Error> for Error {
214	fn from(err: io::Error) -> Self {
215		Error::HeapOther(format!("I/O Error: {:?}", err))
216	}
217}
218
219/// Unparsed part of the module/section
220pub struct Unparsed(pub Vec<u8>);
221
222impl Deserialize for Unparsed {
223	type Error = Error;
224
225	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
226		let len = VarUint32::deserialize(reader)?.into();
227		let mut vec = vec![0u8; len];
228		reader.read(&mut vec[..])?;
229		Ok(Unparsed(vec))
230	}
231}
232
233impl From<Unparsed> for Vec<u8> {
234	fn from(u: Unparsed) -> Vec<u8> {
235		u.0
236	}
237}
238
239/// Deserialize deserializable type from buffer.
240pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
241	let mut reader = io::Cursor::new(contents);
242	let result = T::deserialize(&mut reader)?;
243	if reader.position() != contents.len() {
244		// It's a TrailingData, since if there is not enough data then
245		// UnexpectedEof must have been returned earlier in T::deserialize.
246		return Err(io::Error::TrailingData.into())
247	}
248	Ok(result)
249}
250
251/// Create buffer with serialized value.
252pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
253	let mut buf = Vec::new();
254	val.serialize(&mut buf)?;
255	Ok(buf)
256}
257
258/// Deserialize module from the file.
259#[cfg(feature = "std")]
260pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
261	let mut f = ::std::fs::File::open(p)
262		.map_err(|e| Error::HeapOther(format!("Can't read from the file: {:?}", e)))?;
263
264	Module::deserialize(&mut f)
265}
266
267/// Serialize module to the file
268#[cfg(feature = "std")]
269pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error> {
270	let mut io = ::std::fs::File::create(p)
271		.map_err(|e|
272			Error::HeapOther(format!("Can't create the file: {:?}", e))
273		)?;
274
275	module.serialize(&mut io)?;
276	Ok(())
277}