wasmer_types/
module.rs

1// This file contains code from external sources.
2// Attributions: https://github.com/wasmerio/wasmer/blob/master/ATTRIBUTIONS.md
3
4//! Data structure for representing WebAssembly modules in a
5//! `wasmer::Module`.
6
7use crate::entity::{EntityRef, PrimaryMap};
8use crate::ArchivableIndexMap;
9use crate::{
10    CustomSectionIndex, DataIndex, ElemIndex, ExportIndex, FunctionIndex, FunctionType,
11    GlobalIndex, GlobalInit, GlobalType, ImportIndex, LocalFunctionIndex, LocalGlobalIndex,
12    LocalMemoryIndex, LocalTableIndex, MemoryIndex, MemoryType, OwnedTableInitializer,
13    SignatureIndex, TableIndex, TableType,
14};
15use indexmap::IndexMap;
16use rkyv::{
17    de::SharedDeserializeRegistry, ser::ScratchSpace, ser::Serializer,
18    ser::SharedSerializeRegistry, Archive, Archived, Fallible,
19};
20use std::collections::BTreeMap;
21use std::collections::HashMap;
22use std::fmt;
23use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
24use std::sync::Arc;
25
26#[derive(Debug, Clone, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)]
27pub struct ModuleId {
28    id: usize,
29}
30
31impl ModuleId {
32    pub fn id(&self) -> String {
33        format!("{}", &self.id)
34    }
35}
36
37impl Default for ModuleId {
38    fn default() -> Self {
39        static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
40        Self {
41            id: NEXT_ID.fetch_add(1, SeqCst),
42        }
43    }
44}
45
46/// The counts of imported entities in a WebAssembly module.
47#[derive(
48    Debug, Copy, Clone, Default, PartialEq, Eq, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
49)]
50#[archive(as = "Self")]
51pub struct ImportCounts {
52    /// Number of imported functions in the module.
53    pub functions: u32,
54
55    /// Number of imported tables in the module.
56    pub tables: u32,
57
58    /// Number of imported memories in the module.
59    pub memories: u32,
60
61    /// Number of imported globals in the module.
62    pub globals: u32,
63}
64
65impl ImportCounts {
66    fn make_local<R: EntityRef, I: EntityRef>(idx: I, imports: u32) -> Result<R, I> {
67        EntityRef::index(idx)
68            .checked_sub(imports as _)
69            .map(R::new)
70            .ok_or(idx)
71    }
72
73    /// Convert the `FunctionIndex` to a `LocalFunctionIndex`.
74    pub fn local_function_index(
75        &self,
76        idx: FunctionIndex,
77    ) -> Result<LocalFunctionIndex, FunctionIndex> {
78        Self::make_local(idx, self.functions)
79    }
80
81    /// Convert the `TableIndex` to a `LocalTableIndex`.
82    pub fn local_table_index(&self, idx: TableIndex) -> Result<LocalTableIndex, TableIndex> {
83        Self::make_local(idx, self.tables)
84    }
85
86    /// Convert the `MemoryIndex` to a `LocalMemoryIndex`.
87    pub fn local_memory_index(&self, idx: MemoryIndex) -> Result<LocalMemoryIndex, MemoryIndex> {
88        Self::make_local(idx, self.memories)
89    }
90
91    /// Convert the `GlobalIndex` to a `LocalGlobalIndex`.
92    pub fn local_global_index(&self, idx: GlobalIndex) -> Result<LocalGlobalIndex, GlobalIndex> {
93        Self::make_local(idx, self.globals)
94    }
95
96    fn make_index<R: EntityRef, I: EntityRef>(idx: I, imports: u32) -> R {
97        let imports = imports as usize;
98        R::new(idx.index() + imports)
99    }
100
101    /// Convert the `LocalFunctionIndex` to a `FunctionIndex`.
102    pub fn function_index(&self, idx: LocalFunctionIndex) -> FunctionIndex {
103        Self::make_index(idx, self.functions)
104    }
105
106    /// Convert the `LocalTableIndex` to a `TableIndex`.
107    pub fn table_index(&self, idx: LocalTableIndex) -> TableIndex {
108        Self::make_index(idx, self.tables)
109    }
110
111    /// Convert the `LocalMemoryIndex` to a `MemoryIndex`.
112    pub fn memory_index(&self, idx: LocalMemoryIndex) -> MemoryIndex {
113        Self::make_index(idx, self.memories)
114    }
115
116    /// Convert the `LocalGlobalIndex` to a `GlobalIndex`.
117    pub fn global_index(&self, idx: LocalGlobalIndex) -> GlobalIndex {
118        Self::make_index(idx, self.globals)
119    }
120}
121
122/// A translated WebAssembly module, excluding the function bodies and
123/// memory initializers.
124#[derive(Debug, Clone, Default)]
125pub struct ModuleInfo {
126    /// A unique identifier (within this process) for this module.
127    ///
128    /// We skip serialization/deserialization of this field, as it
129    /// should be computed by the process.
130    ///
131    /// It's not skipped in rkyv, but that is okay, because even though it's skipped in
132    /// bincode/serde it's still deserialized back as a garbage number, and later override from
133    /// computed by the process
134    pub id: ModuleId,
135
136    /// The name of this wasm module, often found in the wasm file.
137    pub name: Option<String>,
138
139    /// Imported entities with the (module, field, index_of_the_import)
140    ///
141    /// Keeping the `index_of_the_import` is important, as there can be
142    /// two same references to the same import, and we don't want to confuse
143    /// them.
144    pub imports: IndexMap<(String, String, u32), ImportIndex>,
145
146    /// Exported entities.
147    pub exports: IndexMap<String, ExportIndex>,
148
149    /// The module "start" function, if present.
150    pub start_function: Option<FunctionIndex>,
151
152    /// WebAssembly table initializers.
153    pub table_initializers: Vec<OwnedTableInitializer>,
154
155    /// WebAssembly passive elements.
156    pub passive_elements: BTreeMap<ElemIndex, Box<[FunctionIndex]>>,
157
158    /// WebAssembly passive data segments.
159    pub passive_data: BTreeMap<DataIndex, Arc<[u8]>>,
160
161    /// WebAssembly global initializers.
162    pub global_initializers: PrimaryMap<LocalGlobalIndex, GlobalInit>,
163
164    /// WebAssembly function names.
165    pub function_names: HashMap<FunctionIndex, String>,
166
167    /// WebAssembly function signatures.
168    pub signatures: PrimaryMap<SignatureIndex, FunctionType>,
169
170    /// WebAssembly functions (imported and local).
171    pub functions: PrimaryMap<FunctionIndex, SignatureIndex>,
172
173    /// WebAssembly tables (imported and local).
174    pub tables: PrimaryMap<TableIndex, TableType>,
175
176    /// WebAssembly linear memories (imported and local).
177    pub memories: PrimaryMap<MemoryIndex, MemoryType>,
178
179    /// WebAssembly global variables (imported and local).
180    pub globals: PrimaryMap<GlobalIndex, GlobalType>,
181
182    /// Custom sections in the module.
183    pub custom_sections: IndexMap<String, CustomSectionIndex>,
184
185    /// The data for each CustomSection in the module.
186    pub custom_sections_data: PrimaryMap<CustomSectionIndex, Arc<[u8]>>,
187
188    /// The counts of imported entities.
189    pub import_counts: ImportCounts,
190}
191
192/// Mirror version of ModuleInfo that can derive rkyv traits
193#[derive(rkyv::Serialize, rkyv::Deserialize, rkyv::Archive)]
194pub struct ArchivableModuleInfo {
195    pub name: Option<String>,
196    pub imports: ArchivableIndexMap<(String, String, u32), ImportIndex>,
197    pub exports: ArchivableIndexMap<String, ExportIndex>,
198    pub start_function: Option<FunctionIndex>,
199    pub table_initializers: Vec<OwnedTableInitializer>,
200    pub passive_elements: BTreeMap<ElemIndex, Box<[FunctionIndex]>>,
201    pub passive_data: BTreeMap<DataIndex, Arc<[u8]>>,
202    pub global_initializers: PrimaryMap<LocalGlobalIndex, GlobalInit>,
203    pub function_names: BTreeMap<FunctionIndex, String>,
204    pub signatures: PrimaryMap<SignatureIndex, FunctionType>,
205    pub functions: PrimaryMap<FunctionIndex, SignatureIndex>,
206    pub tables: PrimaryMap<TableIndex, TableType>,
207    pub memories: PrimaryMap<MemoryIndex, MemoryType>,
208    pub globals: PrimaryMap<GlobalIndex, GlobalType>,
209    pub custom_sections: ArchivableIndexMap<String, CustomSectionIndex>,
210    pub custom_sections_data: PrimaryMap<CustomSectionIndex, Arc<[u8]>>,
211    pub import_counts: ImportCounts,
212}
213
214impl From<ModuleInfo> for ArchivableModuleInfo {
215    fn from(it: ModuleInfo) -> ArchivableModuleInfo {
216        ArchivableModuleInfo {
217            name: it.name,
218            imports: ArchivableIndexMap::from(it.imports),
219            exports: ArchivableIndexMap::from(it.exports),
220            start_function: it.start_function,
221            table_initializers: it.table_initializers,
222            passive_elements: it.passive_elements.into_iter().collect(),
223            passive_data: it.passive_data.into_iter().collect(),
224            global_initializers: it.global_initializers,
225            function_names: it.function_names.into_iter().collect(),
226            signatures: it.signatures,
227            functions: it.functions,
228            tables: it.tables,
229            memories: it.memories,
230            globals: it.globals,
231            custom_sections: ArchivableIndexMap::from(it.custom_sections),
232            custom_sections_data: it.custom_sections_data,
233            import_counts: it.import_counts,
234        }
235    }
236}
237
238impl From<ArchivableModuleInfo> for ModuleInfo {
239    fn from(it: ArchivableModuleInfo) -> ModuleInfo {
240        ModuleInfo {
241            id: Default::default(),
242            name: it.name,
243            imports: it.imports.into(),
244            exports: it.exports.into(),
245            start_function: it.start_function,
246            table_initializers: it.table_initializers,
247            passive_elements: it.passive_elements.into_iter().collect(),
248            passive_data: it.passive_data.into_iter().collect(),
249            global_initializers: it.global_initializers,
250            function_names: it.function_names.into_iter().collect(),
251            signatures: it.signatures,
252            functions: it.functions,
253            tables: it.tables,
254            memories: it.memories,
255            globals: it.globals,
256            custom_sections: it.custom_sections.into(),
257            custom_sections_data: it.custom_sections_data,
258            import_counts: it.import_counts,
259        }
260    }
261}
262
263impl From<&ModuleInfo> for ArchivableModuleInfo {
264    fn from(it: &ModuleInfo) -> ArchivableModuleInfo {
265        ArchivableModuleInfo::from(it.clone())
266    }
267}
268
269impl Archive for ModuleInfo {
270    type Archived = <ArchivableModuleInfo as Archive>::Archived;
271    type Resolver = <ArchivableModuleInfo as Archive>::Resolver;
272
273    unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
274        ArchivableModuleInfo::from(self).resolve(pos, resolver, out)
275    }
276}
277
278impl<S: Serializer + SharedSerializeRegistry + ScratchSpace + ?Sized> rkyv::Serialize<S>
279    for ModuleInfo
280{
281    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
282        ArchivableModuleInfo::from(self).serialize(serializer)
283    }
284}
285
286impl<D: Fallible + ?Sized + SharedDeserializeRegistry> rkyv::Deserialize<ModuleInfo, D>
287    for Archived<ModuleInfo>
288{
289    fn deserialize(&self, deserializer: &mut D) -> Result<ModuleInfo, D::Error> {
290        let r: ArchivableModuleInfo =
291            rkyv::Deserialize::<ArchivableModuleInfo, D>::deserialize(self, deserializer)?;
292        Ok(ModuleInfo::from(r))
293    }
294}
295
296// For test serialization correctness, everything except module id should be same
297impl PartialEq for ModuleInfo {
298    fn eq(&self, other: &ModuleInfo) -> bool {
299        self.name == other.name
300            && self.imports == other.imports
301            && self.exports == other.exports
302            && self.start_function == other.start_function
303            && self.table_initializers == other.table_initializers
304            && self.passive_elements == other.passive_elements
305            && self.passive_data == other.passive_data
306            && self.global_initializers == other.global_initializers
307            && self.function_names == other.function_names
308            && self.signatures == other.signatures
309            && self.functions == other.functions
310            && self.tables == other.tables
311            && self.memories == other.memories
312            && self.globals == other.globals
313            && self.custom_sections == other.custom_sections
314            && self.custom_sections_data == other.custom_sections_data
315            && self.import_counts == other.import_counts
316    }
317}
318
319impl Eq for ModuleInfo {}
320
321impl ModuleInfo {
322    /// Allocates the module data structures.
323    pub fn new() -> Self {
324        Default::default()
325    }
326
327    /// Get the given passive element, if it exists.
328    pub fn get_passive_element(&self, index: ElemIndex) -> Option<&[FunctionIndex]> {
329        self.passive_elements.get(&index).map(|es| &**es)
330    }
331
332    /// Get the exported signatures of the module
333    pub fn exported_signatures(&self) -> Vec<FunctionType> {
334        self.exports
335            .iter()
336            .filter_map(|(_name, export_index)| match export_index {
337                ExportIndex::Function(i) => {
338                    let signature = self.functions.get(*i).unwrap();
339                    let func_type = self.signatures.get(*signature).unwrap();
340                    Some(func_type.clone())
341                }
342                _ => None,
343            })
344            .collect::<Vec<FunctionType>>()
345    }
346
347    /// Get the custom sections of the module given a `name`.
348    pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator<Item = Arc<[u8]>> + 'a {
349        self.custom_sections
350            .iter()
351            .filter_map(move |(section_name, section_index)| {
352                if name != section_name {
353                    return None;
354                }
355                Some(self.custom_sections_data[*section_index].clone())
356            })
357    }
358
359    /// Convert a `LocalFunctionIndex` into a `FunctionIndex`.
360    pub fn func_index(&self, local_func: LocalFunctionIndex) -> FunctionIndex {
361        self.import_counts.function_index(local_func)
362    }
363
364    /// Convert a `FunctionIndex` into a `LocalFunctionIndex`. Returns None if the
365    /// index is an imported function.
366    pub fn local_func_index(&self, func: FunctionIndex) -> Option<LocalFunctionIndex> {
367        self.import_counts.local_function_index(func).ok()
368    }
369
370    /// Test whether the given function index is for an imported function.
371    pub fn is_imported_function(&self, index: FunctionIndex) -> bool {
372        self.local_func_index(index).is_none()
373    }
374
375    /// Convert a `LocalTableIndex` into a `TableIndex`.
376    pub fn table_index(&self, local_table: LocalTableIndex) -> TableIndex {
377        self.import_counts.table_index(local_table)
378    }
379
380    /// Convert a `TableIndex` into a `LocalTableIndex`. Returns None if the
381    /// index is an imported table.
382    pub fn local_table_index(&self, table: TableIndex) -> Option<LocalTableIndex> {
383        self.import_counts.local_table_index(table).ok()
384    }
385
386    /// Test whether the given table index is for an imported table.
387    pub fn is_imported_table(&self, index: TableIndex) -> bool {
388        self.local_table_index(index).is_none()
389    }
390
391    /// Convert a `LocalMemoryIndex` into a `MemoryIndex`.
392    pub fn memory_index(&self, local_memory: LocalMemoryIndex) -> MemoryIndex {
393        self.import_counts.memory_index(local_memory)
394    }
395
396    /// Convert a `MemoryIndex` into a `LocalMemoryIndex`. Returns None if the
397    /// index is an imported memory.
398    pub fn local_memory_index(&self, memory: MemoryIndex) -> Option<LocalMemoryIndex> {
399        self.import_counts.local_memory_index(memory).ok()
400    }
401
402    /// Test whether the given memory index is for an imported memory.
403    pub fn is_imported_memory(&self, index: MemoryIndex) -> bool {
404        self.local_memory_index(index).is_none()
405    }
406
407    /// Convert a `LocalGlobalIndex` into a `GlobalIndex`.
408    pub fn global_index(&self, local_global: LocalGlobalIndex) -> GlobalIndex {
409        self.import_counts.global_index(local_global)
410    }
411
412    /// Convert a `GlobalIndex` into a `LocalGlobalIndex`. Returns None if the
413    /// index is an imported global.
414    pub fn local_global_index(&self, global: GlobalIndex) -> Option<LocalGlobalIndex> {
415        self.import_counts.local_global_index(global).ok()
416    }
417
418    /// Test whether the given global index is for an imported global.
419    pub fn is_imported_global(&self, index: GlobalIndex) -> bool {
420        self.local_global_index(index).is_none()
421    }
422
423    /// Get the Module name
424    pub fn name(&self) -> String {
425        match self.name {
426            Some(ref name) => name.to_string(),
427            None => "<module>".to_string(),
428        }
429    }
430
431    /// Get the imported function types of the module.
432    pub fn imported_function_types<'a>(&'a self) -> impl Iterator<Item = FunctionType> + 'a {
433        self.functions
434            .values()
435            .take(self.import_counts.functions as usize)
436            .map(move |sig_index| self.signatures[*sig_index].clone())
437    }
438}
439
440impl fmt::Display for ModuleInfo {
441    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
442        write!(f, "{}", self.name())
443    }
444}