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