1use alloc::{string::String, vec::Vec};
4use crate::io;
5
6use core::fmt;
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, BrTableData};
54
55#[cfg(feature="atomics")]
56pub use self::ops::AtomicsInstruction;
57
58#[cfg(feature="simd")]
59pub use self::ops::SimdInstruction;
60
61#[cfg(feature="sign_ext")]
62pub use self::ops::SignExtInstruction;
63
64#[cfg(feature="bulk")]
65pub use self::ops::BulkInstruction;
66
67#[cfg(any(feature="simd", feature="atomics"))]
68pub use self::ops::MemArg;
69
70pub use self::func::{Func, FuncBody, Local};
71pub use self::segment::{ElementSegment, DataSegment};
72pub use self::index_map::IndexMap;
73pub use self::name_section::{
74 NameMap, NameSection, ModuleNameSubsection, FunctionNameSubsection,
75 LocalNameSubsection,
76};
77pub use self::reloc_section::{
78 RelocSection, RelocationEntry,
79};
80
81pub trait Deserialize : Sized {
83 type Error: From<io::Error>;
85 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
87}
88
89pub trait Serialize {
92 type Error: From<io::Error>;
94 fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
96}
97
98#[derive(Debug, Clone)]
100pub enum Error {
101 UnexpectedEof,
103 InvalidMagic,
105 UnsupportedVersion(u32),
107 InconsistentLength {
109 expected: usize,
111 actual: usize
113 },
114 Other(&'static str),
116 HeapOther(String),
118 UnknownValueType(i8),
120 UnknownTableElementType(i8),
122 NonUtf8String,
124 UnknownExternalKind(u8),
126 UnknownInternalKind(u8),
128 UnknownOpcode(u8),
130 #[cfg(feature="simd")]
131 UnknownSimdOpcode(u32),
133 InvalidVarUint1(u8),
135 InvalidVarInt32,
137 InvalidVarInt64,
139 InvalidVarUint32,
141 InvalidVarUint64,
143 InconsistentMetadata,
145 InvalidSectionId(u8),
147 SectionsOutOfOrder,
149 DuplicatedSections(u8),
151 InvalidMemoryReference(u8),
153 InvalidTableReference(u8),
155 InvalidLimitsFlags(u8),
157 UnknownFunctionForm(u8),
159 InvalidVarInt7(u8),
161 InconsistentCode,
163 InvalidSegmentFlags(u32),
165 TooManyLocals,
167 DuplicatedNameSubsections(u8),
169 UnknownNameSubsectionType(u8),
171}
172
173impl fmt::Display for Error {
174 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
175 match *self {
176 Error::UnexpectedEof => write!(f, "Unexpected end of input"),
177 Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
178 Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
179 Error::InconsistentLength { expected, actual } => {
180 write!(f, "Expected length {}, found {}", expected, actual)
181 }
182 Error::Other(msg) => write!(f, "{}", msg),
183 Error::HeapOther(ref msg) => write!(f, "{}", msg),
184 Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
185 Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
186 Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
187 Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
188 Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
189 Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
190 #[cfg(feature="simd")]
191 Error::UnknownSimdOpcode(opcode) => write!(f, "Unknown SIMD opcode {}", opcode),
192 Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
193 Error::InvalidVarInt7(val) => write!(f, "Not a signed 7-bit integer: {}", val),
194 Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
195 Error::InvalidVarUint32 => write!(f, "Not an unsigned 32-bit integer"),
196 Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
197 Error::InvalidVarUint64 => write!(f, "Not an unsigned 64-bit integer"),
198 Error::InconsistentMetadata => write!(f, "Inconsistent metadata"),
199 Error::InvalidSectionId(ref id) => write!(f, "Invalid section id: {}", id),
200 Error::SectionsOutOfOrder => write!(f, "Sections out of order"),
201 Error::DuplicatedSections(ref id) => write!(f, "Duplicated sections ({})", id),
202 Error::InvalidMemoryReference(ref mem_ref) => write!(f, "Invalid memory reference ({})", mem_ref),
203 Error::InvalidTableReference(ref table_ref) => write!(f, "Invalid table reference ({})", table_ref),
204 Error::InvalidLimitsFlags(ref flags) => write!(f, "Invalid limits flags ({})", flags),
205 Error::UnknownFunctionForm(ref form) => write!(f, "Unknown function form ({})", form),
206 Error::InconsistentCode => write!(f, "Number of function body entries and signatures does not match"),
207 Error::InvalidSegmentFlags(n) => write!(f, "Invalid segment flags: {}", n),
208 Error::TooManyLocals => write!(f, "Too many locals"),
209 Error::DuplicatedNameSubsections(n) => write!(f, "Duplicated name subsections: {}", n),
210 Error::UnknownNameSubsectionType(n) => write!(f, "Unknown subsection type: {}", n),
211 }
212 }
213}
214
215#[cfg(feature = "std")]
216impl ::std::error::Error for Error {
217 fn description(&self) -> &str {
218 match *self {
219 Error::UnexpectedEof => "Unexpected end of input",
220 Error::InvalidMagic => "Invalid magic number at start of file",
221 Error::UnsupportedVersion(_) => "Unsupported wasm version",
222 Error::InconsistentLength { .. } => "Inconsistent length",
223 Error::Other(msg) => msg,
224 Error::HeapOther(ref msg) => &msg[..],
225 Error::UnknownValueType(_) => "Invalid or unknown value type",
226 Error::UnknownTableElementType(_) => "Unknown table element type",
227 Error::NonUtf8String => "Non-UTF-8 string",
228 Error::UnknownExternalKind(_) => "Unknown external kind",
229 Error::UnknownInternalKind(_) => "Unknown internal kind",
230 Error::UnknownOpcode(_) => "Unknown opcode",
231 #[cfg(feature="simd")]
232 Error::UnknownSimdOpcode(_) => "Unknown SIMD opcode",
233 Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
234 Error::InvalidVarInt32 => "Not a signed 32-bit integer",
235 Error::InvalidVarInt7(_) => "Not a signed 7-bit integer",
236 Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
237 Error::InvalidVarInt64 => "Not a signed 64-bit integer",
238 Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
239 Error::InconsistentMetadata => "Inconsistent metadata",
240 Error::InvalidSectionId(_) => "Invalid section id",
241 Error::SectionsOutOfOrder => "Sections out of order",
242 Error::DuplicatedSections(_) => "Duplicated section",
243 Error::InvalidMemoryReference(_) => "Invalid memory reference",
244 Error::InvalidTableReference(_) => "Invalid table reference",
245 Error::InvalidLimitsFlags(_) => "Invalid limits flags",
246 Error::UnknownFunctionForm(_) => "Unknown function form",
247 Error::InconsistentCode => "Number of function body entries and signatures does not match",
248 Error::InvalidSegmentFlags(_) => "Invalid segment flags",
249 Error::TooManyLocals => "Too many locals",
250 Error::DuplicatedNameSubsections(_) => "Duplicated name subsections",
251 Error::UnknownNameSubsectionType(_) => "Unknown name subsections type",
252 }
253 }
254}
255
256impl From<io::Error> for Error {
257 fn from(err: io::Error) -> Self {
258 Error::HeapOther(format!("I/O Error: {:?}", err))
259 }
260}
261
262impl From<(Vec<(usize, Error)>, Module)> for Error {
264 fn from(err: (Vec<(usize, Error)>, Module)) -> Self {
265 let ret = err.0.iter()
266 .fold(
267 String::new(),
268 |mut acc, item| { acc.push_str(&format!("In section {}: {}\n", item.0, item.1)); acc }
269 );
270 Error::HeapOther(ret)
271 }
272}
273
274pub struct Unparsed(pub Vec<u8>);
276
277impl Deserialize for Unparsed {
278 type Error = Error;
279
280 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
281 let len = VarUint32::deserialize(reader)?.into();
282 let mut vec = vec![0u8; len];
283 reader.read(&mut vec[..])?;
284 Ok(Unparsed(vec))
285 }
286}
287
288impl From<Unparsed> for Vec<u8> {
289 fn from(u: Unparsed) -> Vec<u8> {
290 u.0
291 }
292}
293
294pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
296 let mut reader = io::Cursor::new(contents);
297 let result = T::deserialize(&mut reader)?;
298 if reader.position() != contents.len() {
299 return Err(io::Error::TrailingData.into())
302 }
303 Ok(result)
304}
305
306pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
308 let mut buf = Vec::new();
309 val.serialize(&mut buf)?;
310 Ok(buf)
311}
312
313#[cfg(feature = "std")]
315pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
316 let mut f = ::std::fs::File::open(p)
317 .map_err(|e| Error::HeapOther(format!("Can't read from the file: {:?}", e)))?;
318
319 Module::deserialize(&mut f)
320}
321
322#[cfg(feature = "std")]
324pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error> {
325 let mut io = ::std::fs::File::create(p)
326 .map_err(|e|
327 Error::HeapOther(format!("Can't create the file: {:?}", e))
328 )?;
329
330 module.serialize(&mut io)?;
331 Ok(())
332}