1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
use crate::Error; use alloc::vec::Vec; use parity_wasm::elements::{ BlockType, FunctionType, GlobalType, MemoryType, TableType, ValueType, }; #[derive(Default, Debug)] pub struct ModuleContext { pub memories: Vec<MemoryType>, pub tables: Vec<TableType>, pub globals: Vec<GlobalType>, pub types: Vec<FunctionType>, pub func_type_indexes: Vec<u32>, } impl ModuleContext { pub fn memories(&self) -> &[MemoryType] { &self.memories } pub fn tables(&self) -> &[TableType] { &self.tables } pub fn globals(&self) -> &[GlobalType] { &self.globals } pub fn types(&self) -> &[FunctionType] { &self.types } pub fn func_type_indexes(&self) -> &[u32] { &self.func_type_indexes } pub fn require_memory(&self, idx: u32) -> Result<(), Error> { if self.memories().get(idx as usize).is_none() { return Err(Error(format!("Memory at index {} doesn't exists", idx))); } Ok(()) } pub fn require_table(&self, idx: u32) -> Result<&TableType, Error> { self.tables() .get(idx as usize) .ok_or_else(|| Error(format!("Table at index {} doesn't exists", idx))) } pub fn require_function(&self, idx: u32) -> Result<(&[ValueType], BlockType), Error> { let ty_idx = self .func_type_indexes() .get(idx as usize) .ok_or_else(|| Error(format!("Function at index {} doesn't exists", idx)))?; self.require_function_type(*ty_idx) } pub fn require_function_type(&self, idx: u32) -> Result<(&[ValueType], BlockType), Error> { let ty = self .types() .get(idx as usize) .ok_or_else(|| Error(format!("Type at index {} doesn't exists", idx)))?; let params = ty.params(); let return_ty = ty .return_type() .map(BlockType::Value) .unwrap_or(BlockType::NoResult); Ok((params, return_ty)) } pub fn require_global(&self, idx: u32, mutability: Option<bool>) -> Result<&GlobalType, Error> { let global = self .globals() .get(idx as usize) .ok_or_else(|| Error(format!("Global at index {} doesn't exists", idx)))?; if let Some(expected_mutable) = mutability { if expected_mutable && !global.is_mutable() { return Err(Error(format!("Expected global {} to be mutable", idx))); } if !expected_mutable && global.is_mutable() { return Err(Error(format!("Expected global {} to be immutable", idx))); } } Ok(global) } } #[derive(Default)] pub struct ModuleContextBuilder { memories: Vec<MemoryType>, tables: Vec<TableType>, globals: Vec<GlobalType>, types: Vec<FunctionType>, func_type_indexes: Vec<u32>, } impl ModuleContextBuilder { pub fn new() -> ModuleContextBuilder { ModuleContextBuilder::default() } pub fn push_memory(&mut self, memory: MemoryType) { self.memories.push(memory); } pub fn push_table(&mut self, table: TableType) { self.tables.push(table); } pub fn push_global(&mut self, global: GlobalType) { self.globals.push(global); } pub fn set_types(&mut self, types: Vec<FunctionType>) { self.types = types; } pub fn push_func_type_index(&mut self, func_type_index: u32) { self.func_type_indexes.push(func_type_index); } pub fn build(self) -> ModuleContext { let ModuleContextBuilder { memories, tables, globals, types, func_type_indexes, } = self; ModuleContext { memories, tables, globals, types, func_type_indexes, } } }