wasm/execution/runtime_structure/
external_values.rs

1use crate::{Config, ExternType, FuncAddr, GlobalAddr, MemAddr, Store, TableAddr};
2
3///<https://webassembly.github.io/spec/core/exec/runtime.html#external-values>
4#[derive(Debug, Copy, Clone, PartialEq, Eq)]
5pub enum ExternVal {
6    Func(FuncAddr),
7    Table(TableAddr),
8    Mem(MemAddr),
9    Global(GlobalAddr),
10}
11
12impl ExternVal {
13    /// returns the external type of `self` according to typing relation,
14    /// taking `store` as context S.
15    ///
16    /// # Safety
17    /// The caller has to guarantee that `self` came from the same [`Store`] which
18    /// is passed now as a reference.
19    pub fn extern_type<T: Config>(&self, store: &Store<T>) -> ExternType {
20        match self {
21            // TODO: fix ugly clone in function types
22            ExternVal::Func(func_addr) => {
23                // SAFETY: The caller ensures that self including the function
24                // address in self is valid in the given store.
25                let function = unsafe { store.inner.functions.get(*func_addr) };
26                ExternType::Func(function.ty().clone())
27            }
28            ExternVal::Table(table_addr) => {
29                // SAFETY: The caller ensures that self including the table
30                // address in self is valid in the given store.
31                let table = unsafe { store.inner.tables.get(*table_addr) };
32                ExternType::Table(table.ty)
33            }
34            ExternVal::Mem(mem_addr) => {
35                // SAFETY: The caller ensures that self including the memory
36                // address in self is valid in the given store.
37                let memory = unsafe { store.inner.memories.get(*mem_addr) };
38                ExternType::Mem(memory.ty)
39            }
40            ExternVal::Global(global_addr) => {
41                // SAFETY: The caller ensures that self including the global
42                // address in self is valid in the given store.
43                let global = unsafe { store.inner.globals.get(*global_addr) };
44                ExternType::Global(global.ty)
45            }
46        }
47    }
48}
49
50impl ExternVal {
51    pub fn as_func(self) -> Option<FuncAddr> {
52        match self {
53            ExternVal::Func(func_addr) => Some(func_addr),
54            _ => None,
55        }
56    }
57
58    pub fn as_table(self) -> Option<TableAddr> {
59        match self {
60            ExternVal::Table(table_addr) => Some(table_addr),
61            _ => None,
62        }
63    }
64
65    pub fn as_mem(self) -> Option<MemAddr> {
66        match self {
67            ExternVal::Mem(mem_addr) => Some(mem_addr),
68            _ => None,
69        }
70    }
71
72    pub fn as_global(self) -> Option<GlobalAddr> {
73        match self {
74            ExternVal::Global(global_addr) => Some(global_addr),
75            _ => None,
76        }
77    }
78}
79
80/// common convention functions defined for lists of ExternVals, ExternTypes, Exports
81/// <https://webassembly.github.io/spec/core/exec/runtime.html#conventions>
82/// <https://webassembly.github.io/spec/core/syntax/types.html#id3>
83/// <https://webassembly.github.io/spec/core/syntax/modules.html?highlight=convention#id1>
84// TODO implement this trait for ExternType lists Export lists
85pub trait ExternFilterable {
86    fn funcs(self) -> impl Iterator<Item = FuncAddr>;
87    fn tables(self) -> impl Iterator<Item = TableAddr>;
88    fn mems(self) -> impl Iterator<Item = MemAddr>;
89    fn globals(self) -> impl Iterator<Item = GlobalAddr>;
90}
91
92impl<'a, I> ExternFilterable for I
93where
94    I: Iterator<Item = &'a ExternVal>,
95{
96    fn funcs(self) -> impl Iterator<Item = FuncAddr> {
97        self.filter_map(|extern_val| extern_val.as_func())
98    }
99
100    fn tables(self) -> impl Iterator<Item = TableAddr> {
101        self.filter_map(|extern_val| extern_val.as_table())
102    }
103
104    fn mems(self) -> impl Iterator<Item = MemAddr> {
105        self.filter_map(|extern_val| extern_val.as_mem())
106    }
107
108    fn globals(self) -> impl Iterator<Item = GlobalAddr> {
109        self.filter_map(|extern_val| extern_val.as_global())
110    }
111}