use crate::{
Engine,
FuncType,
ValType,
engine::DedupFuncType,
module::{FuncTypeIdx, ModuleHeader, utils::WasmiValueType},
};
#[derive(Debug, Copy, Clone)]
pub struct BlockType {
inner: BlockTypeInner,
}
#[derive(Debug, Copy, Clone)]
pub enum BlockTypeInner {
Empty,
Returns(ValType),
FuncType(DedupFuncType),
}
impl BlockType {
pub fn new(block_type: wasmparser::BlockType, res: &ModuleHeader) -> Self {
match block_type {
wasmparser::BlockType::Empty => Self::empty(),
wasmparser::BlockType::Type(return_type) => {
let return_type = WasmiValueType::from(return_type).into_inner();
Self::returns(return_type)
}
wasmparser::BlockType::FuncType(func_type_idx) => {
let dedup_func_type = res.get_func_type(FuncTypeIdx::from(func_type_idx));
Self::func_type(dedup_func_type)
}
}
}
fn from_inner(inner: BlockTypeInner) -> Self {
Self { inner }
}
fn empty() -> Self {
Self::from_inner(BlockTypeInner::Empty)
}
fn returns(return_type: ValType) -> Self {
Self::from_inner(BlockTypeInner::Returns(return_type))
}
pub(crate) fn func_type(func_type: &DedupFuncType) -> Self {
Self::from_inner(BlockTypeInner::FuncType(*func_type))
}
pub fn len_params(&self, engine: &Engine) -> u16 {
match &self.inner {
BlockTypeInner::Empty | BlockTypeInner::Returns(_) => 0,
BlockTypeInner::FuncType(func_type) => {
engine.resolve_func_type(func_type, FuncType::len_params)
}
}
}
pub fn len_results(&self, engine: &Engine) -> u16 {
match &self.inner {
BlockTypeInner::Empty => 0,
BlockTypeInner::Returns(_) => 1,
BlockTypeInner::FuncType(func_type) => {
engine.resolve_func_type(func_type, FuncType::len_results)
}
}
}
pub fn func_type_with<R>(&self, engine: &Engine, f: impl for<'a> FnOnce(&FuncType) -> R) -> R {
match &self.inner {
BlockTypeInner::Empty => f(&FuncType::new([], [])),
BlockTypeInner::Returns(return_type) => f(&FuncType::new([], [*return_type])),
BlockTypeInner::FuncType(func_type) => engine.resolve_func_type(func_type, f),
}
}
}