1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use super::{ConstExpr, TableIdx};
use crate::ValType;
use alloc::boxed::Box;
/// A table element segment within a [`Module`].
///
/// [`Module`]: [`super::Module`]
#[derive(Debug)]
pub struct ElementSegment {
/// The kind of the [`ElementSegment`].
kind: ElementSegmentKind,
/// The type of elements of the [`ElementSegment`].
ty: ValType,
/// The items of the [`ElementSegment`].
items: Box<[ConstExpr]>,
}
/// The kind of a Wasm [`ElementSegment`].
#[derive(Debug)]
pub enum ElementSegmentKind {
/// A passive [`ElementSegment`] from the `bulk-memory` Wasm proposal.
Passive,
/// An active [`ElementSegment`].
Active(ActiveElementSegment),
/// A declared [`ElementSegment`] from the `reference-types` Wasm proposal.
Declared,
}
/// An active Wasm element segment.
#[derive(Debug)]
pub struct ActiveElementSegment {
/// The index of the Wasm table that is to be initialized.
table_index: TableIdx,
/// The offset where the Wasm table is to be initialized.
offset: ConstExpr,
}
impl ActiveElementSegment {
/// Returns the Wasm module table index that is to be initialized.
pub fn table_index(&self) -> TableIdx {
self.table_index
}
/// Returns the offset expression of the [`ActiveElementSegment`].
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, ValType::FuncRef)
}
wasmparser::ElementItems::Expressions(ref_ty, items) => {
let ty = match ref_ty {
ty if ty.is_func_ref() => ValType::FuncRef,
ty if ty.is_extern_ref() => ValType::ExternRef,
_ => 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 {
/// Returns the offset expression of the [`ElementSegment`].
pub fn kind(&self) -> &ElementSegmentKind {
&self.kind
}
/// Returns the [`ValType`] of the [`ElementSegment`].
pub fn ty(&self) -> ValType {
self.ty
}
/// Returns the element items of the [`ElementSegment`].
pub fn items(&self) -> &[ConstExpr] {
&self.items[..]
}
}