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