wasmtime/runtime/component/
linker.rs

1use crate::component::func::HostFunc;
2use crate::component::instance::RuntimeImport;
3use crate::component::matching::{InstanceType, TypeChecker};
4use crate::component::types;
5use crate::component::{
6    Component, ComponentNamedList, Instance, InstancePre, Lift, Lower, ResourceType, Val,
7};
8use crate::hash_map::HashMap;
9use crate::prelude::*;
10use crate::{AsContextMut, Engine, Module, StoreContextMut};
11use alloc::sync::Arc;
12use core::marker;
13#[cfg(feature = "async")]
14use core::{future::Future, pin::Pin};
15use wasmtime_environ::component::{NameMap, NameMapIntern};
16use wasmtime_environ::PrimaryMap;
17
18/// A type used to instantiate [`Component`]s.
19///
20/// This type is used to both link components together as well as supply host
21/// functionality to components. Values are defined in a [`Linker`] by their
22/// import name and then components are instantiated with a [`Linker`] using the
23/// names provided for name resolution of the component's imports.
24///
25/// # Names and Semver
26///
27/// Names defined in a [`Linker`] correspond to import names in the Component
28/// Model. Names in the Component Model are allowed to be semver-qualified, for
29/// example:
30///
31/// * `wasi:cli/stdout@0.2.0`
32/// * `wasi:http/types@0.2.0-rc-2023-10-25`
33/// * `my:custom/plugin@1.0.0-pre.2`
34///
35/// These version strings are taken into account when looking up names within a
36/// [`Linker`]. You're allowed to define any number of versions within a
37/// [`Linker`] still, for example you can define `a:b/c@0.2.0`, `a:b/c@0.2.1`,
38/// and `a:b/c@0.3.0` all at the same time.
39///
40/// Specifically though when names are looked up within a linker, for example
41/// during instantiation, semver-compatible names are automatically consulted.
42/// This means that if you define `a:b/c@0.2.1` in a [`Linker`] but a component
43/// imports `a:b/c@0.2.0` then that import will resolve to the `0.2.1` version.
44///
45/// This lookup behavior relies on hosts being well-behaved when using Semver,
46/// specifically that interfaces once defined are never changed. This reflects
47/// how Semver works at the Component Model layer, and it's assumed that if
48/// versions are present then hosts are respecting this.
49///
50/// Note that this behavior goes the other direction, too. If a component
51/// imports `a:b/c@0.2.1` and the host has provided `a:b/c@0.2.0` then that
52/// will also resolve correctly. This is because if an API was defined at 0.2.0
53/// and 0.2.1 then it must be the same API.
54///
55/// This behavior is intended to make it easier for hosts to upgrade WASI and
56/// for guests to upgrade WASI. So long as the actual "meat" of the
57/// functionality is defined then it should align correctly and components can
58/// be instantiated.
59pub struct Linker<T> {
60    engine: Engine,
61    strings: Strings,
62    map: NameMap<usize, Definition>,
63    path: Vec<usize>,
64    allow_shadowing: bool,
65    _marker: marker::PhantomData<fn() -> T>,
66}
67
68impl<T> Clone for Linker<T> {
69    fn clone(&self) -> Linker<T> {
70        Linker {
71            engine: self.engine.clone(),
72            strings: self.strings.clone(),
73            map: self.map.clone(),
74            path: self.path.clone(),
75            allow_shadowing: self.allow_shadowing,
76            _marker: self._marker,
77        }
78    }
79}
80
81#[derive(Clone, Default)]
82pub struct Strings {
83    string2idx: HashMap<Arc<str>, usize>,
84    strings: Vec<Arc<str>>,
85}
86
87/// Structure representing an "instance" being defined within a linker.
88///
89/// Instances do not need to be actual [`Instance`]s and instead are defined by
90/// a "bag of named items", so each [`LinkerInstance`] can further define items
91/// internally.
92pub struct LinkerInstance<'a, T> {
93    engine: &'a Engine,
94    path: &'a mut Vec<usize>,
95    path_len: usize,
96    strings: &'a mut Strings,
97    map: &'a mut NameMap<usize, Definition>,
98    allow_shadowing: bool,
99    _marker: marker::PhantomData<fn() -> T>,
100}
101
102#[derive(Clone, Debug)]
103pub(crate) enum Definition {
104    Instance(NameMap<usize, Definition>),
105    Func(Arc<HostFunc>),
106    Module(Module),
107    Resource(ResourceType, Arc<crate::func::HostFunc>),
108}
109
110impl<T> Linker<T> {
111    /// Creates a new linker for the [`Engine`] specified with no items defined
112    /// within it.
113    pub fn new(engine: &Engine) -> Linker<T> {
114        Linker {
115            engine: engine.clone(),
116            strings: Strings::default(),
117            map: NameMap::default(),
118            allow_shadowing: false,
119            path: Vec::new(),
120            _marker: marker::PhantomData,
121        }
122    }
123
124    /// Returns the [`Engine`] this is connected to.
125    pub fn engine(&self) -> &Engine {
126        &self.engine
127    }
128
129    /// Configures whether or not name-shadowing is allowed.
130    ///
131    /// By default name shadowing is not allowed and it's an error to redefine
132    /// the same name within a linker.
133    pub fn allow_shadowing(&mut self, allow: bool) -> &mut Self {
134        self.allow_shadowing = allow;
135        self
136    }
137
138    /// Returns the "root instance" of this linker, used to define names into
139    /// the root namespace.
140    pub fn root(&mut self) -> LinkerInstance<'_, T> {
141        LinkerInstance {
142            engine: &self.engine,
143            path: &mut self.path,
144            path_len: 0,
145            strings: &mut self.strings,
146            map: &mut self.map,
147            allow_shadowing: self.allow_shadowing,
148            _marker: self._marker,
149        }
150    }
151
152    /// Returns a builder for the named instance specified.
153    ///
154    /// # Errors
155    ///
156    /// Returns an error if `name` is already defined within the linker.
157    pub fn instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>> {
158        self.root().into_instance(name)
159    }
160
161    fn typecheck<'a>(&'a self, component: &'a Component) -> Result<TypeChecker<'a>> {
162        let mut cx = TypeChecker {
163            engine: &self.engine,
164            types: component.types(),
165            strings: &self.strings,
166            imported_resources: Default::default(),
167        };
168
169        // Walk over the component's list of import names and use that to lookup
170        // the definition within this linker that it corresponds to. When found
171        // perform a typecheck against the component's expected type.
172        let env_component = component.env_component();
173        for (_idx, (name, ty)) in env_component.import_types.iter() {
174            let import = self.map.get(name, &self.strings);
175            cx.definition(ty, import)
176                .with_context(|| format!("component imports {desc} `{name}`, but a matching implementation was not found in the linker", desc = ty.desc()))?;
177        }
178        Ok(cx)
179    }
180
181    /// Returns the [`types::Component`] corresponding to `component` with resource
182    /// types imported by it replaced using imports present in [`Self`].
183    pub fn substituted_component_type(&self, component: &Component) -> Result<types::Component> {
184        let cx = self.typecheck(&component)?;
185        Ok(types::Component::from(
186            component.ty(),
187            &InstanceType {
188                types: cx.types,
189                resources: &cx.imported_resources,
190            },
191        ))
192    }
193
194    /// Performs a "pre-instantiation" to resolve the imports of the
195    /// [`Component`] specified with the items defined within this linker.
196    ///
197    /// This method will perform as much work as possible short of actually
198    /// instantiating an instance. Internally this will use the names defined
199    /// within this linker to satisfy the imports of the [`Component`] provided.
200    /// Additionally this will perform type-checks against the component's
201    /// imports against all items defined within this linker.
202    ///
203    /// Note that unlike internally in components where subtyping at the
204    /// interface-types layer is supported this is not supported here. Items
205    /// defined in this linker must match the component's imports precisely.
206    ///
207    /// # Errors
208    ///
209    /// Returns an error if this linker doesn't define a name that the
210    /// `component` imports or if a name defined doesn't match the type of the
211    /// item imported by the `component` provided.
212    pub fn instantiate_pre(&self, component: &Component) -> Result<InstancePre<T>> {
213        let cx = self.typecheck(&component)?;
214
215        // A successful typecheck resolves all of the imported resources used by
216        // this InstancePre. We keep a clone of this table in the InstancePre
217        // so that we can construct an InstanceType for typechecking.
218        let imported_resources = cx.imported_resources.clone();
219
220        // Now that all imports are known to be defined and satisfied by this
221        // linker a list of "flat" import items (aka no instances) is created
222        // using the import map within the component created at
223        // component-compile-time.
224        let env_component = component.env_component();
225        let mut imports = PrimaryMap::with_capacity(env_component.imports.len());
226        for (idx, (import, names)) in env_component.imports.iter() {
227            let (root, _) = &env_component.import_types[*import];
228
229            // This is the flattening process where we go from a definition
230            // optionally through a list of exported names to get to the final
231            // item.
232            let mut cur = self.map.get(root, &self.strings).unwrap();
233            for name in names {
234                cur = match cur {
235                    Definition::Instance(map) => map.get(&name, &self.strings).unwrap(),
236                    _ => unreachable!(),
237                };
238            }
239            let import = match cur {
240                Definition::Module(m) => RuntimeImport::Module(m.clone()),
241                Definition::Func(f) => RuntimeImport::Func(f.clone()),
242                Definition::Resource(t, dtor) => RuntimeImport::Resource {
243                    ty: *t,
244                    _dtor: dtor.clone(),
245                    dtor_funcref: component.resource_drop_func_ref(dtor),
246                },
247
248                // This is guaranteed by the compilation process that "leaf"
249                // runtime imports are never instances.
250                Definition::Instance(_) => unreachable!(),
251            };
252            let i = imports.push(import);
253            assert_eq!(i, idx);
254        }
255        Ok(unsafe {
256            InstancePre::new_unchecked(component.clone(), Arc::new(imports), imported_resources)
257        })
258    }
259
260    /// Instantiates the [`Component`] provided into the `store` specified.
261    ///
262    /// This function will use the items defined within this [`Linker`] to
263    /// satisfy the imports of the [`Component`] provided as necessary. For more
264    /// information about this see [`Linker::instantiate_pre`] as well.
265    ///
266    /// # Errors
267    ///
268    /// Returns an error if this [`Linker`] doesn't define an import that
269    /// `component` requires or if it is of the wrong type. Additionally this
270    /// can return an error if something goes wrong during instantiation such as
271    /// a runtime trap or a runtime limit being exceeded.
272    pub fn instantiate(
273        &self,
274        store: impl AsContextMut<Data = T>,
275        component: &Component,
276    ) -> Result<Instance> {
277        assert!(
278            !store.as_context().async_support(),
279            "must use async instantiation when async support is enabled"
280        );
281        self.instantiate_pre(component)?.instantiate(store)
282    }
283
284    /// Instantiates the [`Component`] provided into the `store` specified.
285    ///
286    /// This is exactly like [`Linker::instantiate`] except for async stores.
287    ///
288    /// # Errors
289    ///
290    /// Returns an error if this [`Linker`] doesn't define an import that
291    /// `component` requires or if it is of the wrong type. Additionally this
292    /// can return an error if something goes wrong during instantiation such as
293    /// a runtime trap or a runtime limit being exceeded.
294    #[cfg(feature = "async")]
295    pub async fn instantiate_async(
296        &self,
297        store: impl AsContextMut<Data = T>,
298        component: &Component,
299    ) -> Result<Instance>
300    where
301        T: Send,
302    {
303        assert!(
304            store.as_context().async_support(),
305            "must use sync instantiation when async support is disabled"
306        );
307        self.instantiate_pre(component)?
308            .instantiate_async(store)
309            .await
310    }
311
312    /// Implement any imports of the given [`Component`] with a function which traps.
313    ///
314    /// By default a [`Linker`] will error when unknown imports are encountered when instantiating a [`Component`].
315    /// This changes this behavior from an instant error to a trap that will happen if the import is called.
316    pub fn define_unknown_imports_as_traps(&mut self, component: &Component) -> Result<()> {
317        use wasmtime_environ::component::ComponentTypes;
318        use wasmtime_environ::component::TypeDef;
319        // Recursively stub out all imports of the component with a function that traps.
320        fn stub_item<T>(
321            linker: &mut LinkerInstance<T>,
322            item_name: &str,
323            item_def: &TypeDef,
324            parent_instance: Option<&str>,
325            types: &ComponentTypes,
326        ) -> Result<()> {
327            // Skip if the item isn't an instance and has already been defined in the linker.
328            if !matches!(item_def, TypeDef::ComponentInstance(_)) && linker.get(item_name).is_some()
329            {
330                return Ok(());
331            }
332
333            match item_def {
334                TypeDef::ComponentFunc(_) => {
335                    let fully_qualified_name = parent_instance
336                        .map(|parent| format!("{parent}#{item_name}"))
337                        .unwrap_or_else(|| item_name.to_owned());
338                    linker.func_new(&item_name, move |_, _, _| {
339                        bail!("unknown import: `{fully_qualified_name}` has not been defined")
340                    })?;
341                }
342                TypeDef::ComponentInstance(i) => {
343                    let instance = &types[*i];
344                    let mut linker_instance = linker.instance(item_name)?;
345                    for (export_name, export) in instance.exports.iter() {
346                        stub_item(
347                            &mut linker_instance,
348                            export_name,
349                            export,
350                            Some(item_name),
351                            types,
352                        )?;
353                    }
354                }
355                TypeDef::Resource(_) => {
356                    let ty = crate::component::ResourceType::host::<()>();
357                    linker.resource(item_name, ty, |_, _| Ok(()))?;
358                }
359                TypeDef::Component(_) | TypeDef::Module(_) => {
360                    bail!("unable to define {} imports as traps", item_def.desc())
361                }
362                _ => {}
363            }
364            Ok(())
365        }
366
367        for (_, (import_name, import_type)) in &component.env_component().import_types {
368            stub_item(
369                &mut self.root(),
370                import_name,
371                import_type,
372                None,
373                component.types(),
374            )?;
375        }
376        Ok(())
377    }
378}
379
380impl<T> LinkerInstance<'_, T> {
381    fn as_mut(&mut self) -> LinkerInstance<'_, T> {
382        LinkerInstance {
383            engine: self.engine,
384            path: self.path,
385            path_len: self.path_len,
386            strings: self.strings,
387            map: self.map,
388            allow_shadowing: self.allow_shadowing,
389            _marker: self._marker,
390        }
391    }
392
393    /// Defines a new host-provided function into this [`Linker`].
394    ///
395    /// This method is used to give host functions to wasm components. The
396    /// `func` provided will be callable from linked components with the type
397    /// signature dictated by `Params` and `Return`. The `Params` is a tuple of
398    /// types that will come from wasm and `Return` is a value coming from the
399    /// host going back to wasm.
400    ///
401    /// Additionally the `func` takes a
402    /// [`StoreContextMut`](crate::StoreContextMut) as its first parameter.
403    ///
404    /// Note that `func` must be an `Fn` and must also be `Send + Sync +
405    /// 'static`. Shared state within a func is typically accessed with the `T`
406    /// type parameter from [`Store<T>`](crate::Store) which is accessible
407    /// through the leading [`StoreContextMut<'_, T>`](crate::StoreContextMut)
408    /// argument which can be provided to the `func` given here.
409    //
410    // TODO: needs more words and examples
411    pub fn func_wrap<F, Params, Return>(&mut self, name: &str, func: F) -> Result<()>
412    where
413        F: Fn(StoreContextMut<T>, Params) -> Result<Return> + Send + Sync + 'static,
414        Params: ComponentNamedList + Lift + 'static,
415        Return: ComponentNamedList + Lower + 'static,
416    {
417        self.insert(name, Definition::Func(HostFunc::from_closure(func)))?;
418        Ok(())
419    }
420
421    /// Defines a new host-provided async function into this [`Linker`].
422    ///
423    /// This is exactly like [`Self::func_wrap`] except it takes an async
424    /// host function.
425    #[cfg(feature = "async")]
426    pub fn func_wrap_async<Params, Return, F>(&mut self, name: &str, f: F) -> Result<()>
427    where
428        F: for<'a> Fn(
429                StoreContextMut<'a, T>,
430                Params,
431            ) -> Box<dyn Future<Output = Result<Return>> + Send + 'a>
432            + Send
433            + Sync
434            + 'static,
435        Params: ComponentNamedList + Lift + 'static,
436        Return: ComponentNamedList + Lower + 'static,
437    {
438        assert!(
439            self.engine.config().async_support,
440            "cannot use `func_wrap_async` without enabling async support in the config"
441        );
442        let ff = move |mut store: StoreContextMut<'_, T>, params: Params| -> Result<Return> {
443            let async_cx = store.as_context_mut().0.async_cx().expect("async cx");
444            let future = f(store.as_context_mut(), params);
445            unsafe { async_cx.block_on(Pin::from(future)) }?
446        };
447        self.func_wrap(name, ff)
448    }
449
450    /// Defines a new host-provided async function into this [`LinkerInstance`].
451    ///
452    /// This allows the caller to register host functions with the
453    /// LinkerInstance such that multiple calls to such functions can run
454    /// concurrently. This isn't possible with the existing func_wrap_async
455    /// method because it takes a function which returns a future that owns a
456    /// unique reference to the Store, meaning the Store can't be used for
457    /// anything else until the future resolves.
458    ///
459    /// Ideally, we'd have a way to thread a `StoreContextMut<T>` through an
460    /// arbitrary `Future` such that it has access to the `Store` only while
461    /// being polled (i.e. between, but not across, await points). However,
462    /// there's currently no way to express that in async Rust, so we make do
463    /// with a more awkward scheme: each function registered using
464    /// `func_wrap_concurrent` gets access to the `Store` twice: once before
465    /// doing any concurrent operations (i.e. before awaiting) and once
466    /// afterward. This allows multiple calls to proceed concurrently without
467    /// any one of them monopolizing the store.
468    #[cfg(feature = "component-model-async")]
469    pub fn func_wrap_concurrent<Params, Return, F, N, FN>(&mut self, name: &str, f: F) -> Result<()>
470    where
471        N: FnOnce(StoreContextMut<T>) -> Result<Return> + Send + Sync + 'static,
472        FN: Future<Output = N> + Send + Sync + 'static,
473        F: Fn(StoreContextMut<T>, Params) -> FN + Send + Sync + 'static,
474        Params: ComponentNamedList + Lift + 'static,
475        Return: ComponentNamedList + Lower + Send + Sync + 'static,
476    {
477        assert!(
478            self.engine.config().async_support,
479            "cannot use `func_wrap_concurrent` without enabling async support in the config"
480        );
481        _ = (name, f);
482        todo!()
483    }
484
485    /// Define a new host-provided function using dynamically typed values.
486    ///
487    /// The `name` provided is the name of the function to define and the
488    /// `func` provided is the host-defined closure to invoke when this
489    /// function is called.
490    ///
491    /// This function is the "dynamic" version of defining a host function as
492    /// compared to [`LinkerInstance::func_wrap`]. With
493    /// [`LinkerInstance::func_wrap`] a function's type is statically known but
494    /// with this method the `func` argument's type isn't known ahead of time.
495    /// That means that `func` can be by imported component so long as it's
496    /// imported as a matching name.
497    ///
498    /// Type information will be available at execution time, however. For
499    /// example when `func` is invoked the second argument, a `&[Val]` list,
500    /// contains [`Val`] entries that say what type they are. Additionally the
501    /// third argument, `&mut [Val]`, is the expected number of results. Note
502    /// that the expected types of the results cannot be learned during the
503    /// execution of `func`. Learning that would require runtime introspection
504    /// of a component.
505    ///
506    /// Return values, stored in the third argument of `&mut [Val]`, are
507    /// type-checked at runtime to ensure that they have the appropriate type.
508    /// A trap will be raised if they do not have the right type.
509    ///
510    /// # Examples
511    ///
512    /// ```
513    /// use wasmtime::{Store, Engine};
514    /// use wasmtime::component::{Component, Linker, Val};
515    ///
516    /// # fn main() -> wasmtime::Result<()> {
517    /// let engine = Engine::default();
518    /// let component = Component::new(
519    ///     &engine,
520    ///     r#"
521    ///         (component
522    ///             (import "thunk" (func $thunk))
523    ///             (import "is-even" (func $is-even (param "x" u32) (result bool)))
524    ///
525    ///             (core module $m
526    ///                 (import "" "thunk" (func $thunk))
527    ///                 (import "" "is-even" (func $is-even (param i32) (result i32)))
528    ///
529    ///                 (func (export "run")
530    ///                     call $thunk
531    ///
532    ///                     (call $is-even (i32.const 1))
533    ///                     if unreachable end
534    ///
535    ///                     (call $is-even (i32.const 2))
536    ///                     i32.eqz
537    ///                     if unreachable end
538    ///                 )
539    ///             )
540    ///             (core func $thunk (canon lower (func $thunk)))
541    ///             (core func $is-even (canon lower (func $is-even)))
542    ///             (core instance $i (instantiate $m
543    ///                 (with "" (instance
544    ///                     (export "thunk" (func $thunk))
545    ///                     (export "is-even" (func $is-even))
546    ///                 ))
547    ///             ))
548    ///
549    ///             (func (export "run") (canon lift (core func $i "run")))
550    ///         )
551    ///     "#,
552    /// )?;
553    ///
554    /// let mut linker = Linker::<()>::new(&engine);
555    ///
556    /// // Sample function that takes no arguments.
557    /// linker.root().func_new("thunk", |_store, params, results| {
558    ///     assert!(params.is_empty());
559    ///     assert!(results.is_empty());
560    ///     println!("Look ma, host hands!");
561    ///     Ok(())
562    /// })?;
563    ///
564    /// // This function takes one argument and returns one result.
565    /// linker.root().func_new("is-even", |_store, params, results| {
566    ///     assert_eq!(params.len(), 1);
567    ///     let param = match params[0] {
568    ///         Val::U32(n) => n,
569    ///         _ => panic!("unexpected type"),
570    ///     };
571    ///
572    ///     assert_eq!(results.len(), 1);
573    ///     results[0] = Val::Bool(param % 2 == 0);
574    ///     Ok(())
575    /// })?;
576    ///
577    /// let mut store = Store::new(&engine, ());
578    /// let instance = linker.instantiate(&mut store, &component)?;
579    /// let run = instance.get_typed_func::<(), ()>(&mut store, "run")?;
580    /// run.call(&mut store, ())?;
581    /// # Ok(())
582    /// # }
583    /// ```
584    pub fn func_new(
585        &mut self,
586        name: &str,
587        func: impl Fn(StoreContextMut<'_, T>, &[Val], &mut [Val]) -> Result<()> + Send + Sync + 'static,
588    ) -> Result<()> {
589        self.insert(name, Definition::Func(HostFunc::new_dynamic(func)))?;
590        Ok(())
591    }
592
593    /// Define a new host-provided async function using dynamic types.
594    ///
595    /// This is exactly like [`Self::func_new`] except it takes an async
596    /// host function.
597    #[cfg(feature = "async")]
598    pub fn func_new_async<F>(&mut self, name: &str, f: F) -> Result<()>
599    where
600        F: for<'a> Fn(
601                StoreContextMut<'a, T>,
602                &'a [Val],
603                &'a mut [Val],
604            ) -> Box<dyn Future<Output = Result<()>> + Send + 'a>
605            + Send
606            + Sync
607            + 'static,
608    {
609        assert!(
610            self.engine.config().async_support,
611            "cannot use `func_new_async` without enabling async support in the config"
612        );
613        let ff = move |mut store: StoreContextMut<'_, T>, params: &[Val], results: &mut [Val]| {
614            let async_cx = store.as_context_mut().0.async_cx().expect("async cx");
615            let future = f(store.as_context_mut(), params, results);
616            unsafe { async_cx.block_on(Pin::from(future)) }?
617        };
618        self.func_new(name, ff)
619    }
620
621    /// Defines a [`Module`] within this instance.
622    ///
623    /// This can be used to provide a core wasm [`Module`] as an import to a
624    /// component. The [`Module`] provided is saved within the linker for the
625    /// specified `name` in this instance.
626    pub fn module(&mut self, name: &str, module: &Module) -> Result<()> {
627        self.insert(name, Definition::Module(module.clone()))?;
628        Ok(())
629    }
630
631    /// Defines a new resource of a given [`ResourceType`] in this linker.
632    ///
633    /// This function is used to specify resources defined in the host.
634    ///
635    /// The `name` argument is the name to define the resource within this
636    /// linker.
637    ///
638    /// The `dtor` provided is a destructor that will get invoked when an owned
639    /// version of this resource is destroyed from the guest. Note that this
640    /// destructor is not called when a host-owned resource is destroyed as it's
641    /// assumed the host knows how to handle destroying its own resources.
642    ///
643    /// The `dtor` closure is provided the store state as the first argument
644    /// along with the representation of the resource that was just destroyed.
645    ///
646    /// [`Resource<U>`]: crate::component::Resource
647    ///
648    /// # Errors
649    ///
650    /// The provided `dtor` closure returns an error if something goes wrong
651    /// when a guest calls the `dtor` to drop a `Resource<T>` such as
652    /// a runtime trap or a runtime limit being exceeded.
653    pub fn resource(
654        &mut self,
655        name: &str,
656        ty: ResourceType,
657        dtor: impl Fn(StoreContextMut<'_, T>, u32) -> Result<()> + Send + Sync + 'static,
658    ) -> Result<()> {
659        let dtor = Arc::new(crate::func::HostFunc::wrap_inner(
660            &self.engine,
661            move |mut cx: crate::Caller<'_, T>, (param,): (u32,)| dtor(cx.as_context_mut(), param),
662        ));
663        self.insert(name, Definition::Resource(ty, dtor))?;
664        Ok(())
665    }
666
667    /// Identical to [`Self::resource`], except that it takes an async destructor.
668    #[cfg(feature = "async")]
669    pub fn resource_async<F>(&mut self, name: &str, ty: ResourceType, dtor: F) -> Result<()>
670    where
671        F: for<'a> Fn(
672                StoreContextMut<'a, T>,
673                u32,
674            ) -> Box<dyn Future<Output = Result<()>> + Send + 'a>
675            + Send
676            + Sync
677            + 'static,
678    {
679        assert!(
680            self.engine.config().async_support,
681            "cannot use `resource_async` without enabling async support in the config"
682        );
683        let dtor = Arc::new(crate::func::HostFunc::wrap_inner(
684            &self.engine,
685            move |mut cx: crate::Caller<'_, T>, (param,): (u32,)| {
686                let async_cx = cx.as_context_mut().0.async_cx().expect("async cx");
687                let future = dtor(cx.as_context_mut(), param);
688                match unsafe { async_cx.block_on(Pin::from(future)) } {
689                    Ok(Ok(())) => Ok(()),
690                    Ok(Err(trap)) | Err(trap) => Err(trap),
691                }
692            },
693        ));
694        self.insert(name, Definition::Resource(ty, dtor))?;
695        Ok(())
696    }
697
698    /// Defines a nested instance within this instance.
699    ///
700    /// This can be used to describe arbitrarily nested levels of instances
701    /// within a linker to satisfy nested instance exports of components.
702    pub fn instance(&mut self, name: &str) -> Result<LinkerInstance<'_, T>> {
703        self.as_mut().into_instance(name)
704    }
705
706    /// Same as [`LinkerInstance::instance`] except with different lifetime
707    /// parameters.
708    pub fn into_instance(mut self, name: &str) -> Result<Self> {
709        let name = self.insert(name, Definition::Instance(NameMap::default()))?;
710        self.map = match self.map.raw_get_mut(&name) {
711            Some(Definition::Instance(map)) => map,
712            _ => unreachable!(),
713        };
714        self.path.truncate(self.path_len);
715        self.path.push(name);
716        self.path_len += 1;
717        Ok(self)
718    }
719
720    fn insert(&mut self, name: &str, item: Definition) -> Result<usize> {
721        self.map
722            .insert(name, self.strings, self.allow_shadowing, item)
723    }
724
725    fn get(&self, name: &str) -> Option<&Definition> {
726        self.map.get(name, self.strings)
727    }
728}
729
730impl NameMapIntern for Strings {
731    type Key = usize;
732
733    fn intern(&mut self, string: &str) -> usize {
734        if let Some(idx) = self.string2idx.get(string) {
735            return *idx;
736        }
737        let string: Arc<str> = string.into();
738        let idx = self.strings.len();
739        self.strings.push(string.clone());
740        self.string2idx.insert(string, idx);
741        idx
742    }
743
744    fn lookup(&self, string: &str) -> Option<usize> {
745        self.string2idx.get(string).cloned()
746    }
747}