1use std::convert::TryFrom;
2use std::ops::Range;
3
4#[derive(Default)]
10pub struct ModuleContext<'a> {
11 raw_sections: Vec<wasm_encoder::RawSection<'a>>,
13
14 imports: Vec<wasmparser::Import<'a>>,
16
17 globals: Vec<wasmparser::GlobalType>,
20
21 defined_globals_index: Option<u32>,
26
27 exports: Vec<wasmparser::Export<'a>>,
35
36 functions: Vec<u32>,
39
40 tables: Vec<wasmparser::TableType>,
43
44 memories: Vec<wasmparser::MemoryType>,
47
48 defined_memories_index: Option<u32>,
53
54 pub(crate) defined_global_exports: Option<Vec<(u32, String)>>,
58
59 pub(crate) defined_memory_exports: Option<Vec<String>>,
61}
62
63impl<'a> ModuleContext<'a> {
64 pub(crate) fn add_raw_section(&mut self, id: u8, range: Range<usize>, full_wasm: &'a [u8]) {
66 self.raw_sections.push(wasm_encoder::RawSection {
67 id,
68 data: &full_wasm[range.start..range.end],
69 })
70 }
71
72 pub(crate) fn push_imported_memory(&mut self, memory_type: wasmparser::MemoryType) {
74 assert!(self.defined_memories_index.is_none());
75 self.memories.push(memory_type);
76 }
77
78 pub(crate) fn push_defined_memory(&mut self, memory_type: wasmparser::MemoryType) {
80 if self.defined_memories_index.is_none() {
81 self.defined_memories_index = Some(u32::try_from(self.memories.len()).unwrap());
82 }
83 self.memories.push(memory_type);
84 }
85
86 pub(crate) fn push_imported_global(&mut self, global_type: wasmparser::GlobalType) {
88 assert!(self.defined_globals_index.is_none());
89 self.globals.push(global_type);
90 }
91
92 pub(crate) fn push_defined_global(&mut self, global_type: wasmparser::GlobalType) {
94 if self.defined_globals_index.is_none() {
95 self.defined_globals_index = Some(u32::try_from(self.globals.len()).unwrap());
96 }
97 self.globals.push(global_type);
98 }
99
100 pub(crate) fn push_function(&mut self, func_type: u32) {
102 self.functions.push(func_type);
103 }
104
105 pub(crate) fn push_table(&mut self, table_type: wasmparser::TableType) {
107 self.tables.push(table_type);
108 }
109
110 pub(crate) fn push_import(&mut self, import: wasmparser::Import<'a>) {
112 self.imports.push(import);
113
114 match import.ty {
116 wasmparser::TypeRef::Memory(ty) => {
117 self.push_imported_memory(ty);
118 }
119 wasmparser::TypeRef::Global(ty) => {
120 self.push_imported_global(ty);
121 }
122 wasmparser::TypeRef::Func(ty_idx) => {
123 self.push_function(ty_idx);
124 }
125 wasmparser::TypeRef::Table(ty) => {
126 self.push_table(ty);
127 }
128 wasmparser::TypeRef::Tag(_) => {
129 unreachable!("exceptions are unsupported; checked in validation")
130 }
131 wasmparser::TypeRef::FuncExact(_) => {
132 unreachable!("custom-descriptors are unsupported; checked in validation")
133 }
134 }
135 }
136
137 pub(crate) fn push_export(&mut self, export: wasmparser::Export<'a>) {
139 self.exports.push(export);
140 }
141
142 pub(crate) fn defined_memories_len(&self) -> usize {
144 self.defined_memories_index.map_or(0, |n| {
145 let n = usize::try_from(n).unwrap();
146 assert!(self.memories.len() > n);
147 self.memories.len() - n
148 })
149 }
150
151 pub(crate) fn defined_memories(
153 &self,
154 ) -> impl Iterator<Item = (u32, wasmparser::MemoryType)> + '_ {
155 self.memories
156 .iter()
157 .copied()
158 .enumerate()
159 .skip(
160 self.defined_memories_index
161 .map_or(self.memories.len(), |i| usize::try_from(i).unwrap()),
162 )
163 .map(|(i, m)| (u32::try_from(i).unwrap(), m))
164 }
165
166 pub(crate) fn defined_globals(
168 &self,
169 ) -> impl Iterator<Item = (u32, wasmparser::GlobalType, Option<&str>)> + '_ {
170 let mut defined_global_exports = self
171 .defined_global_exports
172 .as_ref()
173 .map(|v| v.as_slice())
174 .unwrap_or(&[])
175 .iter()
176 .peekable();
177
178 self.globals
179 .iter()
180 .copied()
181 .enumerate()
182 .skip(
183 self.defined_globals_index
184 .map_or(self.globals.len(), |i| usize::try_from(i).unwrap()),
185 )
186 .map(move |(i, g)| {
187 let i = u32::try_from(i).unwrap();
188 let name = defined_global_exports
189 .next_if(|(j, _)| *j == i)
190 .map(|(_, name)| name.as_str());
191 (i, g, name)
192 })
193 }
194
195 pub(crate) fn raw_sections(&self) -> &[wasm_encoder::RawSection<'a>] {
197 &self.raw_sections
198 }
199
200 pub(crate) fn imports(&self) -> &[wasmparser::Import<'a>] {
202 &self.imports
203 }
204
205 pub(crate) fn exports(&self) -> &[wasmparser::Export<'a>] {
207 &self.exports
208 }
209
210 pub(crate) fn has_wasi_initialize(&self) -> bool {
211 self.exports.iter().any(|e| e.name == "_initialize")
212 }
213}