1use 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#[derive(
48 Debug, Copy, Clone, Default, PartialEq, Eq, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive,
49)]
50#[archive(as = "Self")]
51pub struct ImportCounts {
52 pub functions: u32,
54
55 pub tables: u32,
57
58 pub memories: u32,
60
61 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 pub fn local_function_index(
75 &self,
76 idx: FunctionIndex,
77 ) -> Result<LocalFunctionIndex, FunctionIndex> {
78 Self::make_local(idx, self.functions)
79 }
80
81 pub fn local_table_index(&self, idx: TableIndex) -> Result<LocalTableIndex, TableIndex> {
83 Self::make_local(idx, self.tables)
84 }
85
86 pub fn local_memory_index(&self, idx: MemoryIndex) -> Result<LocalMemoryIndex, MemoryIndex> {
88 Self::make_local(idx, self.memories)
89 }
90
91 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 pub fn function_index(&self, idx: LocalFunctionIndex) -> FunctionIndex {
103 Self::make_index(idx, self.functions)
104 }
105
106 pub fn table_index(&self, idx: LocalTableIndex) -> TableIndex {
108 Self::make_index(idx, self.tables)
109 }
110
111 pub fn memory_index(&self, idx: LocalMemoryIndex) -> MemoryIndex {
113 Self::make_index(idx, self.memories)
114 }
115
116 pub fn global_index(&self, idx: LocalGlobalIndex) -> GlobalIndex {
118 Self::make_index(idx, self.globals)
119 }
120}
121
122#[derive(Debug, Clone, Default)]
125pub struct ModuleInfo {
126 pub id: ModuleId,
135
136 pub name: Option<String>,
138
139 pub imports: IndexMap<(String, String, u32), ImportIndex>,
145
146 pub exports: IndexMap<String, ExportIndex>,
148
149 pub start_function: Option<FunctionIndex>,
151
152 pub table_initializers: Vec<OwnedTableInitializer>,
154
155 pub passive_elements: BTreeMap<ElemIndex, Box<[FunctionIndex]>>,
157
158 pub passive_data: BTreeMap<DataIndex, Arc<[u8]>>,
160
161 pub global_initializers: PrimaryMap<LocalGlobalIndex, GlobalInit>,
163
164 pub function_names: HashMap<FunctionIndex, String>,
166
167 pub signatures: PrimaryMap<SignatureIndex, FunctionType>,
169
170 pub functions: PrimaryMap<FunctionIndex, SignatureIndex>,
172
173 pub tables: PrimaryMap<TableIndex, TableType>,
175
176 pub memories: PrimaryMap<MemoryIndex, MemoryType>,
178
179 pub globals: PrimaryMap<GlobalIndex, GlobalType>,
181
182 pub custom_sections: IndexMap<String, CustomSectionIndex>,
184
185 pub custom_sections_data: PrimaryMap<CustomSectionIndex, Arc<[u8]>>,
187
188 pub import_counts: ImportCounts,
190}
191
192#[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
296impl 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 pub fn new() -> Self {
324 Default::default()
325 }
326
327 pub fn get_passive_element(&self, index: ElemIndex) -> Option<&[FunctionIndex]> {
329 self.passive_elements.get(&index).map(|es| &**es)
330 }
331
332 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 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 pub fn func_index(&self, local_func: LocalFunctionIndex) -> FunctionIndex {
361 self.import_counts.function_index(local_func)
362 }
363
364 pub fn local_func_index(&self, func: FunctionIndex) -> Option<LocalFunctionIndex> {
367 self.import_counts.local_function_index(func).ok()
368 }
369
370 pub fn is_imported_function(&self, index: FunctionIndex) -> bool {
372 self.local_func_index(index).is_none()
373 }
374
375 pub fn table_index(&self, local_table: LocalTableIndex) -> TableIndex {
377 self.import_counts.table_index(local_table)
378 }
379
380 pub fn local_table_index(&self, table: TableIndex) -> Option<LocalTableIndex> {
383 self.import_counts.local_table_index(table).ok()
384 }
385
386 pub fn is_imported_table(&self, index: TableIndex) -> bool {
388 self.local_table_index(index).is_none()
389 }
390
391 pub fn memory_index(&self, local_memory: LocalMemoryIndex) -> MemoryIndex {
393 self.import_counts.memory_index(local_memory)
394 }
395
396 pub fn local_memory_index(&self, memory: MemoryIndex) -> Option<LocalMemoryIndex> {
399 self.import_counts.local_memory_index(memory).ok()
400 }
401
402 pub fn is_imported_memory(&self, index: MemoryIndex) -> bool {
404 self.local_memory_index(index).is_none()
405 }
406
407 pub fn global_index(&self, local_global: LocalGlobalIndex) -> GlobalIndex {
409 self.import_counts.global_index(local_global)
410 }
411
412 pub fn local_global_index(&self, global: GlobalIndex) -> Option<LocalGlobalIndex> {
415 self.import_counts.local_global_index(global).ok()
416 }
417
418 pub fn is_imported_global(&self, index: GlobalIndex) -> bool {
420 self.local_global_index(index).is_none()
421 }
422
423 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 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}