use crate::arena_set::ArenaSet;
use crate::emit::{Emit, EmitContext, Section};
use crate::error::Result;
use crate::module::Module;
use crate::parse::IndicesToIds;
use crate::ty::{Type, TypeId, ValType};
#[derive(Debug, Default)]
pub struct ModuleTypes {
arena: ArenaSet<Type>,
}
impl ModuleTypes {
pub fn get(&self, id: TypeId) -> &Type {
&self.arena[id]
}
pub fn get_mut(&mut self, id: TypeId) -> &mut Type {
&mut self.arena[id]
}
pub fn by_name(&self, name: &str) -> Option<TypeId> {
self.arena.iter().find_map(|(id, ty)| {
if ty.name.as_ref().map(|s| s.as_str()) == Some(name) {
Some(id)
} else {
None
}
})
}
pub fn iter(&self) -> impl Iterator<Item = &Type> {
self.arena.iter().map(|(_, f)| f)
}
pub fn delete(&mut self, ty: TypeId) {
self.arena.remove(ty);
}
pub fn add(&mut self, params: &[ValType], results: &[ValType]) -> TypeId {
let id = self.arena.next_id();
self.arena.insert(Type::new(
id,
params.to_vec().into_boxed_slice(),
results.to_vec().into_boxed_slice(),
))
}
}
impl Module {
pub(crate) fn parse_types(
&mut self,
section: wasmparser::TypeSectionReader,
ids: &mut IndicesToIds,
) -> Result<()> {
log::debug!("parsing type section");
for ty in section {
let fun_ty = ty?;
let id = self.types.arena.next_id();
let params = fun_ty
.params
.iter()
.map(ValType::parse)
.collect::<Result<Vec<_>>>()?
.into_boxed_slice();
let results = fun_ty
.returns
.iter()
.map(ValType::parse)
.collect::<Result<Vec<_>>>()?
.into_boxed_slice();
let id = self.types.arena.insert(Type::new(id, params, results));
ids.push_type(id);
}
Ok(())
}
}
impl Emit for ModuleTypes {
fn emit(&self, cx: &mut EmitContext) {
log::debug!("emitting type section");
let ntypes = self.iter().count();
if ntypes == 0 {
return;
}
let mut cx = cx.start_section(Section::Type);
cx.encoder.usize(ntypes);
for (id, ty) in self.arena.iter() {
cx.indices.push_type(id);
ty.emit(&mut cx);
}
}
}