makepad_stitch/
linker.rs

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/// A linker for defining imports and instantiating [`Module`]s.
9#[derive(Clone, Debug)]
10pub struct Linker {
11    strings: StringInterner,
12    defs: HashMap<(InternedString, InternedString), ExternVal>,
13}
14
15impl Linker {
16    /// Creates a new [`Linker`].
17    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/// An error that can occur when instantiating a module.
45#[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);