135 lines
3.2 KiB
Rust
135 lines
3.2 KiB
Rust
|
use parity_wasm::elements::{MemoryType, TableType, GlobalType, BlockType, ValueType, FunctionType};
|
||
|
use validation::Error;
|
||
|
|
||
|
#[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,
|
||
|
}
|
||
|
}
|
||
|
}
|