1use crate::core::error::Result as CustomResult;
2use crate::core::indices::TypeIdx;
3use crate::core::reader::span::Span;
4use crate::core::reader::types::data::{DataModeActive, DataSegment};
5use crate::core::reader::types::element::{ActiveElem, ElemItems, ElemMode, ElemType};
6use crate::core::reader::types::export::{Export, ExportDesc};
7use crate::core::reader::types::global::{Global, GlobalType};
8use crate::core::reader::types::import::Import;
9use crate::core::reader::types::{
10 ExternType, FuncType, ImportSubTypeRelation, MemType, TableType, ValType,
11};
12use crate::core::reader::WasmReader;
13use crate::core::sidetable::Sidetable;
14use crate::execution::interpreter_loop::{memory_init, table_init};
15use crate::execution::value::{Ref, Value};
16use crate::execution::{run_const_span, Stack};
17use crate::value::FuncAddr;
18use crate::{Error, Limits, RefType, RuntimeError, ValidationInfo};
19use alloc::borrow::ToOwned;
20use alloc::collections::btree_map::BTreeMap;
21use alloc::string::String;
22use alloc::vec;
23use alloc::vec::Vec;
24
25use super::hooks::EmptyHookSet;
26use super::interpreter_loop::{data_drop, elem_drop};
27use super::locals::Locals;
28use super::value::{ExternAddr, InteropValueList};
29use super::{run, UnwrapValidatedExt};
30
31use crate::linear_memory::LinearMemory;
32
33#[derive(Default, Debug)]
39pub struct Store<'b> {
40 pub functions: Vec<FuncInst>,
41 pub memories: Vec<MemInst>,
42 pub globals: Vec<GlobalInst>,
43 pub data: Vec<DataInst>,
44 pub tables: Vec<TableInst>,
45 pub elements: Vec<ElemInst>,
46 pub modules: Vec<ModuleInst<'b>>,
47 pub module_names: BTreeMap<String, usize>,
48}
49
50impl<'b> Store<'b> {
51 pub fn add_module(
57 &mut self,
58 name: &str,
59 validation_info: &ValidationInfo<'b>,
60 ) -> CustomResult<()> {
61 debug!("adding module with name {:?}", name);
64 let mut extern_vals = Vec::new();
65
66 for Import {
67 module_name: exporting_module_name,
68 name: import_name,
69 desc: import_desc,
70 } in &validation_info.imports
71 {
72 trace!(
73 "trying to import from exporting module instance named {:?}, the entity with name {:?} with desc: {:?}",
74 exporting_module_name,
75 import_name,
76 import_desc
77 );
78 let import_extern_type = import_desc.extern_type(validation_info)?;
79 let exporting_module = self
80 .modules
81 .get(
82 *self
83 .module_names
84 .get(exporting_module_name)
85 .ok_or(Error::RuntimeError(RuntimeError::ModuleNotFound))?,
86 )
87 .ok_or(Error::RuntimeError(RuntimeError::ModuleNotFound))?;
88
89 let export_extern_val_candidate = *exporting_module
90 .exports
91 .iter()
92 .find_map(
93 |ExportInst {
94 name: export_name,
95 value: export_extern_val,
96 }| {
97 (import_name == export_name).then_some(export_extern_val)
98 },
99 )
100 .ok_or(Error::UnknownImport)?;
101 trace!("export candidate found: {:?}", export_extern_val_candidate);
102 if !export_extern_val_candidate
103 .extern_type(self)?
104 .is_subtype_of(&import_extern_type)
105 {
106 return Err(Error::InvalidImportType);
107 }
108 trace!("import and export matches. Adding to externvals");
109 extern_vals.push(export_extern_val_candidate)
110 }
111
112 let mut module_inst = ModuleInst {
117 types: validation_info.types.clone(),
118 func_addrs: extern_vals.iter().funcs().collect(),
119 table_addrs: Vec::new(),
120 mem_addrs: Vec::new(),
121 global_addrs: extern_vals.iter().globals().collect(),
122 elem_addrs: Vec::new(),
123 data_addrs: Vec::new(),
124 exports: Vec::new(),
125 wasm_bytecode: validation_info.wasm,
126 sidetable: validation_info.sidetable.clone(),
127 name: name.to_owned(),
128 };
129
130 let func_addrs: Vec<usize> = validation_info
133 .functions
134 .iter()
135 .zip(validation_info.func_blocks_stps.iter())
136 .map(|(ty_idx, (span, stp))| {
137 self.alloc_func((*ty_idx, (*span, *stp)), &module_inst, self.modules.len())
138 })
139 .collect();
140
141 module_inst.func_addrs.extend(func_addrs);
142
143 let maybe_global_init_vals: Result<Vec<Value>, _> = validation_info
146 .globals
147 .iter()
148 .map(|global| {
149 run_const_span(validation_info.wasm, &global.init_expr, &module_inst, self)
150 .transpose()
151 .unwrap_validated()
152 })
153 .collect();
154 let global_init_vals = maybe_global_init_vals?;
155
156 let mut element_init_ref_lists: Vec<Vec<Ref>> =
159 Vec::with_capacity(validation_info.elements.len());
160
161 for elem in &validation_info.elements {
162 let mut new_list = Vec::new();
163 match &elem.init {
164 ElemItems::RefFuncs(ref_funcs) => {
167 for func_idx in ref_funcs {
168 new_list.push(Ref::Func(FuncAddr {
169 addr: Some(module_inst.func_addrs[*func_idx as usize]),
170 }))
171 }
172 }
173 ElemItems::Exprs(_, exprs) => {
174 for expr in exprs {
175 new_list.push(
176 run_const_span(validation_info.wasm, expr, &module_inst, self)?
177 .unwrap_validated()
178 .into(),
179 )
180 }
181 }
182 }
183 element_init_ref_lists.push(new_list);
184 }
185
186 let module = validation_info;
193
194 let extern_vals = extern_vals;
195 let vals = global_init_vals;
196 let ref_lists = element_init_ref_lists;
197
198 let table_addrs: Vec<usize> = module
202 .tables
203 .iter()
204 .map(|table_type| {
205 let null_ref = match table_type.et {
206 RefType::FuncRef => Ref::Func(FuncAddr { addr: None }),
207 RefType::ExternRef => Ref::Extern(ExternAddr { addr: None }),
208 };
209 self.alloc_table(*table_type, null_ref)
210 })
211 .collect();
212 let mem_addrs: Vec<usize> = module
213 .memories
214 .iter()
215 .map(|mem_type| self.alloc_mem(*mem_type))
216 .collect();
217 let global_addrs: Vec<usize> = module
218 .globals
219 .iter()
220 .zip(vals)
221 .map(
222 |(
223 Global {
224 ty: global_type, ..
225 },
226 val,
227 )| self.alloc_global(*global_type, val),
228 )
229 .collect();
230 let elem_addrs = module
231 .elements
232 .iter()
233 .zip(ref_lists)
234 .map(|(elem, refs)| self.alloc_elem(elem.ty(), refs))
235 .collect();
236 let data_addrs = module
237 .data
238 .iter()
239 .map(|DataSegment { init: bytes, .. }| self.alloc_data(bytes))
240 .collect();
241
242 let mut table_addrs_mod: Vec<usize> = extern_vals.iter().tables().collect();
246 table_addrs_mod.extend(table_addrs);
247
248 let mut mem_addrs_mod: Vec<usize> = extern_vals.iter().mems().collect();
249 mem_addrs_mod.extend(mem_addrs);
250
251 module_inst.global_addrs.extend(global_addrs);
253
254 let export_insts = module
256 .exports
257 .iter()
258 .map(|Export { name, desc }| {
259 let value = match desc {
260 ExportDesc::FuncIdx(func_idx) => {
261 ExternVal::Func(module_inst.func_addrs[*func_idx])
262 }
263 ExportDesc::TableIdx(table_idx) => {
264 ExternVal::Table(table_addrs_mod[*table_idx])
265 }
266 ExportDesc::MemIdx(mem_idx) => ExternVal::Mem(mem_addrs_mod[*mem_idx]),
267 ExportDesc::GlobalIdx(global_idx) => {
268 ExternVal::Global(module_inst.global_addrs[*global_idx])
269 }
270 };
271 ExportInst {
272 name: String::from(name),
273 value,
274 }
275 })
276 .collect();
277
278 module_inst.table_addrs = table_addrs_mod;
280 module_inst.mem_addrs = mem_addrs_mod;
281 module_inst.elem_addrs = elem_addrs;
282 module_inst.data_addrs = data_addrs;
283 module_inst.exports = export_insts;
284
285 let current_module_idx = &self.modules.len();
290 self.modules.push(module_inst);
291 self.module_names
292 .insert(String::from(name), *current_module_idx);
293
294 for (
297 i,
298 ElemType {
299 init: elem_items,
300 mode,
301 },
302 ) in validation_info.elements.iter().enumerate()
303 {
304 match mode {
305 ElemMode::Active(ActiveElem {
306 table_idx: table_idx_i,
307 init_expr: einstr_i,
308 }) => {
309 let n = elem_items.len() as i32;
310 let d: i32 = run_const_span(
320 validation_info.wasm,
321 einstr_i,
322 &self.modules[*current_module_idx],
323 self,
324 )?
325 .unwrap_validated()
326 .into();
327 let s = 0;
328 table_init(
329 &self.modules,
330 &mut self.tables,
331 &self.elements,
332 current_module_idx,
333 i,
334 *table_idx_i as usize,
335 n,
336 s,
337 d,
338 )
339 .map_err(Error::RuntimeError)?;
340 elem_drop(&self.modules, &mut self.elements, current_module_idx, i)
341 .map_err(Error::RuntimeError)?;
342 }
343 ElemMode::Declarative => {
344 elem_drop(&self.modules, &mut self.elements, current_module_idx, i)
349 .map_err(Error::RuntimeError)?;
350 }
351 ElemMode::Passive => (),
352 }
353 }
354
355 for (i, DataSegment { init, mode }) in validation_info.data.iter().enumerate() {
358 match mode {
359 crate::core::reader::types::data::DataMode::Active(DataModeActive {
360 memory_idx,
361 offset: dinstr_i,
362 }) => {
363 let n = init.len() as i32;
364 if *memory_idx != 0 {
366 return Err(Error::MoreThanOneMemory);
368 }
369
370 let d: i32 = run_const_span(
378 validation_info.wasm,
379 dinstr_i,
380 &self.modules[*current_module_idx],
381 self,
382 )?
383 .unwrap_validated()
384 .into();
385 let s = 0;
386 memory_init(
387 &self.modules,
388 &mut self.memories,
389 &self.data,
390 current_module_idx,
391 i,
392 0,
393 n,
394 s,
395 d,
396 )
397 .map_err(Error::RuntimeError)?;
398 data_drop(&self.modules, &mut self.data, current_module_idx, i)
399 .map_err(Error::RuntimeError)?;
400 }
401 crate::core::reader::types::data::DataMode::Passive => (),
402 }
403 }
404
405 if let Some(func_idx) = validation_info.start {
407 let func_addr = self.modules[*current_module_idx].func_addrs[func_idx];
411 self.invoke_dynamic(func_addr, Vec::new(), &[])
412 .map_err(Error::RuntimeError)?;
413 };
414
415 Ok(())
416 }
417
418 fn alloc_func(
422 &mut self,
423 func: (TypeIdx, (Span, usize)),
424 module_inst: &ModuleInst,
425 module_addr: usize,
426 ) -> usize {
427 let (ty, (span, stp)) = func;
428
429 let mut wasm_reader = WasmReader::new(module_inst.wasm_bytecode);
431 wasm_reader.move_start_to(span).unwrap_validated();
432
433 let (locals, bytes_read) = wasm_reader
434 .measure_num_read_bytes(crate::code::read_declared_locals)
435 .unwrap_validated();
436
437 let code_expr = wasm_reader
438 .make_span(span.len() - bytes_read)
439 .unwrap_validated();
440
441 let func_inst = FuncInst {
444 ty,
445 locals,
446 code_expr,
447 stp,
448 function_type: module_inst.types[ty].clone(),
451 module_addr,
452 };
453
454 let addr = self.functions.len();
455 self.functions.push(func_inst);
456 addr
457 }
458
459 fn alloc_table(&mut self, table_type: TableType, reff: Ref) -> usize {
461 let table_inst = TableInst {
462 ty: table_type,
463 elem: vec![reff; table_type.lim.min as usize],
464 };
465
466 let addr = self.tables.len();
467 self.tables.push(table_inst);
468 addr
469 }
470
471 fn alloc_mem(&mut self, mem_type: MemType) -> usize {
473 let mem_inst = MemInst {
474 ty: mem_type,
475 mem: LinearMemory::new_with_initial_pages(
476 mem_type.limits.min.try_into().unwrap_validated(),
477 ),
478 };
479
480 let addr = self.memories.len();
481 self.memories.push(mem_inst);
482 addr
483 }
484
485 fn alloc_global(&mut self, global_type: GlobalType, val: Value) -> usize {
487 let global_inst = GlobalInst {
488 ty: global_type,
489 value: val,
490 };
491
492 let addr = self.globals.len();
493 self.globals.push(global_inst);
494 addr
495 }
496
497 fn alloc_elem(&mut self, ref_type: RefType, refs: Vec<Ref>) -> usize {
499 let elem_inst = ElemInst {
500 ty: ref_type,
501 references: refs,
502 };
503
504 let addr = self.elements.len();
505 self.elements.push(elem_inst);
506 addr
507 }
508
509 fn alloc_data(&mut self, bytes: &[u8]) -> usize {
511 let data_inst = DataInst {
512 data: Vec::from(bytes),
513 };
514
515 let addr = self.data.len();
516 self.data.push(data_inst);
517 addr
518 }
519
520 pub fn invoke<Param: InteropValueList, Returns: InteropValueList>(
521 &mut self,
522 func_addr: usize,
523 params: Param,
524 ) -> Result<Returns, RuntimeError> {
525 let func_inst = self
526 .functions
527 .get(func_addr)
528 .ok_or(RuntimeError::FunctionNotFound)?;
529
530 let func_ty = func_inst.ty();
531
532 if func_ty.params.valtypes != Param::TYS {
533 panic!("Invalid `Param` generics");
534 }
535 if func_ty.returns.valtypes != Returns::TYS {
536 panic!("Invalid `Returns` generics");
537 }
538
539 let mut stack = Stack::new();
540 let locals = Locals::new(
541 params.into_values().into_iter(),
542 func_inst.locals.iter().cloned(),
543 );
544
545 let module_addr = func_inst.module_addr;
546
547 let (func_idx, _) = self.modules[module_addr]
549 .func_addrs
550 .iter()
551 .enumerate()
552 .find(|&(_idx, addr)| *addr == func_addr)
553 .ok_or(RuntimeError::FunctionNotFound)?;
554 stack.push_stackframe(
557 module_addr,
558 func_idx,
559 &func_ty,
560 locals,
561 usize::MAX,
562 usize::MAX,
563 )?;
564
565 let mut current_module_idx = module_addr;
566 run(
568 &mut current_module_idx,
570 &mut stack,
572 EmptyHookSet,
573 self,
574 )?;
575
576 let return_values = Returns::TYS
578 .iter()
579 .rev()
580 .map(|ty| stack.pop_value(*ty))
581 .collect::<Vec<Value>>();
582
583 let reversed_values = return_values.into_iter().rev();
585 let ret: Returns = Returns::from_values(reversed_values);
586 debug!("Successfully invoked function");
587 Ok(ret)
588 }
589
590 pub fn invoke_dynamic(
591 &mut self,
592 func_addr: usize,
593 params: Vec<Value>,
594 ret_types: &[ValType],
595 ) -> Result<Vec<Value>, RuntimeError> {
596 let func_inst = self
597 .functions
598 .get(func_addr)
599 .ok_or(RuntimeError::FunctionNotFound)?;
600
601 let func_ty = func_inst.ty();
602
603 let param_types = params.iter().map(|v| v.to_ty()).collect::<Vec<_>>();
605
606 if func_ty.params.valtypes != param_types {
607 trace!(
609 "Func param types len: {}; Given args len: {}",
610 func_ty.params.valtypes.len(),
611 param_types.len()
612 );
613 panic!("Invalid parameters for function");
614 }
615
616 if func_ty.returns.valtypes != ret_types {
618 panic!("Invalid return types for function");
619 }
620
621 let mut stack = Stack::new();
623 let locals = Locals::new(params.into_iter(), func_inst.locals.iter().cloned());
624 let module_addr = func_inst.module_addr;
625
626 let (func_idx, _) = self.modules[module_addr]
628 .func_addrs
629 .iter()
630 .enumerate()
631 .find(|&(_idx, addr)| *addr == func_addr)
632 .ok_or(RuntimeError::FunctionNotFound)?;
633 stack.push_stackframe(
634 module_addr,
635 func_idx,
636 &func_ty,
637 locals,
638 usize::MAX,
639 usize::MAX,
640 )?;
641
642 let mut currrent_module_idx = module_addr;
643 run(
645 &mut currrent_module_idx,
647 &mut stack,
649 EmptyHookSet,
650 self,
651 )?;
652
653 let func_inst = self
654 .functions
655 .get(func_addr)
656 .ok_or(RuntimeError::FunctionNotFound)?;
657
658 let func_ty = func_inst.ty();
659
660 let return_values = func_ty
662 .returns
663 .valtypes
664 .iter()
665 .rev()
666 .map(|ty| stack.pop_value(*ty))
667 .collect::<Vec<Value>>();
668
669 let reversed_values = return_values.into_iter().rev();
671 let ret = reversed_values.collect();
672 debug!("Successfully invoked function");
673 Ok(ret)
674 }
675
676 pub fn invoke_dynamic_unchecked_return_ty(
677 &mut self,
678 func_addr: usize,
679 params: Vec<Value>,
680 ) -> Result<Vec<Value>, RuntimeError> {
681 let func_inst = self
682 .functions
683 .get(func_addr)
684 .ok_or(RuntimeError::FunctionNotFound)?;
685
686 let module_addr = func_inst.module_addr;
687
688 let func_ty = func_inst.ty();
689
690 let param_types = params.iter().map(|v| v.to_ty()).collect::<Vec<_>>();
692
693 if func_ty.params.valtypes != param_types {
694 trace!(
695 "Func param types len: {}; Given args len: {}",
696 func_ty.params.valtypes.len(),
697 param_types.len()
698 );
699 panic!("Invalid parameters for function");
700 }
701
702 let mut stack = Stack::new();
704 let locals = Locals::new(params.into_iter(), func_inst.locals.iter().cloned());
705
706 let (func_idx, _) = self.modules[module_addr]
708 .func_addrs
709 .iter()
710 .enumerate()
711 .find(|&(_idx, addr)| *addr == func_addr)
712 .ok_or(RuntimeError::FunctionNotFound)?;
713
714 stack.push_stackframe(
715 module_addr,
716 func_idx,
717 &func_ty,
718 locals,
719 usize::MAX,
720 usize::MAX,
721 )?;
722
723 let mut currrent_module_idx = module_addr;
724 run(
726 &mut currrent_module_idx,
728 &mut stack,
730 EmptyHookSet,
731 self,
732 )?;
733
734 let return_values = func_ty
736 .returns
737 .valtypes
738 .iter()
739 .rev()
740 .map(|ty| stack.pop_value(*ty))
741 .collect::<Vec<Value>>();
742
743 let reversed_values = return_values.into_iter().rev();
745 let ret = reversed_values.collect();
746 debug!("Successfully invoked function");
747 Ok(ret)
748 }
749
750 pub fn get_module_idx_from_name(&self, module_name: &str) -> Result<usize, RuntimeError> {
752 self.module_names
753 .get(module_name)
754 .copied()
755 .ok_or(RuntimeError::ModuleNotFound)
756 }
757
758 pub fn get_global_function_idx_by_name(
760 &self,
761 module_addr: usize,
762 function_name: &str,
763 ) -> Option<usize> {
764 self.modules
765 .get(module_addr)?
766 .exports
767 .iter()
768 .find_map(|ExportInst { name, value }| {
769 if name != function_name {
770 return None;
771 };
772 match value {
773 ExternVal::Func(func_addr) => Some(*func_addr),
774 _ => None,
775 }
776 })
777 }
778
779 pub fn register_alias(&mut self, alias_name: String, module_idx: usize) {
781 self.module_names.insert(alias_name, module_idx);
782 }
783
784 pub fn lookup_function(&self, target_module: &str, target_function: &str) -> Option<usize> {
786 let module_addr = *self.module_names.get(target_module)?;
787 self.get_global_function_idx_by_name(module_addr, target_function)
788 }
789}
790
791#[derive(Debug)]
792pub struct FuncInst {
795 pub ty: TypeIdx,
796 pub locals: Vec<ValType>,
797 pub code_expr: Span,
798 pub stp: usize,
800 pub function_type: FuncType,
801 pub module_addr: usize,
804}
805
806impl FuncInst {
807 pub fn ty_idx(&self) -> TypeIdx {
808 self.ty
809 }
810
811 pub fn ty(&self) -> FuncType {
812 self.function_type.clone()
813 }
814}
815
816#[derive(Clone, Debug)]
817pub struct ElemInst {
819 pub ty: RefType,
820 pub references: Vec<Ref>,
821}
822
823impl ElemInst {
824 pub fn len(&self) -> usize {
825 self.references.len()
826 }
827 pub fn is_empty(&self) -> bool {
828 self.references.is_empty()
829 }
830}
831
832#[derive(Debug)]
836pub struct TableInst {
837 pub ty: TableType,
838 pub elem: Vec<Ref>,
839}
840
841impl TableInst {
842 pub fn len(&self) -> usize {
843 self.elem.len()
844 }
845
846 pub fn is_empty(&self) -> bool {
847 self.elem.is_empty()
848 }
849
850 pub fn new(ty: TableType) -> Self {
851 Self {
852 ty,
853 elem: vec![Ref::default_from_ref_type(ty.et); ty.lim.min as usize],
854 }
855 }
856
857 pub fn grow(&mut self, n: u32, reff: Ref) -> Result<(), RuntimeError> {
859 let len = n
861 .checked_add(self.elem.len() as u32)
862 .ok_or(RuntimeError::TableAccessOutOfBounds)?;
863
864 if self.ty.lim.max.map(|max| len > max).unwrap_or(false) {
868 return Err(RuntimeError::TableAccessOutOfBounds);
869 }
870 let limits_prime = Limits {
871 min: len,
872 max: self.ty.lim.max,
873 };
874
875 self.elem.extend(vec![reff; n as usize]);
876
877 self.ty.lim = limits_prime;
878 Ok(())
879 }
880}
881
882pub struct MemInst {
883 #[allow(warnings)]
884 pub ty: MemType,
885 pub mem: LinearMemory,
886}
887impl core::fmt::Debug for MemInst {
888 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
889 f.debug_struct("MemInst")
890 .field("ty", &self.ty)
891 .finish_non_exhaustive()
892 }
893}
894
895impl MemInst {
896 pub fn new(ty: MemType) -> Self {
897 Self {
898 ty,
899 mem: LinearMemory::new_with_initial_pages(ty.limits.min.try_into().unwrap()),
900 }
901 }
902
903 pub fn grow(&mut self, n: u32) -> Result<(), RuntimeError> {
905 let len = n + self.mem.pages() as u32;
907 if len > Limits::MAX_MEM_PAGES {
908 return Err(RuntimeError::MemoryAccessOutOfBounds);
909 }
910
911 if self.ty.limits.max.map(|max| len > max).unwrap_or(false) {
915 return Err(RuntimeError::MemoryAccessOutOfBounds);
916 }
917 let limits_prime = Limits {
918 min: len,
919 max: self.ty.limits.max,
920 };
921
922 self.mem.grow(n.try_into().unwrap());
923
924 self.ty.limits = limits_prime;
925 Ok(())
926 }
927
928 pub fn size(&self) -> usize {
930 self.mem.len() / (crate::Limits::MEM_PAGE_SIZE as usize)
931 }
932}
933
934#[derive(Debug)]
940pub struct GlobalInst {
941 pub ty: GlobalType,
942 pub value: Value,
944}
945
946pub struct DataInst {
947 pub data: Vec<u8>,
948}
949
950impl core::fmt::Debug for DataInst {
951 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
952 f.debug_struct("DataInst").finish_non_exhaustive()
953 }
954}
955
956#[derive(Debug, Copy, Clone, PartialEq, Eq)]
958pub enum ExternVal {
959 Func(usize),
960 Table(usize),
961 Mem(usize),
962 Global(usize),
963}
964
965impl ExternVal {
966 pub fn extern_type(&self, store: &Store) -> CustomResult<ExternType> {
971 Ok(match self {
973 ExternVal::Func(func_addr) => ExternType::Func(
975 store
976 .functions
977 .get(*func_addr)
978 .ok_or(Error::InvalidImportType)?
979 .ty(),
980 ),
981 ExternVal::Table(table_addr) => ExternType::Table(
982 store
983 .tables
984 .get(*table_addr)
985 .ok_or(Error::InvalidImportType)?
986 .ty,
987 ),
988 ExternVal::Mem(mem_addr) => ExternType::Mem(
989 store
990 .memories
991 .get(*mem_addr)
992 .ok_or(Error::InvalidImportType)?
993 .ty,
994 ),
995 ExternVal::Global(global_addr) => ExternType::Global(
996 store
997 .globals
998 .get(*global_addr)
999 .ok_or(Error::InvalidImportType)?
1000 .ty,
1001 ),
1002 })
1003 }
1004}
1005
1006pub trait ExternFilterable<T> {
1012 fn funcs(self) -> impl Iterator<Item = T>;
1013 fn tables(self) -> impl Iterator<Item = T>;
1014 fn mems(self) -> impl Iterator<Item = T>;
1015 fn globals(self) -> impl Iterator<Item = T>;
1016}
1017
1018impl<'a, I> ExternFilterable<usize> for I
1019where
1020 I: Iterator<Item = &'a ExternVal>,
1021{
1022 fn funcs(self) -> impl Iterator<Item = usize> {
1023 self.filter_map(|extern_val| {
1024 if let ExternVal::Func(func_addr) = extern_val {
1025 Some(*func_addr)
1026 } else {
1027 None
1028 }
1029 })
1030 }
1031
1032 fn tables(self) -> impl Iterator<Item = usize> {
1033 self.filter_map(|extern_val| {
1034 if let ExternVal::Table(table_addr) = extern_val {
1035 Some(*table_addr)
1036 } else {
1037 None
1038 }
1039 })
1040 }
1041
1042 fn mems(self) -> impl Iterator<Item = usize> {
1043 self.filter_map(|extern_val| {
1044 if let ExternVal::Mem(mem_addr) = extern_val {
1045 Some(*mem_addr)
1046 } else {
1047 None
1048 }
1049 })
1050 }
1051
1052 fn globals(self) -> impl Iterator<Item = usize> {
1053 self.filter_map(|extern_val| {
1054 if let ExternVal::Global(global_addr) = extern_val {
1055 Some(*global_addr)
1056 } else {
1057 None
1058 }
1059 })
1060 }
1061}
1062
1063#[derive(Debug)]
1065pub struct ExportInst {
1066 pub name: String,
1067 pub value: ExternVal,
1068}
1069
1070#[derive(Debug)]
1072pub struct ModuleInst<'b> {
1073 pub types: Vec<FuncType>,
1074 pub func_addrs: Vec<usize>,
1075 pub table_addrs: Vec<usize>,
1076 pub mem_addrs: Vec<usize>,
1077 pub global_addrs: Vec<usize>,
1078 pub elem_addrs: Vec<usize>,
1079 pub data_addrs: Vec<usize>,
1080 pub exports: Vec<ExportInst>,
1081
1082 pub wasm_bytecode: &'b [u8],
1084
1085 pub sidetable: Sidetable,
1087
1088 pub name: String,
1091}