1use 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
65pub trait Deserialize : Sized {
67	type Error: From<io::Error>;
69	fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
71}
72
73pub trait Serialize {
76	type Error: From<io::Error>;
78	fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
80}
81
82#[derive(Debug, Clone)]
84pub enum Error {
85	UnexpectedEof,
87	InvalidMagic,
89	UnsupportedVersion(u32),
91	InconsistentLength {
93		expected: usize,
95		actual: usize
97	},
98	Other(&'static str),
100	HeapOther(String),
102	UnknownValueType(i8),
104	UnknownTableElementType(i8),
106	NonUtf8String,
108	UnknownExternalKind(u8),
110	UnknownInternalKind(u8),
112	UnknownOpcode(u8),
114	InvalidVarUint1(u8),
116	InvalidVarInt32,
118	InvalidVarInt64,
120	InvalidVarUint32,
122	InvalidVarUint64,
124	InconsistentMetadata,
126	InvalidSectionId(u8),
128	SectionsOutOfOrder,
130	DuplicatedSections(u8),
132	InvalidMemoryReference(u8),
134	InvalidTableReference(u8),
136	UnknownFunctionForm(u8),
138	InvalidVarInt7(u8),
140	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
219pub 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
239pub 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		return Err(io::Error::TrailingData.into())
247	}
248	Ok(result)
249}
250
251pub 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#[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#[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}