use crate::ir::id::{FunctionID, ImportsID};
use wasmparser::TypeRef;
#[derive(Debug, Clone)]
pub struct Import<'a> {
pub module: &'a str,
pub name: &'a str,
pub ty: TypeRef,
pub custom_name: Option<String>,
pub(crate) deleted: bool,
}
impl<'a> From<wasmparser::Import<'a>> for Import<'a> {
fn from(import: wasmparser::Import<'a>) -> Self {
Import {
module: import.module,
name: import.name,
ty: import.ty,
custom_name: None,
deleted: false,
}
}
}
impl Import<'_> {
pub fn is_function(&self) -> bool {
matches!(self.ty, TypeRef::Func(_))
}
pub fn is_global(&self) -> bool {
matches!(self.ty, TypeRef::Global(_))
}
pub fn is_table(&self) -> bool {
matches!(self.ty, TypeRef::Table(_))
}
pub fn is_tag(&self) -> bool {
matches!(self.ty, TypeRef::Tag(_))
}
pub fn is_memory(&self) -> bool {
matches!(self.ty, TypeRef::Memory(_))
}
}
#[derive(Clone, Debug, Default)]
pub struct ModuleImports<'a> {
imports: Vec<Import<'a>>,
pub(crate) num_funcs: u32,
pub(crate) num_funcs_added: u32,
pub(crate) num_globals: u32,
pub(crate) num_globals_added: u32,
pub(crate) num_tables: u32,
pub(crate) num_tables_added: u32,
pub(crate) num_tags: u32,
pub(crate) num_tags_added: u32,
pub(crate) num_memories: u32,
pub(crate) num_memories_added: u32,
}
impl<'a> ModuleImports<'a> {
pub fn new(imports: Vec<Import<'a>>) -> Self {
let mut def = Self::default();
for import in imports.iter() {
if import.is_function() {
def.num_funcs += 1;
} else if import.is_global() {
def.num_globals += 1;
} else if import.is_table() {
def.num_tables += 1;
} else if import.is_tag() {
def.num_tags += 1;
} else if import.is_memory() {
def.num_memories += 1;
}
}
def.imports = imports;
def
}
pub fn is_empty(&self) -> bool {
self.imports.is_empty()
}
pub fn iter(&self) -> std::slice::Iter<'_, Import<'a>> {
self.imports.iter()
}
pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, Import<'a>> {
self.imports.iter_mut()
}
pub fn set_name(&mut self, name: String, imports_id: ImportsID) {
self.imports[*imports_id as usize].custom_name = Some(name)
}
pub fn set_fn_name(&mut self, name: String, func_id: FunctionID) {
for (curr_fn_id, import) in (0_u32..).zip(self.imports.iter_mut()) {
if import.is_function() && curr_fn_id == *func_id {
import.custom_name = Some(name);
return;
}
}
}
pub fn len(&self) -> usize {
self.imports.len()
}
pub(crate) fn add<'b>(&'b mut self, import: Import<'a>) -> ImportsID {
match import.ty {
TypeRef::Func(..) => {
self.num_funcs += 1;
self.num_funcs_added += 1;
}
TypeRef::Global(..) => {
self.num_globals += 1;
self.num_globals_added += 1;
}
TypeRef::Table(..) => {
self.num_tables += 1;
self.num_tables_added += 1;
}
TypeRef::Tag(..) => {
self.num_tags += 1;
self.num_tags_added += 1;
}
TypeRef::Memory(..) => {
self.num_memories += 1;
self.num_memories_added += 1;
}
}
self.imports.push(import);
ImportsID((self.imports.len() - 1) as u32)
}
pub(crate) fn delete(&mut self, imports_id: ImportsID) {
self.imports[*imports_id as usize].deleted = true;
}
pub fn find(&self, module: String, name: String) -> Option<ImportsID> {
for (id, imp) in self.imports.iter().enumerate() {
if imp.module == module.as_str() && imp.name == name.as_str() {
return Some(ImportsID(id as u32));
}
}
None
}
pub fn get_func(&self, module: String, name: String) -> Option<FunctionID> {
for (idx, imp) in self.imports.iter().enumerate() {
if imp.is_function() && imp.module == module.as_str() && *imp.name == name {
return Some(FunctionID(idx as u32));
}
}
None
}
pub fn get(&self, id: ImportsID) -> &Import {
&self.imports[*id as usize]
}
pub fn get_import_name(&self, imports_id: ImportsID) -> &Option<String> {
&self.imports[*imports_id as usize].custom_name
}
}