use super::{ConstExpr, TableIdx};
use crate::{core::ValType, module::utils::WasmiValueType};
use std::boxed::Box;
#[derive(Debug)]
pub struct ElementSegment {
kind: ElementSegmentKind,
ty: ValType,
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);
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 {
assert!(
element.ty.is_reference_type(),
"only reftypes are allowed as element types but found: {:?}",
element.ty
);
let kind = ElementSegmentKind::from(element.kind);
let ty = WasmiValueType::from(element.ty).into_inner();
let items = match element.items {
wasmparser::ElementItems::Functions(items) => items
.into_iter()
.map(|item| {
item.unwrap_or_else(|error| panic!("failed to parse element item: {error}"))
})
.map(ConstExpr::new_funcref)
.collect::<Box<[_]>>(),
wasmparser::ElementItems::Expressions(items) => items
.into_iter()
.map(|item| {
item.unwrap_or_else(|error| panic!("failed to parse element item: {error}"))
})
.map(ConstExpr::new)
.collect::<Box<[_]>>(),
};
Self { kind, ty, items }
}
}
impl ElementSegment {
pub fn kind(&self) -> &ElementSegmentKind {
&self.kind
}
pub fn ty(&self) -> ValType {
self.ty
}
pub fn items(&self) -> &[ConstExpr] {
&self.items[..]
}
}