wasmer_types/
module.rs

1// This file contains code from external sources.
2// Attributions: https://github.com/wasmerio/wasmer/blob/main/docs/ATTRIBUTIONS.md
3
4//! Data structure for representing WebAssembly modules in a
5//! `wasmer::Module`.
6
7use crate::entity::{EntityRef, PrimaryMap};
8use crate::{
9    CustomSectionIndex, DataIndex, ElemIndex, ExportIndex, ExportType, ExternType, FunctionIndex,
10    FunctionType, GlobalIndex, GlobalInit, GlobalType, ImportIndex, ImportType, LocalFunctionIndex,
11    LocalGlobalIndex, LocalMemoryIndex, LocalTableIndex, MemoryIndex, MemoryType, ModuleHash,
12    SignatureIndex, TableIndex, TableInitializer, TableType,
13};
14
15use indexmap::IndexMap;
16use rkyv::rancor::{Fallible, Source, Trace};
17use rkyv::{Archive, Deserialize as RkyvDeserialize, Serialize as RkyvSerialize};
18#[cfg(feature = "enable-serde")]
19use serde::{Deserialize, Serialize};
20use std::collections::BTreeMap;
21use std::collections::HashMap;
22use std::fmt;
23use std::iter::ExactSizeIterator;
24use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
25
26#[derive(Debug, Clone, RkyvSerialize, RkyvDeserialize, Archive)]
27#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
28#[rkyv(derive(Debug))]
29pub struct ModuleId {
30    id: usize,
31}
32
33impl ModuleId {
34    pub fn id(&self) -> String {
35        format!("{}", &self.id)
36    }
37}
38
39impl Default for ModuleId {
40    fn default() -> Self {
41        static NEXT_ID: AtomicUsize = AtomicUsize::new(0);
42        Self {
43            id: NEXT_ID.fetch_add(1, SeqCst),
44        }
45    }
46}
47
48/// Hash key of an import
49#[derive(Debug, Hash, Eq, PartialEq, Clone, Default, RkyvSerialize, RkyvDeserialize, Archive)]
50#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
51#[rkyv(derive(PartialOrd, Ord, PartialEq, Eq, Hash, Debug))]
52pub struct ImportKey {
53    /// Module name
54    pub module: String,
55    /// Field name
56    pub field: String,
57    /// Import index
58    pub import_idx: u32,
59}
60
61impl From<(String, String, u32)> for ImportKey {
62    fn from((module, field, import_idx): (String, String, u32)) -> Self {
63        Self {
64            module,
65            field,
66            import_idx,
67        }
68    }
69}
70
71#[cfg(feature = "enable-serde")]
72mod serde_imports {
73
74    use crate::ImportIndex;
75    use crate::ImportKey;
76    use indexmap::IndexMap;
77    use serde::{Deserialize, Deserializer, Serialize, Serializer};
78
79    type InitialType = IndexMap<ImportKey, ImportIndex>;
80    type SerializedType = Vec<(ImportKey, ImportIndex)>;
81    // IndexMap<ImportKey, ImportIndex>
82    // Vec<
83    pub fn serialize<S: Serializer>(s: &InitialType, serializer: S) -> Result<S::Ok, S::Error> {
84        let vec: SerializedType = s
85            .iter()
86            .map(|(a, b)| (a.clone(), b.clone()))
87            .collect::<Vec<_>>();
88        vec.serialize(serializer)
89    }
90
91    pub fn deserialize<'de, D: Deserializer<'de>>(
92        deserializer: D,
93    ) -> Result<InitialType, D::Error> {
94        let serialized = <SerializedType as Deserialize>::deserialize(deserializer)?;
95        Ok(serialized.into_iter().collect())
96    }
97}
98
99/// A translated WebAssembly module, excluding the function bodies and
100/// memory initializers.
101///
102/// IMPORTANT: since this struct will be serialized as part of the compiled module artifact,
103/// if you change this struct, do not forget to update [`MetadataHeader::version`](crate::serialize::MetadataHeader)
104/// to make sure we don't break compatibility between versions.
105#[derive(Debug, Clone, Default)]
106#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
107#[cfg_attr(feature = "artifact-size", derive(loupe::MemoryUsage))]
108pub struct ModuleInfo {
109    /// A unique identifier (within this process) for this module.
110    ///
111    /// We skip serialization/deserialization of this field, as it
112    /// should be computed by the process.
113    /// It's not skipped in rkyv, but that is okay, because even though it's skipped in bincode/serde
114    /// it's still deserialized back as a garbage number, and later override from computed by the process
115    #[cfg_attr(feature = "enable-serde", serde(skip_serializing, skip_deserializing))]
116    pub id: ModuleId,
117
118    /// hash of the module
119    pub hash: Option<ModuleHash>,
120
121    /// The name of this wasm module, often found in the wasm file.
122    pub name: Option<String>,
123
124    /// Imported entities with the (module, field, index_of_the_import)
125    ///
126    /// Keeping the `index_of_the_import` is important, as there can be
127    /// two same references to the same import, and we don't want to confuse
128    /// them.
129    #[cfg_attr(feature = "enable-serde", serde(with = "serde_imports"))]
130    pub imports: IndexMap<ImportKey, ImportIndex>,
131
132    /// Exported entities.
133    pub exports: IndexMap<String, ExportIndex>,
134
135    /// The module "start" function, if present.
136    pub start_function: Option<FunctionIndex>,
137
138    /// WebAssembly table initializers.
139    pub table_initializers: Vec<TableInitializer>,
140
141    /// WebAssembly passive elements.
142    pub passive_elements: HashMap<ElemIndex, Box<[FunctionIndex]>>,
143
144    /// WebAssembly passive data segments.
145    pub passive_data: HashMap<DataIndex, Box<[u8]>>,
146
147    /// WebAssembly global initializers.
148    pub global_initializers: PrimaryMap<LocalGlobalIndex, GlobalInit>,
149
150    /// WebAssembly function names.
151    pub function_names: HashMap<FunctionIndex, String>,
152
153    /// WebAssembly function signatures.
154    pub signatures: PrimaryMap<SignatureIndex, FunctionType>,
155
156    /// WebAssembly functions (imported and local).
157    pub functions: PrimaryMap<FunctionIndex, SignatureIndex>,
158
159    /// WebAssembly tables (imported and local).
160    pub tables: PrimaryMap<TableIndex, TableType>,
161
162    /// WebAssembly linear memories (imported and local).
163    pub memories: PrimaryMap<MemoryIndex, MemoryType>,
164
165    /// WebAssembly global variables (imported and local).
166    pub globals: PrimaryMap<GlobalIndex, GlobalType>,
167
168    /// Custom sections in the module.
169    pub custom_sections: IndexMap<String, CustomSectionIndex>,
170
171    /// The data for each CustomSection in the module.
172    pub custom_sections_data: PrimaryMap<CustomSectionIndex, Box<[u8]>>,
173
174    /// Number of imported functions in the module.
175    pub num_imported_functions: usize,
176
177    /// Number of imported tables in the module.
178    pub num_imported_tables: usize,
179
180    /// Number of imported memories in the module.
181    pub num_imported_memories: usize,
182
183    /// Number of imported globals in the module.
184    pub num_imported_globals: usize,
185}
186
187/// Mirror version of ModuleInfo that can derive rkyv traits
188#[derive(Debug, RkyvSerialize, RkyvDeserialize, Archive)]
189#[rkyv(derive(Debug))]
190pub struct ArchivableModuleInfo {
191    name: Option<String>,
192    hash: Option<ModuleHash>,
193    imports: IndexMap<ImportKey, ImportIndex>,
194    exports: IndexMap<String, ExportIndex>,
195    start_function: Option<FunctionIndex>,
196    table_initializers: Vec<TableInitializer>,
197    passive_elements: BTreeMap<ElemIndex, Box<[FunctionIndex]>>,
198    passive_data: BTreeMap<DataIndex, Box<[u8]>>,
199    global_initializers: PrimaryMap<LocalGlobalIndex, GlobalInit>,
200    function_names: BTreeMap<FunctionIndex, String>,
201    signatures: PrimaryMap<SignatureIndex, FunctionType>,
202    functions: PrimaryMap<FunctionIndex, SignatureIndex>,
203    tables: PrimaryMap<TableIndex, TableType>,
204    memories: PrimaryMap<MemoryIndex, MemoryType>,
205    globals: PrimaryMap<GlobalIndex, GlobalType>,
206    custom_sections: IndexMap<String, CustomSectionIndex>,
207    custom_sections_data: PrimaryMap<CustomSectionIndex, Box<[u8]>>,
208    num_imported_functions: usize,
209    num_imported_tables: usize,
210    num_imported_memories: usize,
211    num_imported_globals: usize,
212}
213
214impl From<ModuleInfo> for ArchivableModuleInfo {
215    fn from(it: ModuleInfo) -> Self {
216        Self {
217            name: it.name,
218            hash: it.hash,
219            imports: it.imports,
220            exports: it.exports,
221            start_function: it.start_function,
222            table_initializers: it.table_initializers,
223            passive_elements: it.passive_elements.into_iter().collect(),
224            passive_data: it.passive_data.into_iter().collect(),
225            global_initializers: it.global_initializers,
226            function_names: it.function_names.into_iter().collect(),
227            signatures: it.signatures,
228            functions: it.functions,
229            tables: it.tables,
230            memories: it.memories,
231            globals: it.globals,
232            custom_sections: it.custom_sections,
233            custom_sections_data: it.custom_sections_data,
234            num_imported_functions: it.num_imported_functions,
235            num_imported_tables: it.num_imported_tables,
236            num_imported_memories: it.num_imported_memories,
237            num_imported_globals: it.num_imported_globals,
238        }
239    }
240}
241
242impl From<ArchivableModuleInfo> for ModuleInfo {
243    fn from(it: ArchivableModuleInfo) -> Self {
244        Self {
245            id: Default::default(),
246            name: it.name,
247            hash: it.hash,
248            imports: it.imports,
249            exports: it.exports,
250            start_function: it.start_function,
251            table_initializers: it.table_initializers,
252            passive_elements: it.passive_elements.into_iter().collect(),
253            passive_data: it.passive_data.into_iter().collect(),
254            global_initializers: it.global_initializers,
255            function_names: it.function_names.into_iter().collect(),
256            signatures: it.signatures,
257            functions: it.functions,
258            tables: it.tables,
259            memories: it.memories,
260            globals: it.globals,
261            custom_sections: it.custom_sections,
262            custom_sections_data: it.custom_sections_data,
263            num_imported_functions: it.num_imported_functions,
264            num_imported_tables: it.num_imported_tables,
265            num_imported_memories: it.num_imported_memories,
266            num_imported_globals: it.num_imported_globals,
267        }
268    }
269}
270
271impl From<&ModuleInfo> for ArchivableModuleInfo {
272    fn from(it: &ModuleInfo) -> Self {
273        Self::from(it.clone())
274    }
275}
276
277impl Archive for ModuleInfo {
278    type Archived = <ArchivableModuleInfo as Archive>::Archived;
279    type Resolver = <ArchivableModuleInfo as Archive>::Resolver;
280
281    fn resolve(&self, resolver: Self::Resolver, out: rkyv::Place<Self::Archived>) {
282        ArchivableModuleInfo::from(self).resolve(resolver, out)
283    }
284}
285
286impl<S: rkyv::ser::Allocator + rkyv::ser::Writer + Fallible + ?Sized> RkyvSerialize<S>
287    for ModuleInfo
288where
289    <S as Fallible>::Error: rkyv::rancor::Source + rkyv::rancor::Trace,
290{
291    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
292        ArchivableModuleInfo::from(self).serialize(serializer)
293    }
294}
295
296impl<D: Fallible + ?Sized> RkyvDeserialize<ModuleInfo, D> for ArchivedArchivableModuleInfo
297where
298    D::Error: Source + Trace,
299{
300    fn deserialize(&self, deserializer: &mut D) -> Result<ModuleInfo, D::Error> {
301        let archived = RkyvDeserialize::<ArchivableModuleInfo, D>::deserialize(self, deserializer)?;
302        Ok(ModuleInfo::from(archived))
303    }
304}
305
306// For test serialization correctness, everything except module id should be same
307impl PartialEq for ModuleInfo {
308    fn eq(&self, other: &Self) -> bool {
309        self.name == other.name
310            && self.imports == other.imports
311            && self.exports == other.exports
312            && self.start_function == other.start_function
313            && self.table_initializers == other.table_initializers
314            && self.passive_elements == other.passive_elements
315            && self.passive_data == other.passive_data
316            && self.global_initializers == other.global_initializers
317            && self.function_names == other.function_names
318            && self.signatures == other.signatures
319            && self.functions == other.functions
320            && self.tables == other.tables
321            && self.memories == other.memories
322            && self.globals == other.globals
323            && self.custom_sections == other.custom_sections
324            && self.custom_sections_data == other.custom_sections_data
325            && self.num_imported_functions == other.num_imported_functions
326            && self.num_imported_tables == other.num_imported_tables
327            && self.num_imported_memories == other.num_imported_memories
328            && self.num_imported_globals == other.num_imported_globals
329    }
330}
331
332impl Eq for ModuleInfo {}
333
334impl ModuleInfo {
335    /// Allocates the module data structures.
336    pub fn new() -> Self {
337        Default::default()
338    }
339
340    /// Returns the module hash if available
341    pub fn hash(&self) -> Option<ModuleHash> {
342        self.hash
343    }
344
345    /// Get the given passive element, if it exists.
346    pub fn get_passive_element(&self, index: ElemIndex) -> Option<&[FunctionIndex]> {
347        self.passive_elements.get(&index).map(|es| &**es)
348    }
349
350    /// Get the exported signatures of the module
351    pub fn exported_signatures(&self) -> Vec<FunctionType> {
352        self.exports
353            .iter()
354            .filter_map(|(_name, export_index)| match export_index {
355                ExportIndex::Function(i) => {
356                    let signature = self.functions.get(*i).unwrap();
357                    let func_type = self.signatures.get(*signature).unwrap();
358                    Some(func_type.clone())
359                }
360                _ => None,
361            })
362            .collect::<Vec<FunctionType>>()
363    }
364
365    /// Get the export types of the module
366    pub fn exports(&'_ self) -> ExportsIterator<impl Iterator<Item = ExportType> + '_> {
367        let iter = self.exports.iter().map(move |(name, export_index)| {
368            let extern_type = match export_index {
369                ExportIndex::Function(i) => {
370                    let signature = self.functions.get(*i).unwrap();
371                    let func_type = self.signatures.get(*signature).unwrap();
372                    ExternType::Function(func_type.clone())
373                }
374                ExportIndex::Table(i) => {
375                    let table_type = self.tables.get(*i).unwrap();
376                    ExternType::Table(*table_type)
377                }
378                ExportIndex::Memory(i) => {
379                    let memory_type = self.memories.get(*i).unwrap();
380                    ExternType::Memory(*memory_type)
381                }
382                ExportIndex::Global(i) => {
383                    let global_type = self.globals.get(*i).unwrap();
384                    ExternType::Global(*global_type)
385                }
386            };
387            ExportType::new(name, extern_type)
388        });
389        ExportsIterator::new(iter, self.exports.len())
390    }
391
392    /// Get the import types of the module
393    pub fn imports(&'_ self) -> ImportsIterator<impl Iterator<Item = ImportType> + '_> {
394        let iter =
395            self.imports
396                .iter()
397                .map(move |(ImportKey { module, field, .. }, import_index)| {
398                    let extern_type = match import_index {
399                        ImportIndex::Function(i) => {
400                            let signature = self.functions.get(*i).unwrap();
401                            let func_type = self.signatures.get(*signature).unwrap();
402                            ExternType::Function(func_type.clone())
403                        }
404                        ImportIndex::Table(i) => {
405                            let table_type = self.tables.get(*i).unwrap();
406                            ExternType::Table(*table_type)
407                        }
408                        ImportIndex::Memory(i) => {
409                            let memory_type = self.memories.get(*i).unwrap();
410                            ExternType::Memory(*memory_type)
411                        }
412                        ImportIndex::Global(i) => {
413                            let global_type = self.globals.get(*i).unwrap();
414                            ExternType::Global(*global_type)
415                        }
416                    };
417                    ImportType::new(module, field, extern_type)
418                });
419        ImportsIterator::new(iter, self.imports.len())
420    }
421
422    /// Get the custom sections of the module given a `name`.
423    pub fn custom_sections<'a>(&'a self, name: &'a str) -> impl Iterator<Item = Box<[u8]>> + 'a {
424        self.custom_sections
425            .iter()
426            .filter_map(move |(section_name, section_index)| {
427                if name != section_name {
428                    return None;
429                }
430                Some(self.custom_sections_data[*section_index].clone())
431            })
432    }
433
434    /// Convert a `LocalFunctionIndex` into a `FunctionIndex`.
435    pub fn func_index(&self, local_func: LocalFunctionIndex) -> FunctionIndex {
436        FunctionIndex::new(self.num_imported_functions + local_func.index())
437    }
438
439    /// Convert a `FunctionIndex` into a `LocalFunctionIndex`. Returns None if the
440    /// index is an imported function.
441    pub fn local_func_index(&self, func: FunctionIndex) -> Option<LocalFunctionIndex> {
442        func.index()
443            .checked_sub(self.num_imported_functions)
444            .map(LocalFunctionIndex::new)
445    }
446
447    /// Test whether the given function index is for an imported function.
448    pub fn is_imported_function(&self, index: FunctionIndex) -> bool {
449        index.index() < self.num_imported_functions
450    }
451
452    /// Convert a `LocalTableIndex` into a `TableIndex`.
453    pub fn table_index(&self, local_table: LocalTableIndex) -> TableIndex {
454        TableIndex::new(self.num_imported_tables + local_table.index())
455    }
456
457    /// Convert a `TableIndex` into a `LocalTableIndex`. Returns None if the
458    /// index is an imported table.
459    pub fn local_table_index(&self, table: TableIndex) -> Option<LocalTableIndex> {
460        table
461            .index()
462            .checked_sub(self.num_imported_tables)
463            .map(LocalTableIndex::new)
464    }
465
466    /// Test whether the given table index is for an imported table.
467    pub fn is_imported_table(&self, index: TableIndex) -> bool {
468        index.index() < self.num_imported_tables
469    }
470
471    /// Convert a `LocalMemoryIndex` into a `MemoryIndex`.
472    pub fn memory_index(&self, local_memory: LocalMemoryIndex) -> MemoryIndex {
473        MemoryIndex::new(self.num_imported_memories + local_memory.index())
474    }
475
476    /// Convert a `MemoryIndex` into a `LocalMemoryIndex`. Returns None if the
477    /// index is an imported memory.
478    pub fn local_memory_index(&self, memory: MemoryIndex) -> Option<LocalMemoryIndex> {
479        memory
480            .index()
481            .checked_sub(self.num_imported_memories)
482            .map(LocalMemoryIndex::new)
483    }
484
485    /// Test whether the given memory index is for an imported memory.
486    pub fn is_imported_memory(&self, index: MemoryIndex) -> bool {
487        index.index() < self.num_imported_memories
488    }
489
490    /// Convert a `LocalGlobalIndex` into a `GlobalIndex`.
491    pub fn global_index(&self, local_global: LocalGlobalIndex) -> GlobalIndex {
492        GlobalIndex::new(self.num_imported_globals + local_global.index())
493    }
494
495    /// Convert a `GlobalIndex` into a `LocalGlobalIndex`. Returns None if the
496    /// index is an imported global.
497    pub fn local_global_index(&self, global: GlobalIndex) -> Option<LocalGlobalIndex> {
498        global
499            .index()
500            .checked_sub(self.num_imported_globals)
501            .map(LocalGlobalIndex::new)
502    }
503
504    /// Test whether the given global index is for an imported global.
505    pub fn is_imported_global(&self, index: GlobalIndex) -> bool {
506        index.index() < self.num_imported_globals
507    }
508
509    /// Get the Module name
510    pub fn name(&self) -> String {
511        match self.name {
512            Some(ref name) => name.to_string(),
513            None => "<module>".to_string(),
514        }
515    }
516
517    /// Get the imported function types of the module.
518    pub fn imported_function_types(&'_ self) -> impl Iterator<Item = FunctionType> + '_ {
519        self.functions
520            .values()
521            .take(self.num_imported_functions)
522            .map(move |sig_index| self.signatures[*sig_index].clone())
523    }
524}
525
526impl fmt::Display for ModuleInfo {
527    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
528        write!(f, "{}", self.name())
529    }
530}
531
532// Code inspired from
533// https://www.reddit.com/r/rust/comments/9vspv4/extending_iterators_ergonomically/
534
535/// This iterator allows us to iterate over the exports
536/// and offer nice API ergonomics over it.
537pub struct ExportsIterator<I: Iterator<Item = ExportType> + Sized> {
538    iter: I,
539    size: usize,
540}
541
542impl<I: Iterator<Item = ExportType> + Sized> ExportsIterator<I> {
543    /// Create a new `ExportsIterator` for a given iterator and size
544    pub fn new(iter: I, size: usize) -> Self {
545        Self { iter, size }
546    }
547}
548
549impl<I: Iterator<Item = ExportType> + Sized> ExactSizeIterator for ExportsIterator<I> {
550    // We can easily calculate the remaining number of iterations.
551    fn len(&self) -> usize {
552        self.size
553    }
554}
555
556impl<I: Iterator<Item = ExportType> + Sized> ExportsIterator<I> {
557    /// Get only the functions
558    pub fn functions(self) -> impl Iterator<Item = ExportType<FunctionType>> + Sized {
559        self.iter.filter_map(|extern_| match extern_.ty() {
560            ExternType::Function(ty) => Some(ExportType::new(extern_.name(), ty.clone())),
561            _ => None,
562        })
563    }
564    /// Get only the memories
565    pub fn memories(self) -> impl Iterator<Item = ExportType<MemoryType>> + Sized {
566        self.iter.filter_map(|extern_| match extern_.ty() {
567            ExternType::Memory(ty) => Some(ExportType::new(extern_.name(), *ty)),
568            _ => None,
569        })
570    }
571    /// Get only the tables
572    pub fn tables(self) -> impl Iterator<Item = ExportType<TableType>> + Sized {
573        self.iter.filter_map(|extern_| match extern_.ty() {
574            ExternType::Table(ty) => Some(ExportType::new(extern_.name(), *ty)),
575            _ => None,
576        })
577    }
578    /// Get only the globals
579    pub fn globals(self) -> impl Iterator<Item = ExportType<GlobalType>> + Sized {
580        self.iter.filter_map(|extern_| match extern_.ty() {
581            ExternType::Global(ty) => Some(ExportType::new(extern_.name(), *ty)),
582            _ => None,
583        })
584    }
585}
586
587impl<I: Iterator<Item = ExportType> + Sized> Iterator for ExportsIterator<I> {
588    type Item = ExportType;
589    fn next(&mut self) -> Option<Self::Item> {
590        self.iter.next()
591    }
592}
593
594/// This iterator allows us to iterate over the imports
595/// and offer nice API ergonomics over it.
596pub struct ImportsIterator<I: Iterator<Item = ImportType> + Sized> {
597    iter: I,
598    size: usize,
599}
600
601impl<I: Iterator<Item = ImportType> + Sized> ImportsIterator<I> {
602    /// Create a new `ImportsIterator` for a given iterator and size
603    pub fn new(iter: I, size: usize) -> Self {
604        Self { iter, size }
605    }
606}
607
608impl<I: Iterator<Item = ImportType> + Sized> ExactSizeIterator for ImportsIterator<I> {
609    // We can easily calculate the remaining number of iterations.
610    fn len(&self) -> usize {
611        self.size
612    }
613}
614
615impl<I: Iterator<Item = ImportType> + Sized> ImportsIterator<I> {
616    /// Get only the functions
617    pub fn functions(self) -> impl Iterator<Item = ImportType<FunctionType>> + Sized {
618        self.iter.filter_map(|extern_| match extern_.ty() {
619            ExternType::Function(ty) => Some(ImportType::new(
620                extern_.module(),
621                extern_.name(),
622                ty.clone(),
623            )),
624            _ => None,
625        })
626    }
627    /// Get only the memories
628    pub fn memories(self) -> impl Iterator<Item = ImportType<MemoryType>> + Sized {
629        self.iter.filter_map(|extern_| match extern_.ty() {
630            ExternType::Memory(ty) => Some(ImportType::new(extern_.module(), extern_.name(), *ty)),
631            _ => None,
632        })
633    }
634    /// Get only the tables
635    pub fn tables(self) -> impl Iterator<Item = ImportType<TableType>> + Sized {
636        self.iter.filter_map(|extern_| match extern_.ty() {
637            ExternType::Table(ty) => Some(ImportType::new(extern_.module(), extern_.name(), *ty)),
638            _ => None,
639        })
640    }
641    /// Get only the globals
642    pub fn globals(self) -> impl Iterator<Item = ImportType<GlobalType>> + Sized {
643        self.iter.filter_map(|extern_| match extern_.ty() {
644            ExternType::Global(ty) => Some(ImportType::new(extern_.module(), extern_.name(), *ty)),
645            _ => None,
646        })
647    }
648}
649
650impl<I: Iterator<Item = ImportType> + Sized> Iterator for ImportsIterator<I> {
651    type Item = ImportType;
652    fn next(&mut self) -> Option<Self::Item> {
653        self.iter.next()
654    }
655}