1mod builder;
2mod compile;
3mod data;
4mod element;
5mod error;
6mod export;
7mod global;
8mod import;
9mod init_expr;
10mod instantiate;
11mod parser;
12mod read;
13mod utils;
14
15pub(crate) use self::init_expr::InitExpr;
16use self::{
17 builder::ModuleBuilder,
18 data::DataSegment,
19 element::ElementSegment,
20 export::ExternIdx,
21 global::Global,
22 import::{ExternTypeIdx, Import},
23 parser::parse,
24 read::ReadError,
25};
26pub use self::{
27 builder::ModuleResources,
28 compile::BlockType,
29 error::ModuleError,
30 export::{ExportType, FuncIdx, MemoryIdx, ModuleExportsIter, TableIdx},
31 global::GlobalIdx,
32 import::{FuncTypeIdx, ImportName},
33 instantiate::{InstancePre, InstantiationError},
34 parser::ReusableAllocations,
35 read::Read,
36};
37use crate::{
38 engine::{DedupFuncType, FuncBody},
39 Engine,
40 Error,
41 ExternType,
42 FuncType,
43 GlobalType,
44 MemoryType,
45 TableType,
46};
47use alloc::{boxed::Box, collections::BTreeMap, sync::Arc, vec::Vec};
48use core::{iter, slice::Iter as SliceIter};
49
50#[derive(Debug)]
52pub struct Module {
53 engine: Engine,
54 func_types: Arc<[DedupFuncType]>,
55 imports: ModuleImports,
56 funcs: Box<[DedupFuncType]>,
57 tables: Box<[TableType]>,
58 memories: Box<[MemoryType]>,
59 globals: Box<[GlobalType]>,
60 globals_init: Box<[InitExpr]>,
61 exports: BTreeMap<Box<str>, ExternIdx>,
62 start: Option<FuncIdx>,
63 func_bodies: Box<[FuncBody]>,
64 element_segments: Box<[ElementSegment]>,
65 data_segments: Box<[DataSegment]>,
66}
67
68pub(crate) const DEFAULT_MEMORY_INDEX: u32 = 0;
70
71pub(crate) const DEFAULT_TABLE_INDEX: u32 = 0;
73
74#[derive(Debug)]
76pub enum Imported {
77 Func(ImportName),
81 Table(ImportName),
85 Memory(ImportName),
89 Global(ImportName),
91}
92
93#[derive(Debug)]
95pub struct ModuleImports {
96 items: Box<[Imported]>,
98 len_funcs: usize,
102 len_globals: usize,
104 len_memories: usize,
108 len_tables: usize,
112}
113
114impl ModuleImports {
115 fn from_builder(imports: builder::ModuleImports) -> Self {
117 let len_funcs = imports.funcs.len();
118 let len_globals = imports.globals.len();
119 let len_memories = imports.memories.len();
120 let len_tables = imports.tables.len();
121 let funcs = imports.funcs.into_iter().map(Imported::Func);
122 let tables = imports.tables.into_iter().map(Imported::Table);
123 let memories = imports.memories.into_iter().map(Imported::Memory);
124 let globals = imports.globals.into_iter().map(Imported::Global);
125 let items = funcs
126 .chain(tables)
127 .chain(memories)
128 .chain(globals)
129 .collect::<Vec<_>>()
130 .into();
131 Self {
132 items,
133 len_funcs,
134 len_globals,
135 len_memories,
136 len_tables,
137 }
138 }
139}
140
141impl Module {
142 pub fn new(engine: &Engine, stream: impl Read) -> Result<Self, Error> {
149 parse(engine, stream).map_err(Into::into)
150 }
151
152 pub fn engine(&self) -> &Engine {
154 &self.engine
155 }
156
157 fn from_builder(builder: ModuleBuilder) -> Self {
159 Self {
160 engine: builder.engine.clone(),
161 func_types: builder.func_types.into(),
162 imports: ModuleImports::from_builder(builder.imports),
163 funcs: builder.funcs.into(),
164 tables: builder.tables.into(),
165 memories: builder.memories.into(),
166 globals: builder.globals.into(),
167 globals_init: builder.globals_init.into(),
168 exports: builder.exports,
169 start: builder.start,
170 func_bodies: builder.func_bodies.into(),
171 element_segments: builder.element_segments.into(),
172 data_segments: builder.data_segments.into(),
173 }
174 }
175
176 pub(crate) fn len_funcs(&self) -> usize {
178 self.funcs.len()
179 }
180 pub(crate) fn len_tables(&self) -> usize {
182 self.tables.len()
183 }
184 pub(crate) fn len_memories(&self) -> usize {
186 self.memories.len()
187 }
188 pub(crate) fn len_globals(&self) -> usize {
190 self.memories.len()
191 }
192
193 pub fn imports(&self) -> ModuleImportsIter {
195 let len_imported_funcs = self.imports.len_funcs;
196 let len_imported_globals = self.imports.len_globals;
197 ModuleImportsIter {
198 engine: &self.engine,
199 names: self.imports.items.iter(),
200 funcs: self.funcs[..len_imported_funcs].iter(),
201 tables: self.tables.iter(),
202 memories: self.memories.iter(),
203 globals: self.globals[..len_imported_globals].iter(),
204 }
205 }
206
207 pub(crate) fn internal_funcs(&self) -> InternalFuncsIter {
211 let len_imported = self.imports.len_funcs;
212 let funcs = &self.funcs[len_imported..];
216 let func_bodies = &self.func_bodies[..];
217 assert_eq!(funcs.len(), func_bodies.len());
218 InternalFuncsIter {
219 iter: funcs.iter().zip(func_bodies),
220 }
221 }
222
223 fn internal_memories(&self) -> SliceIter<MemoryType> {
225 let len_imported = self.imports.len_memories;
226 let memories = &self.memories[len_imported..];
230 memories.iter()
231 }
232
233 fn internal_tables(&self) -> SliceIter<TableType> {
235 let len_imported = self.imports.len_tables;
236 let tables = &self.tables[len_imported..];
240 tables.iter()
241 }
242
243 fn internal_globals(&self) -> InternalGlobalsIter {
245 let len_imported = self.imports.len_globals;
246 let globals = self.globals[len_imported..].iter();
250 let global_inits = self.globals_init.iter();
251 InternalGlobalsIter {
252 iter: globals.zip(global_inits),
253 }
254 }
255
256 pub fn exports(&self) -> ModuleExportsIter {
258 ModuleExportsIter::new(self)
259 }
260
261 pub fn get_export(&self, name: &str) -> Option<ExternType> {
269 let idx = self.exports.get(name).copied()?;
270 let ty = self.get_extern_type(idx);
271 Some(ty)
272 }
273
274 fn get_extern_type(&self, idx: ExternIdx) -> ExternType {
280 match idx {
281 ExternIdx::Func(index) => {
282 let dedup = self.funcs[index.into_usize()];
283 let func_type = self.engine.resolve_func_type(dedup, Clone::clone);
284 ExternType::Func(func_type)
285 }
286 ExternIdx::Table(index) => {
287 let table_type = self.tables[index.into_u32() as usize];
288 ExternType::Table(table_type)
289 }
290 ExternIdx::Memory(index) => {
291 let memory_type = self.memories[index.into_u32() as usize];
292 ExternType::Memory(memory_type)
293 }
294 ExternIdx::Global(index) => {
295 let global_type = self.globals[index.into_usize()];
296 ExternType::Global(global_type)
297 }
298 }
299 }
300}
301
302#[derive(Debug)]
304pub struct ModuleImportsIter<'a> {
305 engine: &'a Engine,
306 names: SliceIter<'a, Imported>,
307 funcs: SliceIter<'a, DedupFuncType>,
308 tables: SliceIter<'a, TableType>,
309 memories: SliceIter<'a, MemoryType>,
310 globals: SliceIter<'a, GlobalType>,
311}
312
313impl<'a> Iterator for ModuleImportsIter<'a> {
314 type Item = ImportType<'a>;
315
316 fn next(&mut self) -> Option<Self::Item> {
317 let import = match self.names.next() {
318 None => return None,
319 Some(imported) => match imported {
320 Imported::Func(name) => {
321 let func_type = self.funcs.next().unwrap_or_else(|| {
322 panic!("unexpected missing imported function for {name:?}")
323 });
324 let func_type = self.engine.resolve_func_type(*func_type, FuncType::clone);
325 ImportType::new(name, func_type)
326 }
327 Imported::Table(name) => {
328 let table_type = self.tables.next().unwrap_or_else(|| {
329 panic!("unexpected missing imported table for {name:?}")
330 });
331 ImportType::new(name, *table_type)
332 }
333 Imported::Memory(name) => {
334 let memory_type = self.memories.next().unwrap_or_else(|| {
335 panic!("unexpected missing imported linear memory for {name:?}")
336 });
337 ImportType::new(name, *memory_type)
338 }
339 Imported::Global(name) => {
340 let global_type = self.globals.next().unwrap_or_else(|| {
341 panic!("unexpected missing imported global variable for {name:?}")
342 });
343 ImportType::new(name, *global_type)
344 }
345 },
346 };
347 Some(import)
348 }
349
350 fn size_hint(&self) -> (usize, Option<usize>) {
351 self.names.size_hint()
352 }
353}
354
355impl<'a> ExactSizeIterator for ModuleImportsIter<'a> {
356 fn len(&self) -> usize {
357 ExactSizeIterator::len(&self.names)
358 }
359}
360
361#[derive(Debug)]
367pub struct ImportType<'module> {
368 name: &'module ImportName,
370 ty: ExternType,
372}
373
374impl<'module> ImportType<'module> {
375 pub(crate) fn new<T>(name: &'module ImportName, ty: T) -> Self
377 where
378 T: Into<ExternType>,
379 {
380 Self {
381 name,
382 ty: ty.into(),
383 }
384 }
385
386 pub(crate) fn import_name(&self) -> &ImportName {
388 self.name
389 }
390
391 pub fn module(&self) -> &'module str {
393 self.name.module()
394 }
395
396 pub fn name(&self) -> &'module str {
398 self.name.name()
399 }
400
401 pub fn ty(&self) -> &ExternType {
403 &self.ty
404 }
405}
406
407#[derive(Debug)]
409pub struct InternalFuncsIter<'a> {
410 iter: iter::Zip<SliceIter<'a, DedupFuncType>, SliceIter<'a, FuncBody>>,
411}
412
413impl<'a> Iterator for InternalFuncsIter<'a> {
414 type Item = (DedupFuncType, FuncBody);
415
416 fn next(&mut self) -> Option<Self::Item> {
417 self.iter
418 .next()
419 .map(|(func_type, func_body)| (*func_type, *func_body))
420 }
421
422 fn size_hint(&self) -> (usize, Option<usize>) {
423 self.iter.size_hint()
424 }
425}
426
427impl<'a> ExactSizeIterator for InternalFuncsIter<'a> {
428 fn len(&self) -> usize {
429 ExactSizeIterator::len(&self.iter)
430 }
431}
432
433#[derive(Debug)]
435pub struct InternalGlobalsIter<'a> {
436 iter: iter::Zip<SliceIter<'a, GlobalType>, SliceIter<'a, InitExpr>>,
437}
438
439impl<'a> Iterator for InternalGlobalsIter<'a> {
440 type Item = (&'a GlobalType, &'a InitExpr);
441
442 fn next(&mut self) -> Option<Self::Item> {
443 self.iter.next()
444 }
445
446 fn size_hint(&self) -> (usize, Option<usize>) {
447 self.iter.size_hint()
448 }
449}
450
451impl<'a> ExactSizeIterator for InternalGlobalsIter<'a> {
452 fn len(&self) -> usize {
453 ExactSizeIterator::len(&self.iter)
454 }
455}