use super::{ConstExpr, TableIdx};
use crate::RefType;
use alloc::boxed::Box;
#[derive(Debug)]
pub struct ElementSegment {
kind: ElementSegmentKind,
ty: RefType,
items: Box<[ConstExpr]>,
}
#[derive(Debug)]
pub enum ElementSegmentKind {
Passive,
Active(ActiveElementSegment),
Declared,
}
#[derive(Debug)]
pub struct ActiveElementSegment {
table_index: TableIdx,
offset: ConstExpr,
}
impl ActiveElementSegment {
pub fn table_index(&self) -> TableIdx {
self.table_index
}
pub fn offset(&self) -> &ConstExpr {
&self.offset
}
}
impl From<wasmparser::ElementKind<'_>> for ElementSegmentKind {
fn from(element_kind: wasmparser::ElementKind<'_>) -> Self {
match element_kind {
wasmparser::ElementKind::Active {
table_index,
offset_expr,
} => {
let table_index = TableIdx::from(table_index.unwrap_or(0));
let offset = ConstExpr::new(offset_expr);
Self::Active(ActiveElementSegment {
table_index,
offset,
})
}
wasmparser::ElementKind::Passive => Self::Passive,
wasmparser::ElementKind::Declared => Self::Declared,
}
}
}
impl From<wasmparser::Element<'_>> for ElementSegment {
fn from(element: wasmparser::Element<'_>) -> Self {
let kind = ElementSegmentKind::from(element.kind);
let (items, ty) = match element.items {
wasmparser::ElementItems::Functions(items) => {
let items = items
.into_iter()
.map(|item| {
item.unwrap_or_else(|error| panic!("failed to parse element item: {error}"))
})
.map(ConstExpr::new_funcref)
.collect::<Box<[_]>>();
(items, RefType::Func)
}
wasmparser::ElementItems::Expressions(ref_ty, items) => {
let ty = match ref_ty {
ty if ty.is_func_ref() => RefType::Func,
ty if ty.is_extern_ref() => RefType::Extern,
_ => panic!("unsupported Wasm reference type"),
};
let items = items
.into_iter()
.map(|item| {
item.unwrap_or_else(|error| panic!("failed to parse element item: {error}"))
})
.map(ConstExpr::new)
.collect::<Box<[_]>>();
(items, ty)
}
};
Self { kind, ty, items }
}
}
impl ElementSegment {
pub fn kind(&self) -> &ElementSegmentKind {
&self.kind
}
pub fn ty(&self) -> RefType {
self.ty
}
pub fn items(&self) -> &[ConstExpr] {
&self.items[..]
}
}