///| Element segments initialise tables or provide passive/declarative function
///| references. The MVP decoder supports the function-index forms used by the
///|
/// core binary format and reports expression-based reference forms explicitly.
pub enum ElementMode {
ActiveElement(Int, Span)
PassiveElement
DeclarativeElement
}
///|
pub struct ElementSegment {
mode : ElementMode
functions : Array[Int]
}
///|
pub fn ElementSegment::description(self : ElementSegment) -> String {
let mode = match self.mode {
ActiveElement(table, _) => "active table=" + table.to_string()
PassiveElement => "passive"
DeclarativeElement => "declarative"
}
mode + " functions=" + self.functions.length().to_string()
}
///|
fn read_function_indices(cursor : Cursor) -> Result[Array[Int], DecodeError] {
let count = match cursor.read_var_u32() {
Ok(value) => value
Err(error) => return Err(error)
}
let indices : Array[Int] = []
for _ in 0.. indices.push(value)
Err(error) => return Err(error)
}
}
Ok(indices)
}
///|
pub fn decode_element_segments(
binary : Module,
) -> Result[Array[ElementSegment], DecodeError] {
let cursor = match section_cursor(binary, Element) {
Some(value) => value
None => return Ok([])
}
let count = match cursor.read_var_u32() {
Ok(value) => value
Err(error) => return Err(error)
}
let segments : Array[ElementSegment] = []
for _ in 0.. value
Err(error) => return Err(error)
}
let mode = match flags {
0 => {
let offset = match skip_const_expr(cursor) {
Ok(value) => value
Err(error) => return Err(error)
}
ActiveElement(0, offset)
}
1 => {
match cursor.read_u8() {
Ok(0) => ()
Ok(_) =>
return Err(UnsupportedFeature("non-funcref element type", position))
Err(error) => return Err(error)
}
PassiveElement
}
2 => {
let table = match cursor.read_var_u32() {
Ok(value) => value
Err(error) => return Err(error)
}
let offset = match skip_const_expr(cursor) {
Ok(value) => value
Err(error) => return Err(error)
}
match cursor.read_u8() {
Ok(0) => ()
Ok(_) =>
return Err(UnsupportedFeature("non-funcref element type", position))
Err(error) => return Err(error)
}
ActiveElement(table, offset)
}
3 => {
match cursor.read_u8() {
Ok(0) => ()
Ok(_) =>
return Err(UnsupportedFeature("non-funcref element type", position))
Err(error) => return Err(error)
}
DeclarativeElement
}
4..=7 =>
return Err(
UnsupportedFeature("expression-based element segment", position),
)
_ =>
return Err(
UnsupportedFeature(
"element segment flag " + flags.to_string(),
position,
),
)
}
let functions = match read_function_indices(cursor) {
Ok(value) => value
Err(error) => return Err(error)
}
segments.push({ mode, functions })
}
match expect_finished(cursor, Element) {
Ok(_) => Ok(segments)
Err(error) => Err(error)
}
}
///|
pub fn render_element_segments(segments : Array[ElementSegment]) -> String {
let mut text = "element segments: " + segments.length().to_string() + "\n"
let mut index = 0
for segment in segments {
text = text +
" [" +
index.to_string() +
"] " +
segment.description() +
"\n"
index = index + 1
}
text
}