swasmi_validation/
context.rs

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