1mod builder;
2mod data;
3mod element;
4mod export;
5mod global;
6mod import;
7mod init_expr;
8mod instantiate;
9mod parser;
10mod read;
11pub(crate) mod utils;
12
13use self::{
14 builder::ModuleBuilder,
15 export::ExternIdx,
16 global::Global,
17 import::{ExternTypeIdx, Import},
18 parser::ModuleParser,
19};
20pub(crate) use self::{
21 data::{DataSegment, DataSegments, InitDataSegment, PassiveDataSegmentBytes},
22 element::{ElementSegment, ElementSegmentItems, ElementSegmentKind},
23 init_expr::ConstExpr,
24 utils::WasmiValueType,
25};
26pub use self::{
27 export::{ExportType, FuncIdx, MemoryIdx, ModuleExportsIter, TableIdx},
28 global::GlobalIdx,
29 import::{FuncTypeIdx, ImportName},
30 instantiate::{InstancePre, InstantiationError},
31 read::{Read, ReadError},
32};
33use crate::{
34 collections::Map,
35 engine::{CompiledFunc, DedupFuncType, EngineWeak},
36 Engine,
37 Error,
38 ExternType,
39 FuncType,
40 GlobalType,
41 MemoryType,
42 TableType,
43};
44use core::{iter, slice::Iter as SliceIter};
45use std::{boxed::Box, collections::BTreeMap, sync::Arc};
46use wasmparser::{FuncValidatorAllocations, Parser, ValidPayload, Validator};
47
48#[derive(Debug)]
50pub struct Module {
51 engine: Engine,
52 header: ModuleHeader,
53 data_segments: DataSegments,
54}
55
56#[derive(Debug, Clone)]
58pub struct ModuleHeader {
59 inner: Arc<ModuleHeaderInner>,
60}
61
62#[derive(Debug)]
63struct ModuleHeaderInner {
64 engine: EngineWeak,
65 func_types: Arc<[DedupFuncType]>,
66 imports: ModuleImports,
67 funcs: Box<[DedupFuncType]>,
68 tables: Box<[TableType]>,
69 memories: Box<[MemoryType]>,
70 globals: Box<[GlobalType]>,
71 globals_init: Box<[ConstExpr]>,
72 exports: Map<Box<str>, ExternIdx>,
73 start: Option<FuncIdx>,
74 compiled_funcs: Box<[CompiledFunc]>,
75 compiled_funcs_idx: BTreeMap<CompiledFunc, FuncIdx>,
76 element_segments: Box<[ElementSegment]>,
77}
78
79impl ModuleHeader {
80 pub fn engine(&self) -> &EngineWeak {
82 &self.inner.engine
83 }
84
85 pub fn get_func_type(&self, func_type_idx: FuncTypeIdx) -> &DedupFuncType {
87 &self.inner.func_types[func_type_idx.into_u32() as usize]
88 }
89
90 pub fn get_type_of_func(&self, func_idx: FuncIdx) -> &DedupFuncType {
92 &self.inner.funcs[func_idx.into_u32() as usize]
93 }
94
95 pub fn get_type_of_global(&self, global_idx: GlobalIdx) -> &GlobalType {
97 &self.inner.globals[global_idx.into_u32() as usize]
98 }
99
100 pub fn get_compiled_func(&self, func_idx: FuncIdx) -> Option<CompiledFunc> {
104 let index = func_idx.into_u32() as usize;
105 let len_imported = self.inner.imports.len_funcs();
106 let index = index.checked_sub(len_imported)?;
107 Some(self.inner.compiled_funcs[index])
110 }
111
112 pub fn get_func_index(&self, func: CompiledFunc) -> Option<FuncIdx> {
114 self.inner.compiled_funcs_idx.get(&func).copied()
115 }
116
117 pub fn get_global(&self, global_idx: GlobalIdx) -> (&GlobalType, Option<&ConstExpr>) {
119 let index = global_idx.into_u32() as usize;
120 let len_imports = self.inner.imports.len_globals();
121 let global_type = self.get_type_of_global(global_idx);
122 if index < len_imports {
123 (global_type, None)
125 } else {
126 let init_expr = &self.inner.globals_init[index - len_imports];
128 (global_type, Some(init_expr))
129 }
130 }
131}
132
133pub(crate) const DEFAULT_MEMORY_INDEX: u32 = 0;
135
136#[derive(Debug)]
138pub enum Imported {
139 Func(ImportName),
143 Table(ImportName),
147 Memory(ImportName),
151 Global(ImportName),
153}
154
155#[derive(Debug)]
157pub struct ModuleImports {
158 items: Box<[Imported]>,
160 len_funcs: usize,
164 len_globals: usize,
166 len_memories: usize,
170 len_tables: usize,
174}
175
176impl ModuleImports {
177 pub fn len_globals(&self) -> usize {
179 self.len_globals
180 }
181
182 pub fn len_funcs(&self) -> usize {
184 self.len_funcs
185 }
186}
187
188impl Module {
189 pub fn new(engine: &Engine, wasm: &[u8]) -> Result<Self, Error> {
204 ModuleParser::new(engine).parse_buffered(wasm)
205 }
206
207 pub fn new_streaming(engine: &Engine, stream: impl Read) -> Result<Self, Error> {
222 ModuleParser::new(engine).parse_streaming(stream)
223 }
224
225 pub unsafe fn new_unchecked(engine: &Engine, wasm: &[u8]) -> Result<Self, Error> {
246 let parser = ModuleParser::new(engine);
247 unsafe { parser.parse_buffered_unchecked(wasm) }
248 }
249
250 pub unsafe fn new_streaming_unchecked(
271 engine: &Engine,
272 stream: impl Read,
273 ) -> Result<Self, Error> {
274 let parser = ModuleParser::new(engine);
275 unsafe { parser.parse_streaming_unchecked(stream) }
276 }
277
278 pub fn engine(&self) -> &Engine {
280 &self.engine
281 }
282
283 pub fn validate(engine: &Engine, wasm: &[u8]) -> Result<(), Error> {
304 let mut validator = Validator::new_with_features(engine.config().wasm_features());
305 for payload in Parser::new(0).parse_all(wasm) {
306 let payload = payload?;
307 if let ValidPayload::Func(func_to_validate, func_body) = validator.payload(&payload)? {
308 func_to_validate
309 .into_validator(FuncValidatorAllocations::default())
310 .validate(&func_body)?;
311 }
312 }
313 Ok(())
314 }
315
316 pub(crate) fn len_funcs(&self) -> usize {
318 self.header.inner.funcs.len()
319 }
320 pub(crate) fn len_tables(&self) -> usize {
322 self.header.inner.tables.len()
323 }
324 pub(crate) fn len_memories(&self) -> usize {
326 self.header.inner.memories.len()
327 }
328 pub(crate) fn len_globals(&self) -> usize {
330 self.header.inner.globals.len()
331 }
332
333 pub(crate) fn func_types_cloned(&self) -> Arc<[DedupFuncType]> {
339 self.header.inner.func_types.clone()
340 }
341
342 pub fn imports(&self) -> ModuleImportsIter {
344 let len_imported_funcs = self.header.inner.imports.len_funcs;
345 let len_imported_globals = self.header.inner.imports.len_globals;
346 ModuleImportsIter {
347 engine: self.engine(),
348 names: self.header.inner.imports.items.iter(),
349 funcs: self.header.inner.funcs[..len_imported_funcs].iter(),
350 tables: self.header.inner.tables.iter(),
351 memories: self.header.inner.memories.iter(),
352 globals: self.header.inner.globals[..len_imported_globals].iter(),
353 }
354 }
355
356 pub(crate) fn internal_funcs(&self) -> InternalFuncsIter {
360 let len_imported = self.header.inner.imports.len_funcs;
361 let funcs = &self.header.inner.funcs[len_imported..];
365 let compiled_funcs = &self.header.inner.compiled_funcs[..];
366 assert_eq!(funcs.len(), compiled_funcs.len());
367 InternalFuncsIter {
368 iter: funcs.iter().zip(compiled_funcs),
369 }
370 }
371
372 fn internal_memories(&self) -> SliceIter<MemoryType> {
374 let len_imported = self.header.inner.imports.len_memories;
375 let memories = &self.header.inner.memories[len_imported..];
379 memories.iter()
380 }
381
382 fn internal_tables(&self) -> SliceIter<TableType> {
384 let len_imported = self.header.inner.imports.len_tables;
385 let tables = &self.header.inner.tables[len_imported..];
389 tables.iter()
390 }
391
392 fn internal_globals(&self) -> InternalGlobalsIter {
394 let len_imported = self.header.inner.imports.len_globals;
395 let globals = self.header.inner.globals[len_imported..].iter();
399 let global_inits = self.header.inner.globals_init.iter();
400 InternalGlobalsIter {
401 iter: globals.zip(global_inits),
402 }
403 }
404
405 pub fn exports(&self) -> ModuleExportsIter {
407 ModuleExportsIter::new(self)
408 }
409
410 pub fn get_export(&self, name: &str) -> Option<ExternType> {
418 let idx = self.header.inner.exports.get(name).copied()?;
419 let ty = self.get_extern_type(idx);
420 Some(ty)
421 }
422
423 fn get_extern_type(&self, idx: ExternIdx) -> ExternType {
429 match idx {
430 ExternIdx::Func(index) => {
431 let dedup = &self.header.inner.funcs[index.into_u32() as usize];
432 let func_type = self.engine().resolve_func_type(dedup, Clone::clone);
433 ExternType::Func(func_type)
434 }
435 ExternIdx::Table(index) => {
436 let table_type = self.header.inner.tables[index.into_u32() as usize];
437 ExternType::Table(table_type)
438 }
439 ExternIdx::Memory(index) => {
440 let memory_type = self.header.inner.memories[index.into_u32() as usize];
441 ExternType::Memory(memory_type)
442 }
443 ExternIdx::Global(index) => {
444 let global_type = self.header.inner.globals[index.into_u32() as usize];
445 ExternType::Global(global_type)
446 }
447 }
448 }
449}
450
451#[derive(Debug)]
453pub struct ModuleImportsIter<'a> {
454 engine: &'a Engine,
455 names: SliceIter<'a, Imported>,
456 funcs: SliceIter<'a, DedupFuncType>,
457 tables: SliceIter<'a, TableType>,
458 memories: SliceIter<'a, MemoryType>,
459 globals: SliceIter<'a, GlobalType>,
460}
461
462impl<'a> Iterator for ModuleImportsIter<'a> {
463 type Item = ImportType<'a>;
464
465 fn next(&mut self) -> Option<Self::Item> {
466 let import = match self.names.next() {
467 None => return None,
468 Some(imported) => match imported {
469 Imported::Func(name) => {
470 let func_type = self.funcs.next().unwrap_or_else(|| {
471 panic!("unexpected missing imported function for {name:?}")
472 });
473 let func_type = self.engine.resolve_func_type(func_type, FuncType::clone);
474 ImportType::new(name, func_type)
475 }
476 Imported::Table(name) => {
477 let table_type = self.tables.next().unwrap_or_else(|| {
478 panic!("unexpected missing imported table for {name:?}")
479 });
480 ImportType::new(name, *table_type)
481 }
482 Imported::Memory(name) => {
483 let memory_type = self.memories.next().unwrap_or_else(|| {
484 panic!("unexpected missing imported linear memory for {name:?}")
485 });
486 ImportType::new(name, *memory_type)
487 }
488 Imported::Global(name) => {
489 let global_type = self.globals.next().unwrap_or_else(|| {
490 panic!("unexpected missing imported global variable for {name:?}")
491 });
492 ImportType::new(name, *global_type)
493 }
494 },
495 };
496 Some(import)
497 }
498
499 fn size_hint(&self) -> (usize, Option<usize>) {
500 self.names.size_hint()
501 }
502}
503
504impl<'a> ExactSizeIterator for ModuleImportsIter<'a> {
505 fn len(&self) -> usize {
506 ExactSizeIterator::len(&self.names)
507 }
508}
509
510#[derive(Debug)]
516pub struct ImportType<'module> {
517 name: &'module ImportName,
519 ty: ExternType,
521}
522
523impl<'module> ImportType<'module> {
524 pub(crate) fn new<T>(name: &'module ImportName, ty: T) -> Self
526 where
527 T: Into<ExternType>,
528 {
529 Self {
530 name,
531 ty: ty.into(),
532 }
533 }
534
535 pub(crate) fn import_name(&self) -> &ImportName {
537 self.name
538 }
539
540 pub fn module(&self) -> &'module str {
542 self.name.module()
543 }
544
545 pub fn name(&self) -> &'module str {
547 self.name.name()
548 }
549
550 pub fn ty(&self) -> &ExternType {
552 &self.ty
553 }
554}
555
556#[derive(Debug)]
558pub struct InternalFuncsIter<'a> {
559 iter: iter::Zip<SliceIter<'a, DedupFuncType>, SliceIter<'a, CompiledFunc>>,
560}
561
562impl<'a> Iterator for InternalFuncsIter<'a> {
563 type Item = (DedupFuncType, CompiledFunc);
564
565 fn next(&mut self) -> Option<Self::Item> {
566 self.iter
567 .next()
568 .map(|(func_type, func_body)| (*func_type, *func_body))
569 }
570
571 fn size_hint(&self) -> (usize, Option<usize>) {
572 self.iter.size_hint()
573 }
574}
575
576impl<'a> ExactSizeIterator for InternalFuncsIter<'a> {
577 fn len(&self) -> usize {
578 ExactSizeIterator::len(&self.iter)
579 }
580}
581
582#[derive(Debug)]
584pub struct InternalGlobalsIter<'a> {
585 iter: iter::Zip<SliceIter<'a, GlobalType>, SliceIter<'a, ConstExpr>>,
586}
587
588impl<'a> Iterator for InternalGlobalsIter<'a> {
589 type Item = (&'a GlobalType, &'a ConstExpr);
590
591 fn next(&mut self) -> Option<Self::Item> {
592 self.iter.next()
593 }
594
595 fn size_hint(&self) -> (usize, Option<usize>) {
596 self.iter.size_hint()
597 }
598}
599
600impl<'a> ExactSizeIterator for InternalGlobalsIter<'a> {
601 fn len(&self) -> usize {
602 ExactSizeIterator::len(&self.iter)
603 }
604}