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}