1use {
2 crate::{
3 error::Error, extern_val::ExternVal, instance::Instance, module::Module, store::Store,
4 },
5 std::{collections::HashMap, fmt, sync::Arc},
6};
7
8#[derive(Clone, Debug)]
10pub struct Linker {
11 strings: StringInterner,
12 defs: HashMap<(InternedString, InternedString), ExternVal>,
13}
14
15impl Linker {
16 pub fn new() -> Self {
18 Linker {
19 strings: StringInterner::new(),
20 defs: HashMap::new(),
21 }
22 }
23
24 pub fn define(&mut self, module: &str, name: &str, val: impl Into<ExternVal>) {
25 let module = self.strings.get_or_intern(module);
26 let name = self.strings.get_or_intern(name);
27 assert!(
28 self.defs.insert((module, name), val.into()).is_none(),
29 "duplicate definition"
30 );
31 }
32
33 pub fn instantiate(&self, store: &mut Store, module: &Module) -> Result<Instance, Error> {
34 module.instantiate(store, self)
35 }
36
37 pub(crate) fn lookup(&self, module: &str, name: &str) -> Option<ExternVal> {
38 let module = self.strings.get(module)?;
39 let name = self.strings.get(name)?;
40 self.defs.get(&(module, name)).copied()
41 }
42}
43
44#[derive(Clone, Copy, Debug)]
46#[non_exhaustive]
47pub enum InstantiateError {
48 DefNotFound,
49 ImportKindMismatch,
50 FuncTypeMismatch,
51 GlobalTypeMismatch,
52 TableTypeMismatch,
53 MemTypeMismatch,
54}
55
56impl fmt::Display for InstantiateError {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 match self {
59 Self::DefNotFound => write!(f, "definition not found"),
60 Self::ImportKindMismatch => write!(f, "import kind mismatch"),
61 Self::FuncTypeMismatch => write!(f, "function type mismatch"),
62 Self::GlobalTypeMismatch => write!(f, "global type mismatch"),
63 Self::TableTypeMismatch => write!(f, "table type mismatch"),
64 Self::MemTypeMismatch => write!(f, "memory type mismatch"),
65 }
66 }
67}
68
69impl std::error::Error for InstantiateError {}
70
71#[derive(Clone, Debug)]
72struct StringInterner {
73 strings: Vec<Arc<str>>,
74 indices: HashMap<Arc<str>, usize>,
75}
76
77impl StringInterner {
78 fn new() -> Self {
79 StringInterner {
80 strings: Vec::new(),
81 indices: HashMap::new(),
82 }
83 }
84
85 fn get(&self, string: &str) -> Option<InternedString> {
86 let index = self.indices.get(string).copied()?;
87 Some(InternedString(index))
88 }
89
90 fn get_or_intern(&mut self, string: &str) -> InternedString {
91 match self.indices.get(string).copied() {
92 Some(index) => InternedString(index),
93 None => {
94 let index = self.strings.len();
95 let string: Arc<str> = string.into();
96 self.strings.push(string.clone());
97 self.indices.insert(string, index);
98 InternedString(index)
99 }
100 }
101 }
102}
103
104#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
105struct InternedString(usize);