use std::{collections::HashMap, convert::TryFrom, rc::Rc};
#[derive(Default)]
pub struct TypesInterner {
types: Vec<Rc<Type>>,
type_to_index: HashMap<Rc<Type>, u32>,
}
#[derive(PartialEq, Eq, Hash)]
pub enum Type {
Func(wasmparser::FuncType),
}
impl Type {
pub fn is_func(&self) -> bool {
matches!(self, Type::Func(_))
}
}
#[derive(PartialEq, Eq, Hash)]
pub enum EntityType {
Function(TypeId),
Table(wasmparser::TableType),
Memory(wasmparser::MemoryType),
Global(wasmparser::GlobalType),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct TypeId {
index: u32,
}
impl TypesInterner {
pub fn get(&self, id: TypeId) -> &Type {
&*self.types[usize::try_from(id.index).unwrap()]
}
pub fn insert_wasmparser(
&mut self,
ty: wasmparser::CompositeType,
_types_space: &[TypeId],
) -> TypeId {
match ty.inner {
wasmparser::CompositeInnerType::Func(func_ty) => self.insert(Type::Func(func_ty)),
wasmparser::CompositeInnerType::Array(_) => todo!(),
wasmparser::CompositeInnerType::Struct(_) => todo!(),
wasmparser::CompositeInnerType::Cont(_) => todo!(),
}
}
pub fn insert(&mut self, ty: Type) -> TypeId {
if let Some(index) = self.type_to_index.get(&ty).copied() {
return TypeId { index };
}
let index = u32::try_from(self.types.len()).unwrap();
let ty = Rc::new(ty);
self.type_to_index.insert(ty.clone(), index);
self.types.push(ty);
TypeId { index }
}
pub fn entity_type(&self, ty: wasmparser::TypeRef, types_space: &[TypeId]) -> EntityType {
match ty {
wasmparser::TypeRef::Func(idx) => {
EntityType::Function(types_space[usize::try_from(idx).unwrap()])
}
wasmparser::TypeRef::Table(ty) => EntityType::Table(ty),
wasmparser::TypeRef::Memory(ty) => EntityType::Memory(ty),
wasmparser::TypeRef::Global(ty) => EntityType::Global(ty),
wasmparser::TypeRef::Tag(_) => unreachable!(),
}
}
}