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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
use crate::{
    BinaryReader, ComponentExport, Export, Result, SectionIteratorLimited, SectionReader,
    SectionWithLimitedItems,
};
use std::ops::Range;

/// Represents the kind of argument when instantiating a WebAssembly module.
#[derive(Debug, Clone)]
pub enum ModuleArgKind {
    /// The argument is an instance.
    Instance(u32),
}

/// Represents an argument to instantiating a WebAssembly component.
#[derive(Debug, Clone)]
pub struct ModuleArg<'a> {
    /// The name of the module argument.
    pub name: &'a str,
    /// The kind of the module argument.
    pub kind: ModuleArgKind,
}

/// Represents the kind of argument when instantiating a WebAssembly component.
#[derive(Debug, Clone)]
pub enum ComponentArgKind {
    /// The argument is a module.
    Module(u32),
    /// The argument is a component.
    Component(u32),
    /// The argument is an instance.
    Instance(u32),
    /// The argument is a function.
    Function(u32),
    /// The argument is a value.
    Value(u32),
    /// The argument is a type.
    Type(u32),
}

/// Represents an argument to instantiating a WebAssembly component.
#[derive(Debug, Clone)]
pub struct ComponentArg<'a> {
    /// The name of the component argument.
    pub name: &'a str,
    /// The kind of the component argument.
    pub kind: ComponentArgKind,
}

/// Represents an instance in a WebAssembly component.
#[derive(Debug, Clone)]
pub enum Instance<'a> {
    /// The instance is from instantiating a WebAssembly module.
    Module {
        /// The module index.
        index: u32,
        /// The module's instantiation arguments.
        args: Box<[ModuleArg<'a>]>,
    },
    /// The instance is from instantiating a WebAssembly component.
    Component {
        /// The component index.
        index: u32,
        /// The component's instantiation arguments.
        args: Box<[ComponentArg<'a>]>,
    },
    /// The instance is a module instance from exporting local items.
    ModuleFromExports(Box<[Export<'a>]>),
    /// The instance is a component instance from exporting local items.
    ComponentFromExports(Box<[ComponentExport<'a>]>),
}

/// A reader for the instance section of a WebAssembly component.
#[derive(Clone)]
pub struct InstanceSectionReader<'a> {
    reader: BinaryReader<'a>,
    count: u32,
}

impl<'a> InstanceSectionReader<'a> {
    /// Constructs a new `InstanceSectionReader` for the given data and offset.
    pub fn new(data: &'a [u8], offset: usize) -> Result<Self> {
        let mut reader = BinaryReader::new_with_offset(data, offset);
        let count = reader.read_var_u32()?;
        Ok(Self { reader, count })
    }

    /// Gets the original position of the section reader.
    pub fn original_position(&self) -> usize {
        self.reader.original_position()
    }

    /// Gets the count of items in the section.
    pub fn get_count(&self) -> u32 {
        self.count
    }

    /// Reads content of the instance section.
    ///
    /// # Examples
    /// ```
    /// use wasmparser::InstanceSectionReader;
    /// # let data: &[u8] = &[0x01, 0x00, 0x00, 0x00, 0x01, 0x03, b'f', b'o', b'o', 0x02, 0x00];
    /// let mut reader = InstanceSectionReader::new(data, 0).unwrap();
    /// for _ in 0..reader.get_count() {
    ///     let instance = reader.read().expect("instance");
    ///     println!("Instance: {:?}", instance);
    /// }
    /// ```
    pub fn read(&mut self) -> Result<Instance<'a>> {
        self.reader.read_instance()
    }
}

impl<'a> SectionReader for InstanceSectionReader<'a> {
    type Item = Instance<'a>;

    fn read(&mut self) -> Result<Self::Item> {
        Self::read(self)
    }

    fn eof(&self) -> bool {
        self.reader.eof()
    }

    fn original_position(&self) -> usize {
        Self::original_position(self)
    }

    fn range(&self) -> Range<usize> {
        self.reader.range()
    }
}

impl<'a> SectionWithLimitedItems for InstanceSectionReader<'a> {
    fn get_count(&self) -> u32 {
        Self::get_count(self)
    }
}

impl<'a> IntoIterator for InstanceSectionReader<'a> {
    type Item = Result<Instance<'a>>;
    type IntoIter = SectionIteratorLimited<Self>;

    /// Implements iterator over the instance section.
    ///
    /// # Examples
    ///
    /// ```
    /// use wasmparser::InstanceSectionReader;
    /// # let data: &[u8] = &[0x01, 0x00, 0x00, 0x00, 0x01, 0x03, b'f', b'o', b'o', 0x02, 0x00];
    /// let mut reader = InstanceSectionReader::new(data, 0).unwrap();
    /// for inst in reader {
    ///     println!("Instance {:?}", inst.expect("instance"));
    /// }
    /// ```
    fn into_iter(self) -> Self::IntoIter {
        SectionIteratorLimited::new(self)
    }
}