use crate::error::Error::{InvalidOperation, UnknownId};
use crate::ir::id::TableID;
use crate::ir::types;
use crate::ir::types::{ElementItems, ElementKind, InjectTag, Tag, TagUtils};
use wasmparser::{RefType, TableType};
#[derive(Clone, Debug, Default)]
pub struct ModuleTables<'a> {
tables: Vec<Table<'a>>,
}
impl<'a> ModuleTables<'a> {
pub fn new(tables: Vec<Table<'a>>) -> Self {
ModuleTables { tables }
}
pub fn is_empty(&self) -> bool {
self.tables.is_empty()
}
pub fn iter(&self) -> std::slice::Iter<'_, Table<'_>> {
self.tables.iter()
}
pub fn main_function(&self) -> types::Result<Option<TableID>> {
let mut tables = self
.tables
.iter()
.enumerate()
.filter(|(_, t)| t.ty.element_type == RefType::FUNCREF);
let id = tables.next().map(|(index, _)| TableID(index as u32));
if tables.next().is_some() {
return Err(InvalidOperation(
"module contains more than one function table".to_string(),
));
}
Ok(id)
}
pub fn get(&self, table_id: TableID) -> Option<TableType> {
if *table_id < self.tables.len() as u32 {
return Some(self.tables[*table_id as usize].ty);
}
None
}
pub fn get_mut(&mut self, table_id: TableID) -> types::Result<&mut TableType> {
if *table_id < self.tables.len() as u32 {
return Ok(&mut self.tables[*table_id as usize].ty);
}
Err(UnknownId("Invalid Table ID".to_string()))
}
}
#[derive(Clone, Debug)]
pub struct Table<'a> {
pub ty: TableType,
pub init_expr: Option<wasmparser::ConstExpr<'a>>,
tag: InjectTag,
}
impl TagUtils for Table<'_> {
fn get_or_create_tag(&mut self) -> &mut Tag {
self.tag.get_or_insert_default()
}
fn get_tag(&self) -> &Option<Tag> {
&self.tag
}
}
impl<'a> Table<'a> {
pub fn new(
ty: TableType,
init_expr: Option<wasmparser::ConstExpr<'a>>,
tag: InjectTag,
) -> Self {
Self { ty, init_expr, tag }
}
}
#[derive(Clone, Debug)]
pub struct Element {
pub kind: ElementKind,
pub items: ElementItems,
tag: InjectTag,
}
impl TagUtils for Element {
fn get_or_create_tag(&mut self) -> &mut Tag {
self.tag.get_or_insert_default()
}
fn get_tag(&self) -> &Option<Tag> {
&self.tag
}
}
impl Element {
pub fn new(kind: ElementKind, items: ElementItems, tag: InjectTag) -> Self {
Self { kind, items, tag }
}
}