1use crate::io;
4use alloc::{string::String, vec::Vec};
5
6use core::fmt;
7
8macro_rules! buffered_read {
9 ($buffer_size: expr, $length: expr, $reader: expr) => {{
10 let mut vec_buf = Vec::new();
11 let mut total_read = 0;
12 let mut buf = [0u8; $buffer_size];
13 while total_read < $length {
14 let next_to_read = if $length - total_read > $buffer_size {
15 $buffer_size
16 } else {
17 $length - total_read
18 };
19 $reader.read(&mut buf[0..next_to_read])?;
20 vec_buf.extend_from_slice(&buf[0..next_to_read]);
21 total_read += next_to_read;
22 }
23 vec_buf
24 }};
25}
26
27mod export_entry;
28mod func;
29mod global_entry;
30mod import_entry;
31mod index_map;
32mod module;
33mod name_section;
34mod ops;
35mod primitives;
36mod reloc_section;
37mod section;
38mod segment;
39mod types;
40
41pub use self::{
42 export_entry::{ExportEntry, Internal},
43 global_entry::GlobalEntry,
44 import_entry::{External, GlobalType, ImportEntry, MemoryType, ResizableLimits, TableType},
45 module::{peek_size, ImportCountType, Module},
46 ops::{opcodes, BrTableData, InitExpr, Instruction, Instructions},
47 primitives::{
48 CountedList, CountedListWriter, CountedWriter, Uint32, Uint64, Uint8, VarInt32, VarInt64,
49 VarInt7, VarUint1, VarUint32, VarUint64, VarUint7,
50 },
51 section::{
52 CodeSection, CustomSection, DataSection, ElementSection, ExportSection, FunctionSection,
53 GlobalSection, ImportSection, MemorySection, Section, TableSection, TypeSection,
54 },
55 types::{BlockType, FunctionType, TableElementType, Type, ValueType},
56};
57
58#[cfg(feature = "atomics")]
59pub use self::ops::AtomicsInstruction;
60
61#[cfg(feature = "simd")]
62pub use self::ops::SimdInstruction;
63
64#[cfg(feature = "sign_ext")]
65pub use self::ops::SignExtInstruction;
66
67#[cfg(feature = "bulk")]
68pub use self::ops::BulkInstruction;
69
70#[cfg(any(feature = "simd", feature = "atomics"))]
71pub use self::ops::MemArg;
72
73pub use self::{
74 func::{Func, FuncBody, Local},
75 index_map::IndexMap,
76 name_section::{
77 FunctionNameSubsection, LocalNameSubsection, ModuleNameSubsection, NameMap, NameSection,
78 },
79 reloc_section::{RelocSection, RelocationEntry},
80 segment::{DataSegment, ElementSegment},
81};
82
83pub trait Deserialize: Sized {
85 type Error: From<io::Error>;
87 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error>;
89}
90
91pub trait Serialize {
94 type Error: From<io::Error>;
96 fn serialize<W: io::Write>(self, writer: &mut W) -> Result<(), Self::Error>;
98}
99
100#[derive(Debug, Clone)]
102pub enum Error {
103 UnexpectedEof,
105 InvalidMagic,
107 UnsupportedVersion(u32),
109 InconsistentLength {
111 expected: usize,
113 actual: usize,
115 },
116 Other(&'static str),
118 HeapOther(String),
120 UnknownValueType(i8),
122 UnknownBlockType(i32),
124 UnknownTableElementType(i8),
126 NonUtf8String,
128 UnknownExternalKind(u8),
130 UnknownInternalKind(u8),
132 UnknownOpcode(u8),
134 #[cfg(feature = "simd")]
135 UnknownSimdOpcode(u32),
137 InvalidVarUint1(u8),
139 InvalidVarInt32,
141 InvalidVarInt64,
143 InvalidVarUint32,
145 InvalidVarUint64,
147 InconsistentMetadata,
149 InvalidSectionId(u8),
151 SectionsOutOfOrder,
153 DuplicatedSections(u8),
155 InvalidMemoryReference(u8),
157 InvalidTableReference(u8),
159 InvalidLimitsFlags(u8),
161 UnknownFunctionForm(u8),
163 InvalidVarInt7(u8),
165 InconsistentCode,
167 InvalidSegmentFlags(u32),
169 TooManyLocals,
171 DuplicatedNameSubsections(u8),
173 UnknownNameSubsectionType(u8),
175}
176
177impl fmt::Display for Error {
178 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
179 match *self {
180 Error::UnexpectedEof => write!(f, "Unexpected end of input"),
181 Error::InvalidMagic => write!(f, "Invalid magic number at start of file"),
182 Error::UnsupportedVersion(v) => write!(f, "Unsupported wasm version {}", v),
183 Error::InconsistentLength { expected, actual } => {
184 write!(f, "Expected length {}, found {}", expected, actual)
185 },
186 Error::Other(msg) => write!(f, "{}", msg),
187 Error::HeapOther(ref msg) => write!(f, "{}", msg),
188 Error::UnknownValueType(ty) => write!(f, "Invalid or unknown value type {}", ty),
189 Error::UnknownBlockType(ty) => write!(f, "Invalid or unknown block type {}", ty),
190 Error::UnknownTableElementType(ty) => write!(f, "Unknown table element type {}", ty),
191 Error::NonUtf8String => write!(f, "Non-UTF-8 string"),
192 Error::UnknownExternalKind(kind) => write!(f, "Unknown external kind {}", kind),
193 Error::UnknownInternalKind(kind) => write!(f, "Unknown internal kind {}", kind),
194 Error::UnknownOpcode(opcode) => write!(f, "Unknown opcode {}", opcode),
195 #[cfg(feature = "simd")]
196 Error::UnknownSimdOpcode(opcode) => write!(f, "Unknown SIMD opcode {}", opcode),
197 Error::InvalidVarUint1(val) => write!(f, "Not an unsigned 1-bit integer: {}", val),
198 Error::InvalidVarInt7(val) => write!(f, "Not a signed 7-bit integer: {}", val),
199 Error::InvalidVarInt32 => write!(f, "Not a signed 32-bit integer"),
200 Error::InvalidVarUint32 => write!(f, "Not an unsigned 32-bit integer"),
201 Error::InvalidVarInt64 => write!(f, "Not a signed 64-bit integer"),
202 Error::InvalidVarUint64 => write!(f, "Not an unsigned 64-bit integer"),
203 Error::InconsistentMetadata => write!(f, "Inconsistent metadata"),
204 Error::InvalidSectionId(ref id) => write!(f, "Invalid section id: {}", id),
205 Error::SectionsOutOfOrder => write!(f, "Sections out of order"),
206 Error::DuplicatedSections(ref id) => write!(f, "Duplicated sections ({})", id),
207 Error::InvalidMemoryReference(ref mem_ref) =>
208 write!(f, "Invalid memory reference ({})", mem_ref),
209 Error::InvalidTableReference(ref table_ref) =>
210 write!(f, "Invalid table reference ({})", table_ref),
211 Error::InvalidLimitsFlags(ref flags) => write!(f, "Invalid limits flags ({})", flags),
212 Error::UnknownFunctionForm(ref form) => write!(f, "Unknown function form ({})", form),
213 Error::InconsistentCode =>
214 write!(f, "Number of function body entries and signatures does not match"),
215 Error::InvalidSegmentFlags(n) => write!(f, "Invalid segment flags: {}", n),
216 Error::TooManyLocals => write!(f, "Too many locals"),
217 Error::DuplicatedNameSubsections(n) => write!(f, "Duplicated name subsections: {}", n),
218 Error::UnknownNameSubsectionType(n) => write!(f, "Unknown subsection type: {}", n),
219 }
220 }
221}
222
223#[cfg(feature = "std")]
224impl ::std::error::Error for Error {
225 fn description(&self) -> &str {
226 match *self {
227 Error::UnexpectedEof => "Unexpected end of input",
228 Error::InvalidMagic => "Invalid magic number at start of file",
229 Error::UnsupportedVersion(_) => "Unsupported wasm version",
230 Error::InconsistentLength { .. } => "Inconsistent length",
231 Error::Other(msg) => msg,
232 Error::HeapOther(ref msg) => &msg[..],
233 Error::UnknownValueType(_) => "Invalid or unknown value type",
234 Error::UnknownBlockType(_) => "Invalid or unknown block type",
235 Error::UnknownTableElementType(_) => "Unknown table element type",
236 Error::NonUtf8String => "Non-UTF-8 string",
237 Error::UnknownExternalKind(_) => "Unknown external kind",
238 Error::UnknownInternalKind(_) => "Unknown internal kind",
239 Error::UnknownOpcode(_) => "Unknown opcode",
240 #[cfg(feature = "simd")]
241 Error::UnknownSimdOpcode(_) => "Unknown SIMD opcode",
242 Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
243 Error::InvalidVarInt32 => "Not a signed 32-bit integer",
244 Error::InvalidVarInt7(_) => "Not a signed 7-bit integer",
245 Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
246 Error::InvalidVarInt64 => "Not a signed 64-bit integer",
247 Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
248 Error::InconsistentMetadata => "Inconsistent metadata",
249 Error::InvalidSectionId(_) => "Invalid section id",
250 Error::SectionsOutOfOrder => "Sections out of order",
251 Error::DuplicatedSections(_) => "Duplicated section",
252 Error::InvalidMemoryReference(_) => "Invalid memory reference",
253 Error::InvalidTableReference(_) => "Invalid table reference",
254 Error::InvalidLimitsFlags(_) => "Invalid limits flags",
255 Error::UnknownFunctionForm(_) => "Unknown function form",
256 Error::InconsistentCode =>
257 "Number of function body entries and signatures does not match",
258 Error::InvalidSegmentFlags(_) => "Invalid segment flags",
259 Error::TooManyLocals => "Too many locals",
260 Error::DuplicatedNameSubsections(_) => "Duplicated name subsections",
261 Error::UnknownNameSubsectionType(_) => "Unknown name subsections type",
262 }
263 }
264}
265
266impl From<io::Error> for Error {
267 fn from(err: io::Error) -> Self {
268 Error::HeapOther(format!("I/O Error: {:?}", err))
269 }
270}
271
272impl From<(Vec<(usize, Error)>, Module)> for Error {
274 fn from(err: (Vec<(usize, Error)>, Module)) -> Self {
275 let ret = err.0.iter().fold(String::new(), |mut acc, item| {
276 acc.push_str(&format!("In section {}: {}\n", item.0, item.1));
277 acc
278 });
279 Error::HeapOther(ret)
280 }
281}
282
283pub struct Unparsed(pub Vec<u8>);
285
286impl Deserialize for Unparsed {
287 type Error = Error;
288
289 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
290 let len = VarUint32::deserialize(reader)?.into();
291 let mut vec = vec![0u8; len];
292 reader.read(&mut vec[..])?;
293 Ok(Unparsed(vec))
294 }
295}
296
297impl From<Unparsed> for Vec<u8> {
298 fn from(u: Unparsed) -> Vec<u8> {
299 u.0
300 }
301}
302
303pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
305 let mut reader = io::Cursor::new(contents);
306 let result = T::deserialize(&mut reader)?;
307 if reader.position() != contents.len() {
308 return Err(io::Error::TrailingData.into())
311 }
312 Ok(result)
313}
314
315pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
317 let mut buf = Vec::new();
318 val.serialize(&mut buf)?;
319 Ok(buf)
320}
321
322#[cfg(feature = "std")]
324pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
325 let mut f = ::std::fs::File::open(p)
326 .map_err(|e| Error::HeapOther(format!("Can't read from the file: {:?}", e)))?;
327
328 Module::deserialize(&mut f)
329}
330
331#[cfg(feature = "std")]
333pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error> {
334 let mut io = ::std::fs::File::create(p)
335 .map_err(|e| Error::HeapOther(format!("Can't create the file: {:?}", e)))?;
336
337 module.serialize(&mut io)?;
338 Ok(())
339}