wasmi_validation/
context.rs

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