use crate::{
collections::arena::ArenaIndex,
core::ValType,
module,
module::{ConstExpr, ElementSegmentItems},
store::Stored,
AsContext,
AsContextMut,
};
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct ElementSegmentIdx(u32);
impl ArenaIndex for ElementSegmentIdx {
fn into_usize(self) -> usize {
self.0 as usize
}
fn from_usize(value: usize) -> Self {
let value = value.try_into().unwrap_or_else(|error| {
panic!("index {value} is out of bounds as element segment index: {error}")
});
Self(value)
}
}
#[derive(Debug, Copy, Clone)]
#[repr(transparent)]
pub struct ElementSegment(Stored<ElementSegmentIdx>);
impl ElementSegment {
pub fn from_inner(stored: Stored<ElementSegmentIdx>) -> Self {
Self(stored)
}
pub fn as_inner(&self) -> &Stored<ElementSegmentIdx> {
&self.0
}
pub fn new(mut ctx: impl AsContextMut, segment: &module::ElementSegment) -> Self {
let entity = ElementSegmentEntity::from(segment);
ctx.as_context_mut()
.store
.inner
.alloc_element_segment(entity)
}
pub fn size(&self, ctx: impl AsContext) -> u32 {
ctx.as_context()
.store
.inner
.resolve_element_segment(self)
.size()
}
pub fn drop_items(&self, mut ctx: impl AsContextMut) {
ctx.as_context_mut()
.store
.inner
.resolve_element_segment_mut(self)
.drop_items()
}
}
#[derive(Debug)]
pub struct ElementSegmentEntity {
ty: ValType,
items: Option<ElementSegmentItems>,
}
impl From<&'_ module::ElementSegment> for ElementSegmentEntity {
fn from(segment: &'_ module::ElementSegment) -> Self {
let ty = segment.ty();
match segment.kind() {
module::ElementSegmentKind::Passive | module::ElementSegmentKind::Active(_) => Self {
ty,
items: Some(segment.items_cloned()),
},
module::ElementSegmentKind::Declared => Self::empty(ty),
}
}
}
impl ElementSegmentEntity {
fn empty(ty: ValType) -> Self {
Self { ty, items: None }
}
pub fn ty(&self) -> ValType {
self.ty
}
pub fn size(&self) -> u32 {
self.items().len() as u32
}
pub fn items(&self) -> &[ConstExpr] {
self.items
.as_ref()
.map(ElementSegmentItems::items)
.unwrap_or(&[])
}
pub fn drop_items(&mut self) {
self.items = None;
}
}