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