twasmi_validation/
context.rs

1use 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}