wasmi/
linker.rs

1use crate::{
2    collections::{
3        string_interner::{InternHint, Sym as Symbol},
4        StringInterner,
5    },
6    func::{FuncEntity, HostFuncEntity, HostFuncTrampolineEntity},
7    module::{ImportName, ImportType},
8    AsContext,
9    AsContextMut,
10    Caller,
11    Engine,
12    Error,
13    Extern,
14    ExternType,
15    Func,
16    FuncType,
17    GlobalType,
18    InstancePre,
19    IntoFunc,
20    MemoryType,
21    Module,
22    TableType,
23    Val,
24};
25use core::{
26    fmt::{self, Debug, Display},
27    marker::PhantomData,
28};
29use std::{
30    collections::{btree_map::Entry, BTreeMap},
31    sync::Arc,
32    vec::Vec,
33};
34
35/// An error that may occur upon operating with [`Linker`] instances.
36#[derive(Debug)]
37pub enum LinkerError {
38    /// Encountered duplicate definitions for the same name.
39    DuplicateDefinition {
40        /// The duplicate import name of the definition.
41        import_name: ImportName,
42    },
43    /// Encountered when no definition for an import is found.
44    MissingDefinition {
45        /// The name of the import for which no definition was found.
46        name: ImportName,
47        /// The type of the import for which no definition has been found.
48        ty: ExternType,
49    },
50    /// Encountered when a definition with invalid type is found.
51    InvalidTypeDefinition {
52        /// The name of the import for which no definition was found.
53        name: ImportName,
54        /// The expected import type.
55        expected: ExternType,
56        /// The found definition type.
57        found: ExternType,
58    },
59    /// Encountered when a [`FuncType`] does not match the expected [`FuncType`].
60    FuncTypeMismatch {
61        /// The name of the import with the mismatched type.
62        name: ImportName,
63        /// The expected [`FuncType`].
64        expected: FuncType,
65        /// The mismatching [`FuncType`] found.
66        found: FuncType,
67    },
68    /// Encountered when a [`TableType`] does not match the expected [`TableType`].
69    InvalidTableSubtype {
70        /// The name of the import with the invalid [`TableType`].
71        name: ImportName,
72        /// The [`TableType`] that is supposed to be a subtype of `other`.
73        ty: TableType,
74        /// The [`TableType`] this is supposed to be a supertype of `ty`.
75        other: TableType,
76    },
77    /// Encountered when a [`MemoryType`] does not match the expected [`MemoryType`].
78    InvalidMemorySubtype {
79        /// The name of the import with the invalid [`MemoryType`].
80        name: ImportName,
81        /// The [`MemoryType`] that is supposed to be a subtype of `other`.
82        ty: MemoryType,
83        /// The [`MemoryType`] this is supposed to be a supertype of `ty`.
84        other: MemoryType,
85    },
86    /// Encountered when a [`GlobalType`] does not match the expected [`GlobalType`].
87    GlobalTypeMismatch {
88        /// The name of the import with the mismatched type.
89        name: ImportName,
90        /// The expected [`GlobalType`].
91        expected: GlobalType,
92        /// The mismatching [`GlobalType`] found.
93        found: GlobalType,
94    },
95}
96
97impl LinkerError {
98    /// Creates a new [`LinkerError`] for when an imported definition was not found.
99    fn missing_definition(import: &ImportType) -> Self {
100        Self::MissingDefinition {
101            name: import.import_name().clone(),
102            ty: import.ty().clone(),
103        }
104    }
105
106    /// Creates a new [`LinkerError`] for when an imported definition has an invalid type.
107    fn invalid_type_definition(import: &ImportType, found: &ExternType) -> Self {
108        Self::InvalidTypeDefinition {
109            name: import.import_name().clone(),
110            expected: import.ty().clone(),
111            found: found.clone(),
112        }
113    }
114
115    /// Create a new [`LinkerError`] for when a [`FuncType`] mismatched.
116    fn func_type_mismatch(name: &ImportName, expected: &FuncType, found: &FuncType) -> Self {
117        Self::FuncTypeMismatch {
118            name: name.clone(),
119            expected: expected.clone(),
120            found: found.clone(),
121        }
122    }
123
124    /// Create a new [`LinkerError`] for when a [`TableType`] `ty` unexpectedly is not a subtype of `other`.
125    fn table_type_mismatch(name: &ImportName, ty: &TableType, other: &TableType) -> Self {
126        Self::InvalidTableSubtype {
127            name: name.clone(),
128            ty: *ty,
129            other: *other,
130        }
131    }
132
133    /// Create a new [`LinkerError`] for when a [`MemoryType`] `ty` unexpectedly is not a subtype of `other`.
134    fn invalid_memory_subtype(name: &ImportName, ty: &MemoryType, other: &MemoryType) -> Self {
135        Self::InvalidMemorySubtype {
136            name: name.clone(),
137            ty: *ty,
138            other: *other,
139        }
140    }
141
142    /// Create a new [`LinkerError`] for when a [`GlobalType`] mismatched.
143    fn global_type_mismatch(name: &ImportName, expected: &GlobalType, found: &GlobalType) -> Self {
144        Self::GlobalTypeMismatch {
145            name: name.clone(),
146            expected: *expected,
147            found: *found,
148        }
149    }
150}
151
152#[cfg(feature = "std")]
153impl std::error::Error for LinkerError {}
154
155impl Display for LinkerError {
156    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
157        match self {
158            Self::DuplicateDefinition { import_name } => {
159                write!(
160                    f,
161                    "encountered duplicate definition with name `{import_name}`",
162                )
163            }
164            Self::MissingDefinition { name, ty } => {
165                write!(
166                    f,
167                    "cannot find definition for import {name} with type {ty:?}",
168                )
169            }
170            Self::InvalidTypeDefinition {
171                name,
172                expected,
173                found,
174            } => {
175                write!(f, "found definition for import {name} with type {expected:?} but found type {found:?}")
176            }
177            Self::FuncTypeMismatch {
178                name,
179                expected,
180                found,
181            } => {
182                write!(
183                    f,
184                    "function type mismatch for import {name}: \
185                    expected {expected:?} but found {found:?}",
186                )
187            }
188            Self::InvalidTableSubtype { name, ty, other } => {
189                write!(
190                    f,
191                    "import {name}: table type {ty:?} is not a subtype of {other:?}"
192                )
193            }
194            Self::InvalidMemorySubtype { name, ty, other } => {
195                write!(
196                    f,
197                    "import {name}: memory type {ty:?} is not a subtype of {other:?}"
198                )
199            }
200            Self::GlobalTypeMismatch {
201                name,
202                expected,
203                found,
204            } => {
205                write!(
206                    f,
207                    "global variable type mismatch for import {name}: \
208                    expected {expected:?} but found {found:?}",
209                )
210            }
211        }
212    }
213}
214
215/// Wasm import keys.
216#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq)]
217#[repr(transparent)]
218struct ImportKey {
219    /// Merged module and name symbols.
220    ///
221    /// Merging allows for a faster `Ord` implementation.
222    module_and_name: u64,
223}
224
225impl Debug for ImportKey {
226    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
227        f.debug_struct("ImportKey")
228            .field("module", &self.module())
229            .field("name", &self.name())
230            .finish()
231    }
232}
233
234impl ImportKey {
235    /// Creates a new [`ImportKey`] from the given `module` and `name` symbols.
236    #[inline]
237    pub fn new(module: Symbol, name: Symbol) -> Self {
238        let module_and_name = u64::from(module.into_u32()) << 32 | u64::from(name.into_u32());
239        Self { module_and_name }
240    }
241
242    /// Returns the `module` [`Symbol`] of the [`ImportKey`].
243    #[inline]
244    pub fn module(&self) -> Symbol {
245        Symbol::from_u32((self.module_and_name >> 32) as u32)
246    }
247
248    /// Returns the `name` [`Symbol`] of the [`ImportKey`].
249    #[inline]
250    pub fn name(&self) -> Symbol {
251        Symbol::from_u32(self.module_and_name as u32)
252    }
253}
254
255/// A [`Linker`] definition.
256#[derive(Debug)]
257enum Definition<T> {
258    /// An external item from an [`Instance`](crate::Instance).
259    Extern(Extern),
260    /// A [`Linker`] internal host function.
261    HostFunc(HostFuncTrampolineEntity<T>),
262}
263
264impl<T> Clone for Definition<T> {
265    fn clone(&self) -> Self {
266        match self {
267            Self::Extern(definition) => Self::Extern(*definition),
268            Self::HostFunc(host_func) => Self::HostFunc(host_func.clone()),
269        }
270    }
271}
272
273impl<T> Definition<T> {
274    /// Returns the [`Extern`] item if this [`Definition`] is [`Definition::Extern`].
275    ///
276    /// Otherwise returns `None`.
277    fn as_extern(&self) -> Option<&Extern> {
278        match self {
279            Definition::Extern(item) => Some(item),
280            Definition::HostFunc(_) => None,
281        }
282    }
283
284    /// Returns the [`ExternType`] of the [`Definition`].
285    pub fn ty(&self, ctx: impl AsContext) -> ExternType {
286        match self {
287            Definition::Extern(item) => item.ty(ctx),
288            Definition::HostFunc(host_func) => ExternType::Func(host_func.func_type().clone()),
289        }
290    }
291
292    /// Returns the [`Func`] of the [`Definition`] if it is a function.
293    ///
294    /// Returns `None` otherwise.
295    ///
296    /// # Note
297    ///
298    /// - This allocates a new [`Func`] on the `ctx` if it is a [`Linker`]
299    ///   defined host function.
300    /// - This unifies handling of [`Definition::Extern(Extern::Func)`] and
301    ///   [`Definition::HostFunc`].
302    pub fn as_func(&self, mut ctx: impl AsContextMut<Data = T>) -> Option<Func> {
303        match self {
304            Definition::Extern(Extern::Func(func)) => Some(*func),
305            Definition::HostFunc(host_func) => {
306                let trampoline = ctx
307                    .as_context_mut()
308                    .store
309                    .alloc_trampoline(host_func.trampoline().clone());
310                let ty_dedup = ctx
311                    .as_context()
312                    .engine()
313                    .alloc_func_type(host_func.func_type().clone());
314                let entity = HostFuncEntity::new(ty_dedup, trampoline);
315                let func = ctx
316                    .as_context_mut()
317                    .store
318                    .inner
319                    .alloc_func(FuncEntity::Host(entity));
320                Some(func)
321            }
322            _ => None,
323        }
324    }
325}
326
327/// A linker used to define module imports and instantiate module instances.
328#[derive(Debug)]
329pub struct Linker<T> {
330    /// The underlying [`Engine`] for the [`Linker`].
331    ///
332    /// # Note
333    ///
334    /// Primarily required to define [`Linker`] owned host functions
335    //  using [`Linker::func_wrap`] and [`Linker::func_new`]. TODO: implement methods
336    engine: Engine,
337    /// Definitions shared with other [`Linker`] instances created by the same [`LinkerBuilder`].
338    ///
339    /// `None` if no [`LinkerBuilder`] was used for creation of the [`Linker`].
340    shared: Option<Arc<LinkerInner<T>>>,
341    /// Inner linker implementation details.
342    inner: LinkerInner<T>,
343}
344
345impl<T> Clone for Linker<T> {
346    fn clone(&self) -> Linker<T> {
347        Self {
348            engine: self.engine.clone(),
349            shared: self.shared.clone(),
350            inner: self.inner.clone(),
351        }
352    }
353}
354
355impl<T> Default for Linker<T> {
356    fn default() -> Self {
357        Self::new(&Engine::default())
358    }
359}
360
361impl<T> Linker<T> {
362    /// Creates a new [`Linker`].
363    pub fn new(engine: &Engine) -> Self {
364        Self {
365            engine: engine.clone(),
366            shared: None,
367            inner: LinkerInner::default(),
368        }
369    }
370
371    /// Creates a new [`LinkerBuilder`] to construct a [`Linker`].
372    pub fn build() -> LinkerBuilder<state::Constructing, T> {
373        LinkerBuilder {
374            inner: Arc::new(LinkerInner::default()),
375            marker: PhantomData,
376        }
377    }
378
379    /// Returns the underlying [`Engine`] of the [`Linker`].
380    pub fn engine(&self) -> &Engine {
381        &self.engine
382    }
383
384    /// Ensures that the `name` in `module` is undefined in the shared definitions.
385    ///
386    /// Returns `Ok` if no shared definition exists.
387    ///
388    /// # Errors
389    ///
390    /// If there exists a shared definition for `name` in `module`.
391    fn ensure_undefined(&self, module: &str, name: &str) -> Result<(), LinkerError> {
392        if let Some(shared) = &self.shared {
393            if shared.has_definition(module, name) {
394                return Err(LinkerError::DuplicateDefinition {
395                    import_name: ImportName::new(module, name),
396                });
397            }
398        }
399        Ok(())
400    }
401
402    /// Define a new item in this [`Linker`].
403    ///
404    /// # Errors
405    ///
406    /// If there already is a definition under the same name for this [`Linker`].
407    pub fn define(
408        &mut self,
409        module: &str,
410        name: &str,
411        item: impl Into<Extern>,
412    ) -> Result<&mut Self, LinkerError> {
413        self.ensure_undefined(module, name)?;
414        let key = self.inner.new_import_key(module, name);
415        self.inner.insert(key, Definition::Extern(item.into()))?;
416        Ok(self)
417    }
418
419    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
420    ///
421    /// For more information see [`Linker::func_wrap`].
422    ///
423    /// # Errors
424    ///
425    /// If there already is a definition under the same name for this [`Linker`].
426    pub fn func_new(
427        &mut self,
428        module: &str,
429        name: &str,
430        ty: FuncType,
431        func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
432    ) -> Result<&mut Self, LinkerError> {
433        self.ensure_undefined(module, name)?;
434        let func = HostFuncTrampolineEntity::new(ty, func);
435        let key = self.inner.new_import_key(module, name);
436        self.inner.insert(key, Definition::HostFunc(func))?;
437        Ok(self)
438    }
439
440    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
441    ///
442    /// For information how to use this API see [`Func::wrap`].
443    ///
444    /// This method creates a host function for this [`Linker`] under the given name.
445    /// It is distinct in its ability to create a [`Store`] independent
446    /// host function. Host functions defined this way can be used to instantiate
447    /// instances in multiple different [`Store`] entities.
448    ///
449    /// The same applies to other [`Linker`] methods to define new [`Func`] instances
450    /// such as [`Linker::func_new`].
451    ///
452    /// In a concurrently running program, this means that these host functions
453    /// could be called concurrently if different [`Store`] entities are executing on
454    /// different threads.
455    ///
456    /// # Errors
457    ///
458    /// If there already is a definition under the same name for this [`Linker`].
459    ///
460    /// [`Store`]: crate::Store
461    pub fn func_wrap<Params, Args>(
462        &mut self,
463        module: &str,
464        name: &str,
465        func: impl IntoFunc<T, Params, Args>,
466    ) -> Result<&mut Self, LinkerError> {
467        self.ensure_undefined(module, name)?;
468        let func = HostFuncTrampolineEntity::wrap(func);
469        let key = self.inner.new_import_key(module, name);
470        self.inner.insert(key, Definition::HostFunc(func))?;
471        Ok(self)
472    }
473
474    /// Looks up a defined [`Extern`] by name in this [`Linker`].
475    ///
476    /// - Returns `None` if this name was not previously defined in this [`Linker`].
477    /// - Returns `None` if the definition is a [`Linker`] defined host function.
478    ///
479    /// # Panics
480    ///
481    /// If the [`Engine`] of this [`Linker`] and the [`Engine`] of `context` are not the same.
482    pub fn get(
483        &self,
484        context: impl AsContext<Data = T>,
485        module: &str,
486        name: &str,
487    ) -> Option<Extern> {
488        match self.get_definition(context, module, name) {
489            Some(Definition::Extern(item)) => Some(*item),
490            _ => None,
491        }
492    }
493
494    /// Looks up a [`Definition`] by name in this [`Linker`].
495    ///
496    /// Returns `None` if this name was not previously defined in this [`Linker`].
497    ///
498    /// # Panics
499    ///
500    /// If the [`Engine`] of this [`Linker`] and the [`Engine`] of `context` are not the same.
501    fn get_definition(
502        &self,
503        context: impl AsContext<Data = T>,
504        module: &str,
505        name: &str,
506    ) -> Option<&Definition<T>> {
507        assert!(Engine::same(
508            context.as_context().store.engine(),
509            self.engine()
510        ));
511        if let Some(shared) = &self.shared {
512            if let Some(item) = shared.get_definition(module, name) {
513                return Some(item);
514            }
515        }
516        self.inner.get_definition(module, name)
517    }
518
519    /// Instantiates the given [`Module`] using the definitions in the [`Linker`].
520    ///
521    /// # Panics
522    ///
523    /// If the [`Engine`] of the [`Linker`] and `context` are not the same.
524    ///
525    /// # Errors
526    ///
527    /// - If the linker does not define imports of the instantiated [`Module`].
528    /// - If any imported item does not satisfy its type requirements.
529    pub fn instantiate(
530        &self,
531        mut context: impl AsContextMut<Data = T>,
532        module: &Module,
533    ) -> Result<InstancePre, Error> {
534        assert!(Engine::same(self.engine(), context.as_context().engine()));
535        // TODO: possibly add further resource limtation here on number of externals.
536        // Not clear that user can't import the same external lots of times to inflate this.
537        let externals = module
538            .imports()
539            .map(|import| self.process_import(&mut context, import))
540            .collect::<Result<Vec<Extern>, Error>>()?;
541        module.instantiate(context, externals)
542    }
543
544    /// Processes a single [`Module`] import.
545    ///
546    /// # Panics
547    ///
548    /// If the [`Engine`] of the [`Linker`] and `context` are not the same.
549    ///
550    /// # Errors
551    ///
552    /// If the imported item does not satisfy constraints set by the [`Module`].
553    fn process_import(
554        &self,
555        mut context: impl AsContextMut<Data = T>,
556        import: ImportType,
557    ) -> Result<Extern, Error> {
558        assert!(Engine::same(self.engine(), context.as_context().engine()));
559        let import_name = import.import_name();
560        let module_name = import.module();
561        let field_name = import.name();
562        let resolved = self
563            .get_definition(context.as_context(), module_name, field_name)
564            .ok_or_else(|| LinkerError::missing_definition(&import))?;
565        let invalid_type = || LinkerError::invalid_type_definition(&import, &resolved.ty(&context));
566        match import.ty() {
567            ExternType::Func(expected_type) => {
568                let found_type = resolved
569                    .ty(&context)
570                    .func()
571                    .cloned()
572                    .ok_or_else(invalid_type)?;
573                if &found_type != expected_type {
574                    return Err(Error::from(LinkerError::func_type_mismatch(
575                        import_name,
576                        expected_type,
577                        &found_type,
578                    )));
579                }
580                let func = resolved
581                    .as_func(&mut context)
582                    .expect("already asserted that `resolved` is a function");
583                Ok(Extern::Func(func))
584            }
585            ExternType::Table(expected_type) => {
586                let table = resolved
587                    .as_extern()
588                    .copied()
589                    .and_then(Extern::into_table)
590                    .ok_or_else(invalid_type)?;
591                let found_type = table.dynamic_ty(context);
592                found_type.is_subtype_or_err(expected_type).map_err(|_| {
593                    LinkerError::table_type_mismatch(import_name, expected_type, &found_type)
594                })?;
595                Ok(Extern::Table(table))
596            }
597            ExternType::Memory(expected_type) => {
598                let memory = resolved
599                    .as_extern()
600                    .copied()
601                    .and_then(Extern::into_memory)
602                    .ok_or_else(invalid_type)?;
603                let found_type = memory.dynamic_ty(context);
604                found_type.is_subtype_or_err(expected_type).map_err(|_| {
605                    LinkerError::invalid_memory_subtype(import_name, expected_type, &found_type)
606                })?;
607                Ok(Extern::Memory(memory))
608            }
609            ExternType::Global(expected_type) => {
610                let global = resolved
611                    .as_extern()
612                    .copied()
613                    .and_then(Extern::into_global)
614                    .ok_or_else(invalid_type)?;
615                let found_type = global.ty(context);
616                if &found_type != expected_type {
617                    return Err(Error::from(LinkerError::global_type_mismatch(
618                        import_name,
619                        expected_type,
620                        &found_type,
621                    )));
622                }
623                Ok(Extern::Global(global))
624            }
625        }
626    }
627}
628
629/// Contains type states for the [`LinkerBuilder`] construction process.
630pub mod state {
631    /// Signals that the [`LinkerBuilder`] is itself under construction.
632    ///
633    /// [`LinkerBuilder`]: super::LinkerBuilder
634    pub enum Constructing {}
635
636    /// Signals that the [`LinkerBuilder`] is ready to create new [`Linker`] instances.
637    ///
638    /// [`Linker`]: super::Linker
639    /// [`LinkerBuilder`]: super::LinkerBuilder
640    pub enum Ready {}
641}
642
643/// A linker used to define module imports and instantiate module instances.
644///
645/// Create this type via the [`Linker::build`] method.
646#[derive(Debug)]
647pub struct LinkerBuilder<State, T> {
648    /// Internal linker implementation details.
649    inner: Arc<LinkerInner<T>>,
650    /// The [`LinkerBuilder`] type state.
651    marker: PhantomData<fn() -> State>,
652}
653
654impl<T> Clone for LinkerBuilder<state::Ready, T> {
655    fn clone(&self) -> Self {
656        Self {
657            inner: self.inner.clone(),
658            marker: PhantomData,
659        }
660    }
661}
662
663impl<T> LinkerBuilder<state::Ready, T> {
664    /// Finishes construction of the [`Linker`] by attaching an [`Engine`].
665    pub fn create(&self, engine: &Engine) -> Linker<T> {
666        Linker {
667            engine: engine.clone(),
668            shared: self.inner.clone().into(),
669            inner: <LinkerInner<T>>::default(),
670        }
671    }
672}
673
674impl<T> LinkerBuilder<state::Constructing, T> {
675    /// Signals that the [`LinkerBuilder`] is now ready to create new [`Linker`] instances.
676    pub fn finish(self) -> LinkerBuilder<state::Ready, T> {
677        LinkerBuilder {
678            inner: self.inner,
679            marker: PhantomData,
680        }
681    }
682
683    /// Returns an exclusive reference to the underlying [`Linker`] internals if no [`Linker`] has been built, yet.
684    ///
685    /// # Panics
686    ///
687    /// If the [`LinkerBuilder`] has already created a [`Linker`] using [`LinkerBuilder::finish`].
688    fn inner_mut(&mut self) -> &mut LinkerInner<T> {
689        Arc::get_mut(&mut self.inner).unwrap_or_else(|| {
690            unreachable!("tried to define host function in LinkerBuilder after Linker creation")
691        })
692    }
693
694    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
695    ///
696    /// For more information see [`Linker::func_wrap`].
697    ///
698    /// # Errors
699    ///
700    /// If there already is a definition under the same name for this [`Linker`].
701    ///
702    /// # Panics
703    ///
704    /// If the [`LinkerBuilder`] has already created a [`Linker`] using [`LinkerBuilder::finish`].
705    pub fn func_new(
706        &mut self,
707        module: &str,
708        name: &str,
709        ty: FuncType,
710        func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
711    ) -> Result<&mut Self, LinkerError> {
712        self.inner_mut().func_new(module, name, ty, func)?;
713        Ok(self)
714    }
715
716    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
717    ///
718    /// For information how to use this API see [`Func::wrap`].
719    ///
720    /// This method creates a host function for this [`Linker`] under the given name.
721    /// It is distinct in its ability to create a [`Store`] independent
722    /// host function. Host functions defined this way can be used to instantiate
723    /// instances in multiple different [`Store`] entities.
724    ///
725    /// The same applies to other [`Linker`] methods to define new [`Func`] instances
726    /// such as [`Linker::func_new`].
727    ///
728    /// In a concurrently running program, this means that these host functions
729    /// could be called concurrently if different [`Store`] entities are executing on
730    /// different threads.
731    ///
732    /// # Errors
733    ///
734    /// If there already is a definition under the same name for this [`Linker`].
735    ///
736    /// [`Store`]: crate::Store
737    ///
738    /// # Panics
739    ///
740    /// If the [`LinkerBuilder`] has already created a [`Linker`] using [`LinkerBuilder::finish`].
741    pub fn func_wrap<Params, Args>(
742        &mut self,
743        module: &str,
744        name: &str,
745        func: impl IntoFunc<T, Params, Args>,
746    ) -> Result<&mut Self, LinkerError> {
747        self.inner_mut().func_wrap(module, name, func)?;
748        Ok(self)
749    }
750}
751
752/// Internal [`Linker`] implementation.
753#[derive(Debug)]
754pub struct LinkerInner<T> {
755    /// Allows to efficiently store strings and deduplicate them..
756    strings: StringInterner,
757    /// Stores the definitions given their names.
758    ///
759    /// # Dev. Note
760    ///
761    /// Benchmarks show that [`BTreeMap`] performs better than [`HashMap`]
762    /// which is why we do not use [`wasmi_collections::Map`] here.
763    ///
764    /// [`HashMap`]: std::collections::HashMap
765    definitions: BTreeMap<ImportKey, Definition<T>>,
766}
767
768impl<T> Default for LinkerInner<T> {
769    fn default() -> Self {
770        Self {
771            strings: StringInterner::default(),
772            definitions: BTreeMap::default(),
773        }
774    }
775}
776
777impl<T> Clone for LinkerInner<T> {
778    fn clone(&self) -> Self {
779        Self {
780            strings: self.strings.clone(),
781            definitions: self.definitions.clone(),
782        }
783    }
784}
785
786impl<T> LinkerInner<T> {
787    /// Returns the import key for the module name and item name.
788    fn new_import_key(&mut self, module: &str, name: &str) -> ImportKey {
789        ImportKey::new(
790            self.strings
791                .get_or_intern_with_hint(module, InternHint::LikelyExists),
792            self.strings
793                .get_or_intern_with_hint(name, InternHint::LikelyNew),
794        )
795    }
796
797    /// Returns the import key for the module name and item name.
798    fn get_import_key(&self, module: &str, name: &str) -> Option<ImportKey> {
799        Some(ImportKey::new(
800            self.strings.get(module)?,
801            self.strings.get(name)?,
802        ))
803    }
804
805    /// Resolves the module and item name of the import key if any.
806    fn resolve_import_key(&self, key: ImportKey) -> Option<(&str, &str)> {
807        let module_name = self.strings.resolve(key.module())?;
808        let item_name = self.strings.resolve(key.name())?;
809        Some((module_name, item_name))
810    }
811
812    /// Inserts the extern item under the import key.
813    ///
814    /// # Errors
815    ///
816    /// If there already is a definition for the import key for this [`Linker`].
817    fn insert(&mut self, key: ImportKey, item: Definition<T>) -> Result<(), LinkerError> {
818        match self.definitions.entry(key) {
819            Entry::Occupied(_) => {
820                let (module_name, field_name) = self
821                    .resolve_import_key(key)
822                    .unwrap_or_else(|| panic!("encountered missing import names for key {key:?}"));
823                let import_name = ImportName::new(module_name, field_name);
824                return Err(LinkerError::DuplicateDefinition { import_name });
825            }
826            Entry::Vacant(v) => {
827                v.insert(item);
828            }
829        }
830        Ok(())
831    }
832
833    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
834    ///
835    /// For more information see [`Linker::func_wrap`].
836    ///
837    /// # Errors
838    ///
839    /// If there already is a definition under the same name for this [`Linker`].
840    pub fn func_new(
841        &mut self,
842        module: &str,
843        name: &str,
844        ty: FuncType,
845        func: impl Fn(Caller<'_, T>, &[Val], &mut [Val]) -> Result<(), Error> + Send + Sync + 'static,
846    ) -> Result<&mut Self, LinkerError> {
847        let func = HostFuncTrampolineEntity::new(ty, func);
848        let key = self.new_import_key(module, name);
849        self.insert(key, Definition::HostFunc(func))?;
850        Ok(self)
851    }
852
853    /// Creates a new named [`Func::new`]-style host [`Func`] for this [`Linker`].
854    ///
855    /// For information how to use this API see [`Func::wrap`].
856    ///
857    /// This method creates a host function for this [`Linker`] under the given name.
858    /// It is distinct in its ability to create a [`Store`] independent
859    /// host function. Host functions defined this way can be used to instantiate
860    /// instances in multiple different [`Store`] entities.
861    ///
862    /// The same applies to other [`Linker`] methods to define new [`Func`] instances
863    /// such as [`Linker::func_new`].
864    ///
865    /// In a concurrently running program, this means that these host functions
866    /// could be called concurrently if different [`Store`] entities are executing on
867    /// different threads.
868    ///
869    /// # Errors
870    ///
871    /// If there already is a definition under the same name for this [`Linker`].
872    ///
873    /// [`Store`]: crate::Store
874    pub fn func_wrap<Params, Args>(
875        &mut self,
876        module: &str,
877        name: &str,
878        func: impl IntoFunc<T, Params, Args>,
879    ) -> Result<&mut Self, LinkerError> {
880        let func = HostFuncTrampolineEntity::wrap(func);
881        let key = self.new_import_key(module, name);
882        self.insert(key, Definition::HostFunc(func))?;
883        Ok(self)
884    }
885
886    /// Looks up a [`Definition`] by name in this [`Linker`].
887    ///
888    /// Returns `None` if this name was not previously defined in this [`Linker`].
889    ///
890    /// # Panics
891    ///
892    /// If the [`Engine`] of this [`Linker`] and the [`Engine`] of `context` are not the same.
893    fn get_definition(&self, module: &str, name: &str) -> Option<&Definition<T>> {
894        let key = self.get_import_key(module, name)?;
895        self.definitions.get(&key)
896    }
897
898    /// Returns `true` if [`LinkerInner`] contains a [`Definition`] for `name` in `module`.
899    fn has_definition(&self, module: &str, name: &str) -> bool {
900        let Some(key) = self.get_import_key(module, name) else {
901            return false;
902        };
903        self.definitions.contains_key(&key)
904    }
905}
906
907#[cfg(test)]
908mod tests {
909    use crate::core::ValType;
910
911    use super::*;
912    use crate::Store;
913
914    struct HostState {
915        a: i32,
916        b: i64,
917    }
918
919    #[test]
920    fn linker_funcs_work() {
921        let engine = Engine::default();
922        let mut linker = <Linker<HostState>>::new(&engine);
923        linker
924            .func_new(
925                "host",
926                "get_a",
927                FuncType::new([], [ValType::I32]),
928                |ctx: Caller<HostState>, _params: &[Val], results: &mut [Val]| {
929                    results[0] = Val::from(ctx.data().a);
930                    Ok(())
931                },
932            )
933            .unwrap();
934        linker
935            .func_new(
936                "host",
937                "set_a",
938                FuncType::new([ValType::I32], []),
939                |mut ctx: Caller<HostState>, params: &[Val], _results: &mut [Val]| {
940                    ctx.data_mut().a = params[0].i32().unwrap();
941                    Ok(())
942                },
943            )
944            .unwrap();
945        linker
946            .func_wrap("host", "get_b", |ctx: Caller<HostState>| ctx.data().b)
947            .unwrap();
948        linker
949            .func_wrap("host", "set_b", |mut ctx: Caller<HostState>, value: i64| {
950                ctx.data_mut().b = value
951            })
952            .unwrap();
953        let a_init = 42;
954        let b_init = 77;
955        let mut store = <Store<HostState>>::new(
956            &engine,
957            HostState {
958                a: a_init,
959                b: b_init,
960            },
961        );
962        let wat = r#"
963                (module
964                    (import "host" "get_a" (func $host_get_a (result i32)))
965                    (import "host" "set_a" (func $host_set_a (param i32)))
966                    (import "host" "get_b" (func $host_get_b (result i64)))
967                    (import "host" "set_b" (func $host_set_b (param i64)))
968
969                    (func (export "wasm_get_a") (result i32)
970                        (call $host_get_a)
971                    )
972                    (func (export "wasm_set_a") (param $param i32)
973                        (call $host_set_a (local.get $param))
974                    )
975
976                    (func (export "wasm_get_b") (result i64)
977                        (call $host_get_b)
978                    )
979                    (func (export "wasm_set_b") (param $param i64)
980                        (call $host_set_b (local.get $param))
981                    )
982                )
983            "#;
984        let wasm = wat::parse_str(wat).unwrap();
985        let module = Module::new(&engine, &wasm[..]).unwrap();
986        let instance = linker
987            .instantiate(&mut store, &module)
988            .unwrap()
989            .start(&mut store)
990            .unwrap();
991
992        let wasm_get_a = instance
993            .get_typed_func::<(), i32>(&store, "wasm_get_a")
994            .unwrap();
995        let wasm_set_a = instance
996            .get_typed_func::<i32, ()>(&store, "wasm_set_a")
997            .unwrap();
998        let wasm_get_b = instance
999            .get_typed_func::<(), i64>(&store, "wasm_get_b")
1000            .unwrap();
1001        let wasm_set_b = instance
1002            .get_typed_func::<i64, ()>(&store, "wasm_set_b")
1003            .unwrap();
1004
1005        assert_eq!(wasm_get_a.call(&mut store, ()).unwrap(), a_init);
1006        wasm_set_a.call(&mut store, 100).unwrap();
1007        assert_eq!(wasm_get_a.call(&mut store, ()).unwrap(), 100);
1008
1009        assert_eq!(wasm_get_b.call(&mut store, ()).unwrap(), b_init);
1010        wasm_set_b.call(&mut store, 200).unwrap();
1011        assert_eq!(wasm_get_b.call(&mut store, ()).unwrap(), 200);
1012    }
1013
1014    #[test]
1015    fn build_linker() {
1016        let mut builder = <Linker<()>>::build();
1017        builder
1018            .func_wrap("env", "foo", || std::println!("called foo"))
1019            .unwrap();
1020        builder
1021            .func_new(
1022                "env",
1023                "bar",
1024                FuncType::new([], []),
1025                |_caller, _params, _results| {
1026                    std::println!("called bar");
1027                    Ok(())
1028                },
1029            )
1030            .unwrap();
1031        let builder = builder.finish();
1032        for _ in 0..3 {
1033            let engine = Engine::default();
1034            let _ = builder.create(&engine);
1035        }
1036    }
1037
1038    #[test]
1039    fn linker_builder_uses() {
1040        use crate::{Engine, Linker, Module, Store};
1041        let wasm = wat::parse_str(
1042            r#"
1043            (module
1044                (import "host" "func.0" (func $host_func.0))
1045                (import "host" "func.1" (func $host_func.1))
1046                (func (export "hello")
1047                    (call $host_func.0)
1048                    (call $host_func.1)
1049                )
1050            )"#,
1051        )
1052        .unwrap();
1053        let engine = Engine::default();
1054        let mut builder = <Linker<()>>::build();
1055        builder
1056            .func_wrap("host", "func.0", |_caller: Caller<()>| unimplemented!())
1057            .unwrap();
1058        builder
1059            .func_wrap("host", "func.1", |_caller: Caller<()>| unimplemented!())
1060            .unwrap();
1061        let linker = builder.finish().create(&engine);
1062        let mut store = Store::new(&engine, ());
1063        let module = Module::new(&engine, &wasm[..]).unwrap();
1064        linker.instantiate(&mut store, &module).unwrap();
1065    }
1066
1067    #[test]
1068    fn linker_builder_and_linker_uses() {
1069        use crate::{Engine, Linker, Module, Store};
1070        let wasm = wat::parse_str(
1071            r#"
1072            (module
1073                (import "host" "func.0" (func $host_func.0))
1074                (import "host" "func.1" (func $host_func.1))
1075                (func (export "hello")
1076                    (call $host_func.0)
1077                    (call $host_func.1)
1078                )
1079            )"#,
1080        )
1081        .unwrap();
1082        let engine = Engine::default();
1083        let mut builder = <Linker<()>>::build();
1084        builder
1085            .func_wrap("host", "func.0", |_caller: Caller<()>| unimplemented!())
1086            .unwrap();
1087        let mut linker = builder.finish().create(&engine);
1088        linker
1089            .func_wrap("host", "func.1", |_caller: Caller<()>| unimplemented!())
1090            .unwrap();
1091        let mut store = Store::new(&engine, ());
1092        let module = Module::new(&engine, &wasm[..]).unwrap();
1093        linker.instantiate(&mut store, &module).unwrap();
1094    }
1095
1096    #[test]
1097    fn linker_builder_no_overwrite() {
1098        use crate::{Engine, Linker};
1099        let engine = Engine::default();
1100        let mut builder = <Linker<()>>::build();
1101        builder
1102            .func_wrap("host", "func.0", |_caller: Caller<()>| unimplemented!())
1103            .unwrap();
1104        let mut linker = builder.finish().create(&engine);
1105        linker
1106            .func_wrap("host", "func.1", |_caller: Caller<()>| unimplemented!())
1107            .unwrap();
1108        // The following definition won't shadow the previous 'host/func.0' func and errors instead:
1109        linker
1110            .func_wrap("host", "func.0", |_caller: Caller<()>| unimplemented!())
1111            .unwrap_err();
1112    }
1113
1114    #[test]
1115    fn populate_via_imports() {
1116        use crate::{Engine, Func, Linker, Memory, MemoryType, Module, Store};
1117        let wasm = wat::parse_str(
1118            r#"
1119            (module
1120                (import "host" "hello" (func $host_hello (param i32) (result i32)))
1121                (import "env" "memory" (memory $mem 0 4096))
1122                (func (export "hello") (result i32)
1123                    (call $host_hello (i32.const 3))
1124                    (i32.const 2)
1125                    i32.add
1126                )
1127            )"#,
1128        )
1129        .unwrap();
1130        let engine = Engine::default();
1131        let mut linker = <Linker<()>>::new(&engine);
1132        let mut store = Store::new(&engine, ());
1133        let memory = Memory::new(&mut store, MemoryType::new(1, Some(4096)).unwrap()).unwrap();
1134        let module = Module::new(&engine, &wasm[..]).unwrap();
1135        linker.define("env", "memory", memory).unwrap();
1136        let func = Func::new(
1137            &mut store,
1138            FuncType::new([ValType::I32], [ValType::I32]),
1139            |_caller, _params, _results| todo!(),
1140        );
1141        linker.define("host", "hello", func).unwrap();
1142        linker.instantiate(&mut store, &module).unwrap();
1143    }
1144}