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 },
210 Error::InvalidTableReference(ref table_ref) => {
211 write!(f, "Invalid table reference ({})", table_ref)
212 },
213 Error::InvalidLimitsFlags(ref flags) => write!(f, "Invalid limits flags ({})", flags),
214 Error::UnknownFunctionForm(ref form) => write!(f, "Unknown function form ({})", form),
215 Error::InconsistentCode => {
216 write!(f, "Number of function body entries and signatures does not match")
217 },
218 Error::InvalidSegmentFlags(n) => write!(f, "Invalid segment flags: {}", n),
219 Error::TooManyLocals => write!(f, "Too many locals"),
220 Error::DuplicatedNameSubsections(n) => write!(f, "Duplicated name subsections: {}", n),
221 Error::UnknownNameSubsectionType(n) => write!(f, "Unknown subsection type: {}", n),
222 }
223 }
224}
225
226#[cfg(feature = "std")]
227impl ::std::error::Error for Error {
228 fn description(&self) -> &str {
229 match *self {
230 Error::UnexpectedEof => "Unexpected end of input",
231 Error::InvalidMagic => "Invalid magic number at start of file",
232 Error::UnsupportedVersion(_) => "Unsupported wasm version",
233 Error::InconsistentLength { .. } => "Inconsistent length",
234 Error::Other(msg) => msg,
235 Error::HeapOther(ref msg) => &msg[..],
236 Error::UnknownValueType(_) => "Invalid or unknown value type",
237 Error::UnknownBlockType(_) => "Invalid or unknown block type",
238 Error::UnknownTableElementType(_) => "Unknown table element type",
239 Error::NonUtf8String => "Non-UTF-8 string",
240 Error::UnknownExternalKind(_) => "Unknown external kind",
241 Error::UnknownInternalKind(_) => "Unknown internal kind",
242 Error::UnknownOpcode(_) => "Unknown opcode",
243 #[cfg(feature = "simd")]
244 Error::UnknownSimdOpcode(_) => "Unknown SIMD opcode",
245 Error::InvalidVarUint1(_) => "Not an unsigned 1-bit integer",
246 Error::InvalidVarInt32 => "Not a signed 32-bit integer",
247 Error::InvalidVarInt7(_) => "Not a signed 7-bit integer",
248 Error::InvalidVarUint32 => "Not an unsigned 32-bit integer",
249 Error::InvalidVarInt64 => "Not a signed 64-bit integer",
250 Error::InvalidVarUint64 => "Not an unsigned 64-bit integer",
251 Error::InconsistentMetadata => "Inconsistent metadata",
252 Error::InvalidSectionId(_) => "Invalid section id",
253 Error::SectionsOutOfOrder => "Sections out of order",
254 Error::DuplicatedSections(_) => "Duplicated section",
255 Error::InvalidMemoryReference(_) => "Invalid memory reference",
256 Error::InvalidTableReference(_) => "Invalid table reference",
257 Error::InvalidLimitsFlags(_) => "Invalid limits flags",
258 Error::UnknownFunctionForm(_) => "Unknown function form",
259 Error::InconsistentCode =>
260 "Number of function body entries and signatures does not match",
261 Error::InvalidSegmentFlags(_) => "Invalid segment flags",
262 Error::TooManyLocals => "Too many locals",
263 Error::DuplicatedNameSubsections(_) => "Duplicated name subsections",
264 Error::UnknownNameSubsectionType(_) => "Unknown name subsections type",
265 }
266 }
267}
268
269impl From<io::Error> for Error {
270 fn from(err: io::Error) -> Self {
271 Error::HeapOther(format!("I/O Error: {:?}", err))
272 }
273}
274
275impl From<(Vec<(usize, Error)>, Module)> for Error {
277 fn from(err: (Vec<(usize, Error)>, Module)) -> Self {
278 let ret = err.0.iter().fold(String::new(), |mut acc, item| {
279 acc.push_str(&format!("In section {}: {}\n", item.0, item.1));
280 acc
281 });
282 Error::HeapOther(ret)
283 }
284}
285
286pub struct Unparsed(pub Vec<u8>);
288
289impl Deserialize for Unparsed {
290 type Error = Error;
291
292 fn deserialize<R: io::Read>(reader: &mut R) -> Result<Self, Self::Error> {
293 let len = VarUint32::deserialize(reader)?.into();
294 let mut vec = vec![0u8; len];
295 reader.read(&mut vec[..])?;
296 Ok(Unparsed(vec))
297 }
298}
299
300impl From<Unparsed> for Vec<u8> {
301 fn from(u: Unparsed) -> Vec<u8> {
302 u.0
303 }
304}
305
306pub fn deserialize_buffer<T: Deserialize>(contents: &[u8]) -> Result<T, T::Error> {
308 let mut reader = io::Cursor::new(contents);
309 let result = T::deserialize(&mut reader)?;
310 if reader.position() != contents.len() {
311 return Err(io::Error::TrailingData.into());
314 }
315 Ok(result)
316}
317
318pub fn serialize<T: Serialize>(val: T) -> Result<Vec<u8>, T::Error> {
320 let mut buf = Vec::new();
321 val.serialize(&mut buf)?;
322 Ok(buf)
323}
324
325#[cfg(feature = "std")]
327pub fn deserialize_file<P: AsRef<::std::path::Path>>(p: P) -> Result<Module, Error> {
328 let mut f = ::std::fs::File::open(p)
329 .map_err(|e| Error::HeapOther(format!("Can't read from the file: {:?}", e)))?;
330
331 Module::deserialize(&mut f)
332}
333
334#[cfg(feature = "std")]
336pub fn serialize_to_file<P: AsRef<::std::path::Path>>(p: P, module: Module) -> Result<(), Error> {
337 let mut io = ::std::fs::File::create(p)
338 .map_err(|e| Error::HeapOther(format!("Can't create the file: {:?}", e)))?;
339
340 module.serialize(&mut io)?;
341 Ok(())
342}