wasmi/module/
element.rs

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
use super::{ConstExpr, TableIdx};
use crate::{core::ValType, module::utils::WasmiValueType};
use std::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);
                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 {
    /// 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[..]
    }
}