wasm_component_layer/
lib.rs

1#![deny(warnings)]
2#![forbid(unsafe_code)]
3#![warn(missing_docs)]
4#![warn(clippy::missing_docs_in_private_items)]
5
6//! `wasm_component_layer` is a runtime agnostic implementation of the [WebAssembly component model](https://github.com/WebAssembly/component-model).
7//! It supports loading and linking WASM components, inspecting and generating component interface types at runtime, and more atop any WebAssembly backend. The implementation is based upon the [`wasmtime`](https://github.com/bytecodealliance/wasmtime), [`js-component-bindgen`](https://github.com/bytecodealliance/jco), and [`wit-parser`](https://github.com/bytecodealliance/wasm-tools/tree/main) crates.
8//!
9//! ## Usage
10//!
11//! To use `wasm_component_layer`, a runtime is required. The [`wasm_runtime_layer`](https://github.com/DouglasDwyer/wasm_runtime_layer) crate provides the common interface used for WebAssembly runtimes, so when using this crate it must also be added to the `Cargo.toml` file with the appropriate runtime selected. For instance, the examples in this repository use the [`wasmi_runtime_layer`](https://crates.io/crates/wasmi_runtime_layer) runtime:
12//!
13//! ```toml
14//! wasm_component_layer = "0.1.16"
15//! wasmi_runtime_layer = "0.31.0"
16//! # wasmtime_runtime_layer = "21.0.0"
17//! # js_wasm_runtime_layer = "0.4.0"
18//! ```
19//!
20//! The following is a small overview of `wasm_component_layer`'s API. The complete example may be found in the [examples folder](/examples). Consider a WASM component with the following WIT:
21//!
22//! ```wit
23//! package test:guest
24//!
25//! interface foo {
26//!     // Selects the item in position n within list x
27//!     select-nth: func(x: list<string>, n: u32) -> string
28//! }
29//!
30//! world guest {
31//!     export foo
32//! }
33//! ```
34//!
35//! The component can be loaded into `wasm_component_layer` and invoked as follows:
36//!
37//! ```ignore
38//! use wasm_component_layer::*;
39//!
40//! // The bytes of the component.
41//! const WASM: &[u8] = include_bytes!("single_component/component.wasm");
42//!
43//! pub fn main() {
44//!     // Create a new engine for instantiating a component.
45//!     let engine = Engine::new(wasmi::Engine::default());
46//!
47//!     // Create a store for managing WASM data and any custom user-defined state.
48//!     let mut store = Store::new(&engine, ());
49//!
50//!     // Parse the component bytes and load its imports and exports.
51//!     let component = Component::new(&engine, WASM).unwrap();
52//!     // Create a linker that will be used to resolve the component's imports, if any.
53//!     let linker = Linker::default();
54//!     // Create an instance of the component using the linker.
55//!     let instance = linker.instantiate(&mut store, &component).unwrap();
56//!
57//!     // Get the interface that the interface exports.
58//!     let interface = instance.exports().instance(&"test:guest/foo".try_into().unwrap()).unwrap();
59//!     // Get the function for selecting a list element.
60//!     let select_nth = interface.func("select-nth").unwrap().typed::<(Vec<String>, u32), String>().unwrap();
61//!
62//!     // Create an example list to test upon.
63//!     let example = ["a", "b", "c"].iter().map(ToString::to_string).collect::<Vec<_>>();
64//!
65//!     println!("Calling select-nth({example:?}, 1) == {}", select_nth.call(&mut store, (example.clone(), 1)).unwrap());
66//!     // Prints 'Calling select-nth(["a", "b", "c"], 1) == b'
67//! }
68//! ```
69//!
70//! ## Features
71//!
72//! `wasm_component_layer` supports the following major features:
73//!
74//! - Parsing and instantiating WASM component binaries
75//! - Runtime generation of component interface types
76//! - Specialized list types for faster lifting/lowering
77//! - Structural equality of component interface types, as mandated by the spec
78//! - Support for guest resources
79//! - Support for strongly-typed host resources with destructors
80//!
81//! The following features have yet to be implemented:
82//!
83//! - A macro for generating host bindings
84//! - More comprehensive tests
85//! - Subtyping
86
87/// Implements the Canonical ABI conventions for converting between guest and host types.
88mod abi;
89
90/// Provides the ability to create and call component model functions.
91mod func;
92
93/// Defines identifiers for component packages and interfaces.
94mod identifier;
95
96/// Defines a macro that will either pattern-match results or throw an error.
97mod require_matches;
98
99/// Defines all types related to the component model.
100mod types;
101
102/// Provides the ability to instantiate component model types.
103mod values;
104
105use std::any::*;
106use std::sync::atomic::*;
107use std::sync::*;
108
109use anyhow::*;
110use fxhash::*;
111use id_arena::*;
112
113use slab::*;
114pub use wasm_runtime_layer::Engine;
115use wasm_runtime_layer::*;
116use wasmtime_environ::component::*;
117use wit_component::*;
118use wit_parser::*;
119
120pub use crate::func::Func;
121pub use crate::func::*;
122pub use crate::identifier::PackageName;
123pub use crate::identifier::*;
124use crate::require_matches::*;
125pub use crate::types::*;
126pub use crate::types::{FuncType, ValueType, VariantCase};
127pub use crate::values::*;
128pub use crate::values::{Enum, Flags, Record, Tuple, Value, Variant};
129
130/// A parsed and validated WebAssembly component, which may be used to instantiate [`Instance`]s.
131#[derive(Clone, Debug)]
132pub struct Component(Arc<ComponentInner>);
133
134impl Component {
135    /// Creates a new component with the given engine and binary data.
136    pub fn new<E: backend::WasmEngine>(engine: &Engine<E>, bytes: &[u8]) -> Result<Self> {
137        let (inner, types) = Self::generate_component(engine, bytes)?;
138        Ok(Self(Arc::new(Self::generate_resources(
139            Self::load_exports(Self::extract_initializers(inner, &types)?, &types)?,
140        )?)))
141    }
142
143    /// The types and interfaces exported by this component.
144    pub fn exports(&self) -> &ComponentTypes {
145        &self.0.export_types
146    }
147
148    /// The types and interfaces imported by this component. To instantiate
149    /// the component, all of these imports must be satisfied by the [`Linker`].
150    pub fn imports(&self) -> &ComponentTypes {
151        &self.0.import_types
152    }
153
154    /// The root package of this component.
155    pub fn package(&self) -> &PackageIdentifier {
156        &self.0.package
157    }
158
159    /// Parses the given bytes into a component, and creates an uninitialized component backing.
160    fn generate_component<E: backend::WasmEngine>(
161        engine: &Engine<E>,
162        bytes: &[u8],
163    ) -> Result<(ComponentInner, wasmtime_environ::component::ComponentTypes)> {
164        /// A counter that uniquely identifies components.
165        static ID_COUNTER: AtomicU64 = AtomicU64::new(0);
166
167        let decoded = wit_component::decode(bytes)
168            .context("Could not decode component information from bytes.")?;
169
170        let (mut resolve, world_id) = match decoded {
171            DecodedWasm::WitPackage(..) => bail!("Cannot instantiate WIT package as module."),
172            DecodedWasm::Component(resolve, id) => (resolve, id),
173        };
174
175        let adapter_vec = wasmtime_environ::ScopeVec::new();
176        let (translation, module_data, component_types) =
177            Self::translate_modules(bytes, &adapter_vec)?;
178
179        let export_mapping = Self::generate_export_mapping(&module_data);
180        let mut modules =
181            FxHashMap::with_capacity_and_hasher(module_data.len(), Default::default());
182
183        for (id, module) in module_data {
184            modules.insert(
185                id,
186                ModuleTranslation {
187                    module: Module::new(engine, std::io::Cursor::new(module.wasm))?,
188                    translation: module.module,
189                },
190            );
191        }
192
193        let mut size_align = SizeAlign::default();
194        size_align.fill(&resolve);
195
196        let package = (&resolve.packages[resolve.worlds[world_id]
197            .package
198            .context("No package associated with world.")?]
199        .name)
200            .into();
201
202        let package_identifiers = Self::generate_package_identifiers(&resolve)?;
203        let interface_identifiers =
204            Self::generate_interface_identifiers(&resolve, &package_identifiers)?;
205
206        let type_identifiers =
207            Self::generate_type_identifiers(&mut resolve, &interface_identifiers);
208
209        Ok((
210            ComponentInner {
211                export_mapping,
212                export_names: FxHashMap::default(),
213                import_types: ComponentTypes::new(),
214                export_types: ComponentTypes::new(),
215                export_info: ExportTypes::default(),
216                extracted_memories: FxHashMap::default(),
217                extracted_reallocs: FxHashMap::default(),
218                extracted_post_returns: FxHashMap::default(),
219                id: ID_COUNTER.fetch_add(1, Ordering::AcqRel),
220                generated_trampolines: FxHashMap::default(),
221                instance_modules: wasmtime_environ::PrimaryMap::default(),
222                interface_identifiers,
223                type_identifiers,
224                modules,
225                resource_map: vec![
226                    TypeResourceTableIndex::from_u32(u32::MAX - 1);
227                    resolve.types.len()
228                ],
229                resolve,
230                size_align,
231                translation,
232                world_id,
233                package,
234            },
235            component_types,
236        ))
237    }
238
239    /// Generates type identifiers for all types in the resolve.
240    fn generate_type_identifiers(
241        resolve: &mut Resolve,
242        interface_ids: &[InterfaceIdentifier],
243    ) -> Vec<Option<TypeIdentifier>> {
244        let mut ids = Vec::with_capacity(resolve.types.len());
245
246        for (_, def) in &mut resolve.types {
247            if let Some(name) = std::mem::take(&mut def.name) {
248                ids.push(Some(TypeIdentifier::new(
249                    name,
250                    match &def.owner {
251                        TypeOwner::Interface(x) => Some(interface_ids[x.index()].clone()),
252                        _ => None,
253                    },
254                )));
255            } else {
256                ids.push(None);
257            }
258        }
259
260        ids
261    }
262
263    /// Creates a mapping from module index to entities, used to resolve component exports at link-time.
264    fn generate_export_mapping(
265        module_data: &wasmtime_environ::PrimaryMap<
266            StaticModuleIndex,
267            wasmtime_environ::ModuleTranslation,
268        >,
269    ) -> FxHashMap<StaticModuleIndex, FxHashMap<wasmtime_environ::EntityIndex, String>> {
270        let mut export_mapping =
271            FxHashMap::with_capacity_and_hasher(module_data.len(), Default::default());
272
273        for (idx, module) in module_data {
274            let entry: &mut FxHashMap<wasmtime_environ::EntityIndex, String> =
275                export_mapping.entry(idx).or_default();
276            for (name, index) in module.module.exports.clone() {
277                entry.insert(index, name);
278            }
279        }
280
281        export_mapping
282    }
283
284    /// Fills in the abstract resource types for the given component.
285    fn generate_resources(mut inner: ComponentInner) -> Result<ComponentInner> {
286        for (_key, item) in &inner.resolve.worlds[inner.world_id].imports {
287            match item {
288                WorldItem::Type(x) => {
289                    if inner.resolve.types[*x].kind == TypeDefKind::Resource {
290                        if let Some(name) = &inner.resolve.types[*x].name {
291                            ensure!(
292                                inner
293                                    .import_types
294                                    .root
295                                    .resources
296                                    .insert(
297                                        name.as_str().into(),
298                                        ResourceType::from_resolve(
299                                            inner.type_identifiers[x.index()].clone(),
300                                            *x,
301                                            &inner,
302                                            None
303                                        )?
304                                    )
305                                    .is_none(),
306                                "Duplicate resource import."
307                            );
308                        }
309                    }
310                }
311                WorldItem::Interface(x) => {
312                    for (name, ty) in &inner.resolve.interfaces[*x].types {
313                        if inner.resolve.types[*ty].kind == TypeDefKind::Resource {
314                            let ty = ResourceType::from_resolve(
315                                inner.type_identifiers[ty.index()].clone(),
316                                *ty,
317                                &inner,
318                                None,
319                            )?;
320                            let entry = inner
321                                .import_types
322                                .instances
323                                .entry(inner.interface_identifiers[x.index()].clone())
324                                .or_insert_with(ComponentTypesInstance::new);
325                            ensure!(
326                                entry.resources.insert(name.as_str().into(), ty).is_none(),
327                                "Duplicate resource import."
328                            );
329                        }
330                    }
331                }
332                _ => {}
333            }
334        }
335
336        for (_key, item) in &inner.resolve.worlds[inner.world_id].exports {
337            match item {
338                WorldItem::Type(x) => {
339                    if inner.resolve.types[*x].kind == TypeDefKind::Resource {
340                        if let Some(name) = &inner.resolve.types[*x].name {
341                            ensure!(
342                                inner
343                                    .export_types
344                                    .root
345                                    .resources
346                                    .insert(
347                                        name.as_str().into(),
348                                        ResourceType::from_resolve(
349                                            inner.type_identifiers[x.index()].clone(),
350                                            *x,
351                                            &inner,
352                                            None
353                                        )?
354                                    )
355                                    .is_none(),
356                                "Duplicate resource export."
357                            );
358                        }
359                    }
360                }
361                WorldItem::Interface(x) => {
362                    for (name, ty) in &inner.resolve.interfaces[*x].types {
363                        if inner.resolve.types[*ty].kind == TypeDefKind::Resource {
364                            let ty = ResourceType::from_resolve(
365                                inner.type_identifiers[ty.index()].clone(),
366                                *ty,
367                                &inner,
368                                None,
369                            )?;
370                            let entry = inner
371                                .export_types
372                                .instances
373                                .entry(inner.interface_identifiers[x.index()].clone())
374                                .or_insert_with(ComponentTypesInstance::new);
375                            ensure!(
376                                entry.resources.insert(name.as_str().into(), ty).is_none(),
377                                "Duplicate resource export."
378                            );
379                        }
380                    }
381                }
382                _ => {}
383            }
384        }
385
386        Ok(inner)
387    }
388
389    /// Parses all package identifiers.
390    fn generate_package_identifiers(resolve: &Resolve) -> Result<Vec<PackageIdentifier>> {
391        let mut res = Vec::with_capacity(resolve.packages.len());
392
393        for (_, pkg) in &resolve.packages {
394            res.push(PackageIdentifier::from(&pkg.name));
395        }
396
397        Ok(res)
398    }
399
400    /// Generates a mapping from interface ID to parsed interface identifier.
401    fn generate_interface_identifiers(
402        resolve: &Resolve,
403        packages: &[PackageIdentifier],
404    ) -> Result<Vec<InterfaceIdentifier>> {
405        let mut res = Vec::with_capacity(resolve.interfaces.len());
406
407        for (_, iface) in &resolve.interfaces {
408            let pkg = iface
409                .package
410                .context("Interface did not have associated package.")?;
411            res.push(InterfaceIdentifier::new(
412                packages[pkg.index()].clone(),
413                iface
414                    .name
415                    .as_deref()
416                    .context("Exported interface did not have valid name.")?,
417            ));
418        }
419
420        Ok(res)
421    }
422
423    /// Fills in all initialization data for the component.
424    fn extract_initializers(
425        mut inner: ComponentInner,
426        types: &wasmtime_environ::component::ComponentTypes,
427    ) -> Result<ComponentInner> {
428        let lowering_options = Self::get_lowering_options_and_extract_trampolines(
429            &inner.translation.trampolines,
430            &mut inner.generated_trampolines,
431        )?;
432        let mut imports = FxHashMap::default();
433        for (key, _) in &inner.resolve.worlds[inner.world_id].imports {
434            let name = inner.resolve.name_world_key(key);
435            imports.insert(name, key.clone());
436        }
437
438        let _root_name = Arc::<str>::from("$root");
439
440        let mut destructors = FxHashMap::default();
441
442        for initializer in &inner.translation.component.initializers {
443            match initializer {
444                GlobalInitializer::InstantiateModule(InstantiateModule::Static(idx, _def)) => {
445                    inner.instance_modules.push(*idx);
446                }
447                GlobalInitializer::ExtractMemory(ExtractMemory { index, export }) => {
448                    ensure!(
449                        inner
450                            .extracted_memories
451                            .insert(*index, export.clone())
452                            .is_none(),
453                        "Extracted the same memory more than once."
454                    );
455                }
456                GlobalInitializer::ExtractRealloc(ExtractRealloc { index, def }) => {
457                    if let CoreDef::Export(export) = def {
458                        ensure!(
459                            inner
460                                .extracted_reallocs
461                                .insert(*index, export.clone())
462                                .is_none(),
463                            "Extracted the same memory more than once."
464                        );
465                    } else {
466                        bail!("Unexpected post return definition type.");
467                    }
468                }
469                GlobalInitializer::ExtractPostReturn(ExtractPostReturn { index, def }) => {
470                    if let CoreDef::Export(export) = def {
471                        ensure!(
472                            inner
473                                .extracted_post_returns
474                                .insert(*index, export.clone())
475                                .is_none(),
476                            "Extracted the same memory more than once."
477                        );
478                    } else {
479                        bail!("Unexpected post return definition type.");
480                    }
481                }
482                GlobalInitializer::LowerImport { index, import } => {
483                    let (idx, lowering_opts, index_ty) = lowering_options[*index];
484                    let (import_index, path) = &inner.translation.component.imports[*import];
485                    let (import_name, _) = &inner.translation.component.import_types[*import_index];
486                    let world_key = &imports[import_name];
487
488                    let imp = match &inner.resolve.worlds[inner.world_id].imports[world_key] {
489                        WorldItem::Function(func) => {
490                            assert_eq!(path.len(), 0);
491                            ComponentImport {
492                                instance: None,
493                                name: import_name.as_str().into(),
494                                func: func.clone(),
495                                options: lowering_opts.clone(),
496                            }
497                        }
498                        WorldItem::Interface(i) => {
499                            assert_eq!(path.len(), 1);
500                            let iface = &inner.resolve.interfaces[*i];
501                            let func = &iface.functions[&path[0]];
502
503                            ComponentImport {
504                                instance: Some(inner.interface_identifiers[i.index()].clone()),
505                                name: path[0].as_str().into(),
506                                func: func.clone(),
507                                options: lowering_opts.clone(),
508                            }
509                        }
510                        WorldItem::Type(_) => unreachable!(),
511                    };
512
513                    let ty = crate::types::FuncType::from_component(&imp.func, &inner, None)?;
514                    let inst = if let Some(inst) = &imp.instance {
515                        inner
516                            .import_types
517                            .instances
518                            .entry(inst.clone())
519                            .or_insert_with(ComponentTypesInstance::new)
520                    } else {
521                        &mut inner.import_types.root
522                    };
523
524                    Self::update_resource_map(
525                        &inner.resolve,
526                        types,
527                        &imp.func,
528                        index_ty,
529                        &mut inner.resource_map,
530                    );
531
532                    ensure!(
533                        inst.functions.insert(imp.name.clone(), ty).is_none(),
534                        "Attempted to insert duplicate import."
535                    );
536
537                    ensure!(
538                        inner
539                            .generated_trampolines
540                            .insert(idx, GeneratedTrampoline::ImportedFunction(imp))
541                            .is_none(),
542                        "Attempted to insert duplicate import."
543                    );
544                }
545                GlobalInitializer::Resource(x) => {
546                    if let Some(destructor) = x.dtor.clone() {
547                        ensure!(
548                            destructors.insert(x.index, destructor).is_none(),
549                            "Attempted to define duplicate resource."
550                        );
551                    }
552                }
553                _ => bail!("Not yet implemented {initializer:?}."),
554            }
555        }
556
557        for trampoline in inner.generated_trampolines.values_mut() {
558            if let GeneratedTrampoline::ResourceDrop(x, destructor) = trampoline {
559                let resource = &types[*x];
560                if let Some(resource_idx) = inner
561                    .translation
562                    .component
563                    .defined_resource_index(resource.ty)
564                {
565                    *destructor = destructors.remove(&resource_idx);
566                }
567            }
568        }
569
570        Ok(inner)
571    }
572
573    /// Creates a mapping from lowered functions to trampoline data,
574    /// and records any auxiliary trampolines in the map.
575    fn get_lowering_options_and_extract_trampolines<'a>(
576        trampolines: &'a wasmtime_environ::PrimaryMap<TrampolineIndex, Trampoline>,
577        output_trampolines: &mut FxHashMap<TrampolineIndex, GeneratedTrampoline>,
578    ) -> Result<
579        wasmtime_environ::PrimaryMap<
580            LoweredIndex,
581            (TrampolineIndex, &'a CanonicalOptions, TypeFuncIndex),
582        >,
583    > {
584        let mut lowers = wasmtime_environ::PrimaryMap::default();
585        for (idx, trampoline) in trampolines {
586            match trampoline {
587                Trampoline::LowerImport {
588                    index,
589                    lower_ty,
590                    options,
591                } => assert!(
592                    lowers.push((idx, options, *lower_ty)) == *index,
593                    "Indices did not match."
594                ),
595                Trampoline::ResourceNew(x) => {
596                    output_trampolines.insert(idx, GeneratedTrampoline::ResourceNew(*x));
597                }
598                Trampoline::ResourceRep(x) => {
599                    output_trampolines.insert(idx, GeneratedTrampoline::ResourceRep(*x));
600                }
601                Trampoline::ResourceDrop(x) => {
602                    output_trampolines.insert(idx, GeneratedTrampoline::ResourceDrop(*x, None));
603                }
604                _ => bail!("Trampoline not implemented."),
605            }
606        }
607        Ok(lowers)
608    }
609
610    /// Translates the given bytes into component data and a set of core modules.
611    fn translate_modules<'a>(
612        bytes: &'a [u8],
613        scope: &'a wasmtime_environ::ScopeVec<u8>,
614    ) -> Result<(
615        ComponentTranslation,
616        wasmtime_environ::PrimaryMap<StaticModuleIndex, wasmtime_environ::ModuleTranslation<'a>>,
617        wasmtime_environ::component::ComponentTypes,
618    )> {
619        let tunables = wasmtime_environ::Tunables::default_u32();
620        let mut types = ComponentTypesBuilder::default();
621        let mut validator = Self::create_component_validator();
622
623        let (translation, modules) = Translator::new(&tunables, &mut validator, &mut types, scope)
624            .translate(bytes)
625            .context("Could not translate input component to core WASM.")?;
626
627        Ok((
628            translation,
629            modules,
630            types.finish(&Default::default(), [], []).0,
631        ))
632    }
633
634    /// Fills in all of the exports for a component.
635    fn load_exports(
636        mut inner: ComponentInner,
637        types: &wasmtime_environ::component::ComponentTypes,
638    ) -> Result<ComponentInner> {
639        Self::export_names(&mut inner);
640
641        for (export_name, export) in &inner.translation.component.exports {
642            let world_key = &inner.export_names[export_name];
643            let item = &inner.resolve.worlds[inner.world_id].exports[world_key];
644            match export {
645                wasmtime_environ::component::Export::LiftedFunction { ty, func, options } => {
646                    let f = match item {
647                        WorldItem::Function(f) => f,
648                        WorldItem::Interface(_) | WorldItem::Type(_) => unreachable!(),
649                    };
650
651                    Self::update_resource_map(
652                        &inner.resolve,
653                        types,
654                        f,
655                        *ty,
656                        &mut inner.resource_map,
657                    );
658
659                    let export_name = Arc::<str>::from(export_name.as_str());
660                    let ty = crate::types::FuncType::from_component(f, &inner, None)?;
661
662                    ensure!(
663                        inner
664                            .export_types
665                            .root
666                            .functions
667                            .insert(export_name.clone(), ty.clone())
668                            .is_none(),
669                        "Duplicate function definition."
670                    );
671
672                    ensure!(
673                        inner
674                            .export_info
675                            .root
676                            .functions
677                            .insert(
678                                export_name,
679                                ComponentExport {
680                                    options: options.clone(),
681                                    def: match func {
682                                        CoreDef::Export(x) => x.clone(),
683                                        _ => unreachable!(),
684                                    },
685                                    func: f.clone(),
686                                    ty
687                                }
688                            )
689                            .is_none(),
690                        "Duplicate function definition."
691                    );
692                }
693                wasmtime_environ::component::Export::Instance { exports, .. } => {
694                    let id = match item {
695                        WorldItem::Interface(id) => *id,
696                        WorldItem::Function(_) | WorldItem::Type(_) => unreachable!(),
697                    };
698                    for (func_name, export) in exports {
699                        let (func, options, ty) = match export {
700                            wasmtime_environ::component::Export::LiftedFunction {
701                                func,
702                                options,
703                                ty,
704                            } => (func, options, ty),
705                            wasmtime_environ::component::Export::Type(_) => continue, // ignored
706                            _ => unreachable!(),
707                        };
708
709                        let f = &inner.resolve.interfaces[id].functions[func_name];
710
711                        Self::update_resource_map(
712                            &inner.resolve,
713                            types,
714                            f,
715                            *ty,
716                            &mut inner.resource_map,
717                        );
718                        let exp = ComponentExport {
719                            options: options.clone(),
720                            def: match func {
721                                CoreDef::Export(x) => x.clone(),
722                                _ => unreachable!(),
723                            },
724                            func: f.clone(),
725                            ty: crate::types::FuncType::from_component(f, &inner, None)?,
726                        };
727                        let func_name = Arc::<str>::from(func_name.as_str());
728                        ensure!(
729                            inner
730                                .export_types
731                                .instances
732                                .entry(inner.interface_identifiers[id.index()].clone())
733                                .or_insert_with(ComponentTypesInstance::new)
734                                .functions
735                                .insert(func_name.clone(), exp.ty.clone())
736                                .is_none(),
737                            "Duplicate function definition."
738                        );
739                        ensure!(
740                            inner
741                                .export_info
742                                .instances
743                                .entry(inner.interface_identifiers[id.index()].clone())
744                                .or_default()
745                                .functions
746                                .insert(func_name, exp)
747                                .is_none(),
748                            "Duplicate function definition."
749                        );
750                    }
751                }
752
753                // ignore type exports for now
754                wasmtime_environ::component::Export::Type(_) => {}
755
756                // This can't be tested at this time so leave it unimplemented
757                wasmtime_environ::component::Export::ModuleStatic(_) => {
758                    bail!("Not yet implemented.")
759                }
760                wasmtime_environ::component::Export::ModuleImport { .. } => {
761                    bail!("Not yet implemented.")
762                }
763            }
764        }
765
766        Ok(inner)
767    }
768
769    /// Fills in the mapping of export names to the exports' respective worlds.
770    fn export_names(inner: &mut ComponentInner) {
771        let to_iter = &inner.resolve.worlds[inner.world_id].exports;
772        let mut exports = FxHashMap::with_capacity_and_hasher(to_iter.len(), Default::default());
773        for (key, _) in to_iter {
774            let name = inner.resolve.name_world_key(key);
775            exports.insert(name, key.clone());
776        }
777        inner.export_names = exports;
778    }
779
780    /// Updates the mapping from type IDs to table indices based upon the resources
781    /// referenced by the provided function.
782    fn update_resource_map(
783        resolve: &Resolve,
784        types: &wasmtime_environ::component::ComponentTypes,
785        func: &Function,
786        ty_func_idx: TypeFuncIndex,
787        map: &mut Vec<TypeResourceTableIndex>,
788    ) {
789        let params_ty = &types[types[ty_func_idx].params];
790        for ((_, ty), iface_ty) in func.params.iter().zip(params_ty.types.iter()) {
791            Self::connect_resources(resolve, types, ty, iface_ty, map);
792        }
793        let results_ty = &types[types[ty_func_idx].results];
794        for (ty, iface_ty) in func.results.iter_types().zip(results_ty.types.iter()) {
795            Self::connect_resources(resolve, types, ty, iface_ty, map);
796        }
797    }
798
799    /// Inspects the given type (and any referenced subtypes) for resources,
800    /// and records the table indices of those resources in the map.
801    fn connect_resources(
802        resolve: &Resolve,
803        types: &wasmtime_environ::component::ComponentTypes,
804        ty: &Type,
805        iface_ty: &InterfaceType,
806        map: &mut Vec<TypeResourceTableIndex>,
807    ) {
808        let Type::Id(id) = ty else { return };
809        match (&resolve.types[*id].kind, iface_ty) {
810            (TypeDefKind::Flags(_), InterfaceType::Flags(_))
811            | (TypeDefKind::Enum(_), InterfaceType::Enum(_)) => {}
812            (TypeDefKind::Record(t1), InterfaceType::Record(t2)) => {
813                let t2 = &types[*t2];
814                for (f1, f2) in t1.fields.iter().zip(t2.fields.iter()) {
815                    Self::connect_resources(resolve, types, &f1.ty, &f2.ty, map);
816                }
817            }
818            (
819                TypeDefKind::Handle(Handle::Own(t1) | Handle::Borrow(t1)),
820                InterfaceType::Own(t2) | InterfaceType::Borrow(t2),
821            ) => {
822                map[t1.index()] = *t2;
823            }
824            (TypeDefKind::Tuple(t1), InterfaceType::Tuple(t2)) => {
825                let t2 = &types[*t2];
826                for (f1, f2) in t1.types.iter().zip(t2.types.iter()) {
827                    Self::connect_resources(resolve, types, f1, f2, map);
828                }
829            }
830            (TypeDefKind::Variant(t1), InterfaceType::Variant(t2)) => {
831                let t2 = &types[*t2];
832                for (f1, f2) in t1.cases.iter().zip(t2.cases.iter()) {
833                    if let Some(t1) = &f1.ty {
834                        Self::connect_resources(resolve, types, t1, f2.ty.as_ref().unwrap(), map);
835                    }
836                }
837            }
838            (TypeDefKind::Option(t1), InterfaceType::Option(t2)) => {
839                let t2 = &types[*t2];
840                Self::connect_resources(resolve, types, t1, &t2.ty, map);
841            }
842            (TypeDefKind::Result(t1), InterfaceType::Result(t2)) => {
843                let t2 = &types[*t2];
844                if let Some(t1) = &t1.ok {
845                    Self::connect_resources(resolve, types, t1, &t2.ok.unwrap(), map);
846                }
847                if let Some(t1) = &t1.err {
848                    Self::connect_resources(resolve, types, t1, &t2.err.unwrap(), map);
849                }
850            }
851            (TypeDefKind::List(t1), InterfaceType::List(t2)) => {
852                let t2 = &types[*t2];
853                Self::connect_resources(resolve, types, t1, &t2.element, map);
854            }
855            (TypeDefKind::Type(ty), _) => {
856                Self::connect_resources(resolve, types, ty, iface_ty, map);
857            }
858            (_, _) => unreachable!(),
859        }
860    }
861
862    /// Creates a validator with the appropriate settings for component model resolution.
863    fn create_component_validator() -> wasmtime_environ::wasmparser::Validator {
864        wasmtime_environ::wasmparser::Validator::new_with_features(
865            wasmtime_environ::wasmparser::WasmFeatures::all(),
866        )
867    }
868}
869
870/// Holds the inner, immutable state of an instantiated component.
871struct ComponentInner {
872    /// Maps from module indices to export indices for linking.
873    pub export_mapping:
874        FxHashMap<StaticModuleIndex, FxHashMap<wasmtime_environ::EntityIndex, String>>,
875    /// Maps between export names and world keys.
876    pub export_names: FxHashMap<String, WorldKey>,
877    /// The exports of the component.
878    pub export_types: ComponentTypes,
879    /// Holds internal information for linking exports.
880    pub export_info: ExportTypes,
881    /// The memories that this component instantiates and references.
882    pub extracted_memories: FxHashMap<RuntimeMemoryIndex, CoreExport<MemoryIndex>>,
883    /// The reallocation functions that this component instantiates and references.
884    pub extracted_reallocs:
885        FxHashMap<RuntimeReallocIndex, CoreExport<wasmtime_environ::EntityIndex>>,
886    /// The post-return functions that this component instantiates and references.
887    pub extracted_post_returns:
888        FxHashMap<RuntimePostReturnIndex, CoreExport<wasmtime_environ::EntityIndex>>,
889    /// A mapping from type indices to resource table indices.
890    pub resource_map: Vec<TypeResourceTableIndex>,
891    /// The set of trampolines required to use this resource.
892    pub generated_trampolines: FxHashMap<TrampolineIndex, GeneratedTrampoline>,
893    /// The component's globally-unique ID.
894    pub id: u64,
895    /// The imports of the component.
896    pub import_types: ComponentTypes,
897    /// A mapping from runtime module indices to static indices.
898    pub instance_modules: wasmtime_environ::PrimaryMap<RuntimeInstanceIndex, StaticModuleIndex>,
899    /// A mapping from interface ID to parsed identifier.
900    pub interface_identifiers: Vec<InterfaceIdentifier>,
901    /// A mapping from type ID to parsed identifier.
902    pub type_identifiers: Vec<Option<TypeIdentifier>>,
903    /// The translated modules of this component.
904    pub modules: FxHashMap<StaticModuleIndex, ModuleTranslation>,
905    /// The resolved WIT of the component.
906    pub resolve: Resolve,
907    /// The size and alignment of component types.
908    pub size_align: SizeAlign,
909    /// The translated component data.
910    pub translation: ComponentTranslation,
911    /// The ID of the primary exported world.
912    pub world_id: Id<World>,
913    /// The package identifier for the component.
914    pub package: PackageIdentifier,
915}
916
917impl std::fmt::Debug for ComponentInner {
918    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
919        f.debug_struct("ComponentInner").finish()
920    }
921}
922
923/// A translated module.
924struct ModuleTranslation {
925    /// The instantiated module that was translated.
926    pub module: Module,
927    /// The translation data for the module.
928    pub translation: wasmtime_environ::Module,
929}
930
931/// Details the set of types and functions exported by a component.
932#[derive(Debug, Default)]
933struct ExportTypes {
934    /// The root instance for component exports.
935    root: ExportTypesInstance,
936    /// The interfaces exported by the component.
937    instances: FxHashMap<InterfaceIdentifier, ExportTypesInstance>,
938}
939
940/// Represents an interface that has been exported by a component.
941#[derive(Debug, Default)]
942struct ExportTypesInstance {
943    /// The functions in the interface.
944    functions: FxHashMap<Arc<str>, ComponentExport>,
945}
946
947/// Details a set of types within a component.
948#[derive(Debug)]
949pub struct ComponentTypes {
950    /// The package root of the component.
951    root: ComponentTypesInstance,
952    /// All instances owned by the component.
953    instances: FxHashMap<InterfaceIdentifier, ComponentTypesInstance>,
954}
955
956impl ComponentTypes {
957    /// Creates a new, initially empty component type set.
958    pub(crate) fn new() -> Self {
959        Self {
960            root: ComponentTypesInstance::new(),
961            instances: FxHashMap::default(),
962        }
963    }
964
965    /// Gets the root instance.
966    pub fn root(&self) -> &ComponentTypesInstance {
967        &self.root
968    }
969
970    /// Gets the instance with the specified name, if any.
971    pub fn instance(&self, name: &InterfaceIdentifier) -> Option<&ComponentTypesInstance> {
972        self.instances.get(name)
973    }
974
975    /// Gets an iterator over all instances by identifier.
976    pub fn instances(
977        &self,
978    ) -> impl Iterator<Item = (&'_ InterfaceIdentifier, &'_ ComponentTypesInstance)> {
979        self.instances.iter()
980    }
981}
982
983/// Represents a specific interface from a component.
984#[derive(Debug)]
985pub struct ComponentTypesInstance {
986    /// The functions of the interface.
987    functions: FxHashMap<Arc<str>, crate::types::FuncType>,
988    /// The resources of the interface.
989    resources: FxHashMap<Arc<str>, ResourceType>,
990}
991
992impl ComponentTypesInstance {
993    /// Creates a new, empty instance.
994    pub(crate) fn new() -> Self {
995        Self {
996            functions: FxHashMap::default(),
997            resources: FxHashMap::default(),
998        }
999    }
1000
1001    /// Gets the associated function by name, if any.
1002    pub fn func(&self, name: impl AsRef<str>) -> Option<crate::types::FuncType> {
1003        self.functions.get(name.as_ref()).cloned()
1004    }
1005
1006    /// Iterates over all associated functions by name.
1007    pub fn funcs(&self) -> impl Iterator<Item = (&'_ str, crate::types::FuncType)> {
1008        self.functions.iter().map(|(k, v)| (&**k, v.clone()))
1009    }
1010
1011    /// Gets the associated abstract resource by name, if any.
1012    pub fn resource(&self, name: impl AsRef<str>) -> Option<ResourceType> {
1013        self.resources.get(name.as_ref()).cloned()
1014    }
1015
1016    /// Iterates over all associated functions by name.
1017    pub fn resources(&self) -> impl Iterator<Item = (&'_ str, crate::types::ResourceType)> {
1018        self.resources.iter().map(|(k, v)| (&**k, v.clone()))
1019    }
1020}
1021
1022/// Provides the ability to define imports for a component and create [`Instance`]s of it.
1023#[derive(Clone, Debug, Default)]
1024pub struct Linker {
1025    /// The root instance used for linking.
1026    root: LinkerInstance,
1027    /// The set of interfaces against which to link.
1028    instances: FxHashMap<InterfaceIdentifier, LinkerInstance>,
1029}
1030
1031impl Linker {
1032    /// Immutably obtains the root interface for this linker.
1033    pub fn root(&self) -> &LinkerInstance {
1034        &self.root
1035    }
1036
1037    /// Mutably obtains the root interface for this linker.
1038    pub fn root_mut(&mut self) -> &mut LinkerInstance {
1039        &mut self.root
1040    }
1041
1042    /// Creates a new instance in the linker with the provided name. Returns an
1043    /// error if an instance with that name already exists.
1044    pub fn define_instance(&mut self, name: InterfaceIdentifier) -> Result<&mut LinkerInstance> {
1045        if self.instance(&name).is_none() {
1046            Ok(self.instances.entry(name).or_default())
1047        } else {
1048            bail!("Duplicate instance definition.");
1049        }
1050    }
1051
1052    /// Immutably obtains the instance with the given name, if any.
1053    pub fn instance(&self, name: &InterfaceIdentifier) -> Option<&LinkerInstance> {
1054        self.instances.get(name)
1055    }
1056
1057    /// Mutably obtains the instance with the given name, if any.
1058    pub fn instance_mut(&mut self, name: &InterfaceIdentifier) -> Option<&mut LinkerInstance> {
1059        self.instances.get_mut(name)
1060    }
1061
1062    /// Gets an immutable iterator over all instances defined in this linker.
1063    pub fn instances(
1064        &self,
1065    ) -> impl ExactSizeIterator<Item = (&'_ InterfaceIdentifier, &'_ LinkerInstance)> {
1066        self.instances.iter()
1067    }
1068
1069    /// Gets a mutable iterator over all instances defined in this linker.
1070    pub fn instances_mut(
1071        &mut self,
1072    ) -> impl ExactSizeIterator<Item = (&'_ InterfaceIdentifier, &'_ mut LinkerInstance)> {
1073        self.instances.iter_mut()
1074    }
1075
1076    /// Instantiates a component for the provided store, filling in its imports with externals
1077    /// defined in this linker. All imports must be defined for instantiation to succeed.
1078    pub fn instantiate(&self, ctx: impl AsContextMut, component: &Component) -> Result<Instance> {
1079        Instance::new(ctx, component, self)
1080    }
1081}
1082
1083/// Describes a concrete interface which components may import.
1084#[derive(Clone, Debug, Default)]
1085pub struct LinkerInstance {
1086    /// The functions in the interface.
1087    functions: FxHashMap<Arc<str>, crate::func::Func>,
1088    /// The resource types in the interface.
1089    resources: FxHashMap<Arc<str>, ResourceType>,
1090}
1091
1092impl LinkerInstance {
1093    /// Defines a new function for this interface with the provided name.
1094    /// Fails if the function already exists.
1095    pub fn define_func(
1096        &mut self,
1097        name: impl Into<Arc<str>>,
1098        func: crate::func::Func,
1099    ) -> Result<()> {
1100        let n = Into::<Arc<str>>::into(name);
1101        if self.functions.contains_key(&n) {
1102            bail!("Duplicate function definition.");
1103        }
1104
1105        self.functions.insert(n, func);
1106        Ok(())
1107    }
1108
1109    /// Gets the function in this interface with the given name, if any.
1110    pub fn func(&self, name: impl AsRef<str>) -> Option<crate::func::Func> {
1111        self.functions.get(name.as_ref()).cloned()
1112    }
1113
1114    /// Defines a new resource type for this interface with the provided name.
1115    /// Fails if the resource type already exists, or if the resource is abstract.
1116    pub fn define_resource(
1117        &mut self,
1118        name: impl Into<Arc<str>>,
1119        resource_ty: ResourceType,
1120    ) -> Result<()> {
1121        ensure!(
1122            resource_ty.is_instantiated(),
1123            "Cannot link with abstract resource type."
1124        );
1125
1126        let n = Into::<Arc<str>>::into(name);
1127        if self.resources.contains_key(&n) {
1128            bail!("Duplicate resource definition.");
1129        }
1130
1131        self.resources.insert(n, resource_ty);
1132        Ok(())
1133    }
1134
1135    /// Gets the resource in this interface with the given name, if any.
1136    pub fn resource(&self, name: impl AsRef<str>) -> Option<ResourceType> {
1137        self.resources.get(name.as_ref()).cloned()
1138    }
1139
1140    /// Iterates over all associated functions by name.
1141    pub fn funcs(&self) -> impl Iterator<Item = (&'_ str, crate::func::Func)> {
1142        self.functions.iter().map(|(k, v)| (&**k, v.clone()))
1143    }
1144
1145    /// Iterates over all associated functions by name.
1146    pub fn resources(&self) -> impl Iterator<Item = (&'_ str, ResourceType)> {
1147        self.resources.iter().map(|(k, v)| (&**k, v.clone()))
1148    }
1149}
1150
1151/// An instantiated WebAssembly component.
1152#[derive(Clone, Debug)]
1153pub struct Instance(Arc<InstanceInner>);
1154
1155impl Instance {
1156    /// Creates a new instance for the given component with the specified linker.
1157    pub(crate) fn new(
1158        mut ctx: impl AsContextMut,
1159        component: &Component,
1160        linker: &Linker,
1161    ) -> Result<Self> {
1162        /// A counter that uniquely identifies instances.
1163        static ID_COUNTER: AtomicU64 = AtomicU64::new(0);
1164
1165        let mut instance_flags = wasmtime_environ::PrimaryMap::default();
1166        for _i in 0..component.0.instance_modules.len() {
1167            instance_flags.push(Global::new(
1168                ctx.as_context_mut().inner,
1169                wasm_runtime_layer::Value::I32(
1170                    wasmtime_environ::component::FLAG_MAY_LEAVE
1171                        | wasmtime_environ::component::FLAG_MAY_ENTER,
1172                ),
1173                true,
1174            ));
1175        }
1176
1177        let id = ID_COUNTER.fetch_add(1, Ordering::AcqRel);
1178        let map = Self::create_resource_instantiation_map(id, component, linker)?;
1179        let types = Self::generate_types(component, &map)?;
1180        let resource_tables = Mutex::new(vec![
1181            HandleTable::default();
1182            component.0.translation.component.num_resource_tables
1183        ]);
1184
1185        let instance = InstanceInner {
1186            component: component.clone(),
1187            exports: Exports::new(),
1188            id,
1189            instances: Default::default(),
1190            instance_flags,
1191            state_table: Arc::new(StateTable {
1192                dropped: AtomicBool::new(false),
1193                resource_tables,
1194            }),
1195            types,
1196            store_id: ctx.as_context().inner.data().id,
1197        };
1198        let initialized = Self::global_initialize(instance, &mut ctx, linker, &map)?;
1199        let exported = Self::load_exports(initialized, &ctx, &map)?;
1200
1201        Ok(Self(Arc::new_cyclic(|w| {
1202            Self::fill_exports(exported, w.clone())
1203        })))
1204    }
1205
1206    /// Gets the component associated with this instance.
1207    pub fn component(&self) -> &Component {
1208        &self.0.component
1209    }
1210
1211    /// Gets the exports of this instance.
1212    pub fn exports(&self) -> &Exports {
1213        &self.0.exports
1214    }
1215
1216    /// Drops the instance and all of its owned resources, removing its data from the given store.
1217    /// Returns the list of errors that occurred while dropping owned resources, but continues
1218    /// until all resources have been dropped.
1219    pub fn drop<T, E: backend::WasmEngine>(&self, ctx: &mut Store<T, E>) -> Result<Vec<Error>> {
1220        ensure!(self.0.store_id == ctx.inner.data().id, "Incorrect store.");
1221        self.0.state_table.dropped.store(true, Ordering::Release);
1222
1223        let mut errors = Vec::new();
1224
1225        let mut tables = self
1226            .0
1227            .state_table
1228            .resource_tables
1229            .try_lock()
1230            .expect("Could not lock resource tables.");
1231        for table in &mut *tables {
1232            if let Some(destructor) = table.destructor.as_ref() {
1233                for (_, val) in table.array.iter() {
1234                    if let Err(x) = destructor.call(
1235                        &mut ctx.inner,
1236                        &[wasm_runtime_layer::Value::I32(val.rep)],
1237                        &mut [],
1238                    ) {
1239                        errors.push(x);
1240                    }
1241                }
1242            }
1243        }
1244
1245        Ok(errors)
1246    }
1247
1248    /// Fills the export tables with pointers to the final instance.
1249    fn fill_exports(mut inner: InstanceInner, final_ptr: Weak<InstanceInner>) -> InstanceInner {
1250        for inst in inner.exports.instances.values_mut() {
1251            inst.instance = final_ptr.clone();
1252        }
1253
1254        inner.exports.root.instance = final_ptr;
1255        inner
1256    }
1257
1258    /// Generates the concrete list of types for this instance, after replacing abstract resources with instantiated ones.
1259    fn generate_types(
1260        component: &Component,
1261        map: &FxHashMap<ResourceType, ResourceType>,
1262    ) -> Result<Arc<[crate::types::ValueType]>> {
1263        let mut types = Vec::with_capacity(component.0.resolve.types.len());
1264        for (mut id, mut val) in &component.0.resolve.types {
1265            assert!(
1266                types.len() == id.index(),
1267                "Type definition IDs were not equal."
1268            );
1269
1270            while let TypeDefKind::Type(Type::Id(id_ref)) = val.kind {
1271                id = id_ref;
1272                val = &component.0.resolve.types[id_ref];
1273            }
1274
1275            if val.kind == TypeDefKind::Resource {
1276                types.push(crate::types::ValueType::Bool);
1277            } else {
1278                types.push(crate::types::ValueType::from_component_typedef(
1279                    id,
1280                    &component.0,
1281                    Some(map),
1282                )?);
1283            }
1284        }
1285        Ok(types.into())
1286    }
1287
1288    /// Creates a mapping from component resources to instance resources,
1289    /// since resource types are unique per instantiation.
1290    fn create_resource_instantiation_map(
1291        instance_id: u64,
1292        component: &Component,
1293        linker: &Linker,
1294    ) -> Result<FxHashMap<ResourceType, ResourceType>> {
1295        let mut types = FxHashMap::default();
1296
1297        for (name, resource) in component.imports().root().resources() {
1298            let instantiated = linker
1299                .root()
1300                .resource(name)
1301                .ok_or_else(|| Error::msg(format!("Could not find resource {name} in linker.")))?;
1302            types.insert(resource, instantiated);
1303        }
1304
1305        for (id, interface) in component.imports().instances() {
1306            for (name, resource) in interface.resources() {
1307                let instantiated = linker
1308                    .instance(id)
1309                    .and_then(|x| x.resource(name))
1310                    .ok_or_else(|| {
1311                        Error::msg(format!(
1312                            "Could not find resource {name} from interface {id:?} in linker."
1313                        ))
1314                    })?;
1315                types.insert(resource, instantiated);
1316            }
1317        }
1318
1319        for (_, resource) in component
1320            .exports()
1321            .instances()
1322            .flat_map(|(_, x)| x.resources())
1323            .chain(component.exports().root().resources())
1324        {
1325            let instantiated = resource.instantiate(instance_id)?;
1326            types.insert(resource, instantiated);
1327        }
1328
1329        Ok(types)
1330    }
1331
1332    /// Fills in the exports map for the instance.
1333    fn load_exports(
1334        mut inner: InstanceInner,
1335        ctx: impl AsContext,
1336        map: &FxHashMap<ResourceType, ResourceType>,
1337    ) -> Result<InstanceInner> {
1338        for (name, func) in &inner.component.0.export_info.root.functions {
1339            inner.exports.root.functions.insert(
1340                name.clone(),
1341                Self::export_function(
1342                    &inner,
1343                    &ctx,
1344                    &func.def,
1345                    &func.options,
1346                    &func.func,
1347                    map,
1348                    None,
1349                )?,
1350            );
1351        }
1352        for (name, res) in &inner.component.0.export_types.root.resources {
1353            inner
1354                .exports
1355                .root
1356                .resources
1357                .insert(name.clone(), res.instantiate(inner.id)?);
1358        }
1359
1360        let mut generated_functions = Vec::new();
1361        for (inst_name, inst) in &inner.component.0.export_info.instances {
1362            for (name, func) in &inst.functions {
1363                let export = Self::export_function(
1364                    &inner,
1365                    &ctx,
1366                    &func.def,
1367                    &func.options,
1368                    &func.func,
1369                    map,
1370                    Some(inst_name.clone()),
1371                )?;
1372                generated_functions.push((inst_name.clone(), name.clone(), export));
1373            }
1374        }
1375
1376        for (inst_name, inst) in &inner.component.0.export_types.instances {
1377            for (name, res) in &inst.resources {
1378                inner
1379                    .exports
1380                    .instances
1381                    .entry(inst_name.clone())
1382                    .or_insert_with(ExportInstance::new)
1383                    .resources
1384                    .insert(name.clone(), res.instantiate(inner.id)?);
1385            }
1386        }
1387
1388        for (inst_name, name, func) in generated_functions {
1389            let interface = inner
1390                .exports
1391                .instances
1392                .entry(inst_name)
1393                .or_insert_with(ExportInstance::new);
1394            interface.functions.insert(name, func);
1395        }
1396
1397        Ok(inner)
1398    }
1399
1400    /// Creates the options used to invoke an imported function.
1401    fn import_function(
1402        inner: &InstanceInner,
1403        ctx: impl AsContext,
1404        options: &CanonicalOptions,
1405        func: &Function,
1406    ) -> GuestInvokeOptions {
1407        let memory = options.memory.map(|idx| {
1408            Self::core_export(inner, &ctx, &inner.component.0.extracted_memories[&idx])
1409                .expect("Could not get runtime memory export.")
1410                .into_memory()
1411                .expect("Export was not of memory type.")
1412        });
1413        let realloc = options.realloc.map(|idx| {
1414            Self::core_export(inner, &ctx, &inner.component.0.extracted_reallocs[&idx])
1415                .expect("Could not get runtime realloc export.")
1416                .into_func()
1417                .expect("Export was not of func type.")
1418        });
1419        let post_return = options.post_return.map(|idx| {
1420            Self::core_export(inner, &ctx, &inner.component.0.extracted_post_returns[&idx])
1421                .expect("Could not get runtime post return export.")
1422                .into_func()
1423                .expect("Export was not of func type.")
1424        });
1425
1426        GuestInvokeOptions {
1427            component: inner.component.0.clone(),
1428            encoding: options.string_encoding,
1429            function: func.clone(),
1430            memory,
1431            realloc,
1432            state_table: inner.state_table.clone(),
1433            post_return,
1434            types: inner.types.clone(),
1435            instance_id: inner.id,
1436            store_id: ctx.as_context().inner.data().id,
1437        }
1438    }
1439
1440    /// Creates an exported function from the provided definitions.
1441    fn export_function(
1442        inner: &InstanceInner,
1443        ctx: impl AsContext,
1444        def: &CoreExport<wasmtime_environ::EntityIndex>,
1445        options: &CanonicalOptions,
1446        func: &Function,
1447        mapping: &FxHashMap<ResourceType, ResourceType>,
1448        interface_id: Option<InterfaceIdentifier>,
1449    ) -> Result<crate::func::Func> {
1450        let callee = Self::core_export(inner, &ctx, def)
1451            .expect("Could not get callee export.")
1452            .into_func()
1453            .expect("Export was not of func type.");
1454        let memory = options.memory.map(|idx| {
1455            Self::core_export(inner, &ctx, &inner.component.0.extracted_memories[&idx])
1456                .expect("Could not get runtime memory export.")
1457                .into_memory()
1458                .expect("Export was not of memory type.")
1459        });
1460        let realloc = options.realloc.map(|idx| {
1461            Self::core_export(inner, &ctx, &inner.component.0.extracted_reallocs[&idx])
1462                .expect("Could not get runtime realloc export.")
1463                .into_func()
1464                .expect("Export was not of func type.")
1465        });
1466        let post_return = options.post_return.map(|idx| {
1467            Self::core_export(inner, &ctx, &inner.component.0.extracted_post_returns[&idx])
1468                .expect("Could not get runtime post return export.")
1469                .into_func()
1470                .expect("Export was not of func type.")
1471        });
1472
1473        Ok(crate::func::Func {
1474            store_id: ctx.as_context().inner.data().id,
1475            ty: crate::types::FuncType::from_component(func, &inner.component.0, Some(mapping))?,
1476            backing: FuncImpl::GuestFunc(
1477                None,
1478                Arc::new(GuestFunc {
1479                    callee,
1480                    component: inner.component.0.clone(),
1481                    encoding: options.string_encoding,
1482                    function: func.clone(),
1483                    memory,
1484                    realloc,
1485                    state_table: inner.state_table.clone(),
1486                    post_return,
1487                    types: inner.types.clone(),
1488                    instance_id: inner.id,
1489                    interface_id,
1490                }),
1491            ),
1492        })
1493    }
1494
1495    /// Gets the core WASM import associated with the provided definition.
1496    fn core_import(
1497        inner: &InstanceInner,
1498        mut ctx: impl AsContextMut,
1499        def: &CoreDef,
1500        linker: &Linker,
1501        ty: ExternType,
1502        destructors: &mut Vec<TrampolineIndex>,
1503        resource_map: &FxHashMap<ResourceType, ResourceType>,
1504    ) -> Result<Extern> {
1505        match def {
1506            CoreDef::Export(x) => {
1507                Self::core_export(inner, ctx, x).context("Could not find exported function.")
1508            }
1509            CoreDef::Trampoline(x) => {
1510                let ty = if let ExternType::Func(x) = ty {
1511                    x
1512                } else {
1513                    bail!("Incorrect extern type.")
1514                };
1515                match inner
1516                    .component
1517                    .0
1518                    .generated_trampolines
1519                    .get(x)
1520                    .context("Could not find exported trampoline.")?
1521                {
1522                    GeneratedTrampoline::ImportedFunction(component_import) => {
1523                        let expected = crate::types::FuncType::from_component(
1524                            &component_import.func,
1525                            &inner.component.0,
1526                            Some(resource_map),
1527                        )?;
1528                        let func = Self::get_component_import(component_import, linker)?;
1529                        ensure!(
1530                            func.ty() == expected,
1531                            "Function import {} had type {}, but expected {expected}",
1532                            component_import.name,
1533                            func.ty()
1534                        );
1535                        let guest_options = Self::import_function(
1536                            inner,
1537                            &ctx,
1538                            &component_import.options,
1539                            &component_import.func,
1540                        );
1541
1542                        // Improve the name
1543                        // Due to indirect calls in wasm this function has the name `"0"`, `"1"`, etc, which is only their index in the indirect call table across modules
1544                        let ty = ty.with_name(component_import.name.clone());
1545
1546                        Ok(Extern::Func(wasm_runtime_layer::Func::new(
1547                            ctx.as_context_mut().inner,
1548                            ty,
1549                            move |ctx, args, results| {
1550                                let ctx = StoreContextMut { inner: ctx };
1551                                func.call_from_guest(ctx, &guest_options, args, results)
1552                            },
1553                        )))
1554                    }
1555                    GeneratedTrampoline::ResourceNew(x) => {
1556                        let x = x.as_u32();
1557                        let tables = inner.state_table.clone();
1558                        let ty = ty.with_name(format!("resource-new-{}", x));
1559                        Ok(Extern::Func(wasm_runtime_layer::Func::new(
1560                            ctx.as_context_mut().inner,
1561                            ty,
1562                            move |_ctx, args, results| {
1563                                let rep =
1564                                    require_matches!(args[0], wasm_runtime_layer::Value::I32(x), x);
1565                                let mut table_array = tables
1566                                    .resource_tables
1567                                    .try_lock()
1568                                    .expect("Could not get mutual reference to table.");
1569                                results[0] = wasm_runtime_layer::Value::I32(
1570                                    table_array[x as usize].add(HandleElement {
1571                                        rep,
1572                                        own: true,
1573                                        lend_count: 0,
1574                                    }),
1575                                );
1576                                Ok(())
1577                            },
1578                        )))
1579                    }
1580                    GeneratedTrampoline::ResourceRep(x) => {
1581                        let x = x.as_u32();
1582                        let tables = inner.state_table.clone();
1583                        let ty = ty.with_name(format!("resource-rep-{}", x));
1584                        Ok(Extern::Func(wasm_runtime_layer::Func::new(
1585                            ctx.as_context_mut().inner,
1586                            ty,
1587                            move |_ctx, args, results| {
1588                                let idx =
1589                                    require_matches!(args[0], wasm_runtime_layer::Value::I32(x), x);
1590                                let table_array = tables
1591                                    .resource_tables
1592                                    .try_lock()
1593                                    .expect("Could not get mutual reference to table.");
1594                                results[0] = wasm_runtime_layer::Value::I32(
1595                                    table_array[x as usize].get(idx)?.rep,
1596                                );
1597                                Ok(())
1598                            },
1599                        )))
1600                    }
1601                    GeneratedTrampoline::ResourceDrop(y, _) => {
1602                        destructors.push(*x);
1603                        let x = y.as_u32();
1604                        let tables = inner.state_table.clone();
1605                        let ty = ty.with_name(format!("resource-drop-{}", x));
1606                        Ok(Extern::Func(wasm_runtime_layer::Func::new(
1607                            ctx.as_context_mut().inner,
1608                            ty,
1609                            move |ctx, args, _results| {
1610                                let idx =
1611                                    require_matches!(args[0], wasm_runtime_layer::Value::I32(x), x);
1612                                let mut table_array = tables
1613                                    .resource_tables
1614                                    .try_lock()
1615                                    .expect("Could not get mutual reference to table.");
1616                                let current_table = &mut table_array[x as usize];
1617
1618                                let elem_borrow = current_table.get(idx)?;
1619
1620                                if elem_borrow.own {
1621                                    ensure!(
1622                                        elem_borrow.lend_count == 0,
1623                                        "Attempted to drop loaned resource."
1624                                    );
1625                                    let elem = current_table.remove(idx)?;
1626                                    if let Some(destructor) =
1627                                        table_array[x as usize].destructor().cloned()
1628                                    {
1629                                        drop(table_array);
1630                                        destructor.call(
1631                                            ctx,
1632                                            &[wasm_runtime_layer::Value::I32(elem.rep)],
1633                                            &mut [],
1634                                        )?;
1635                                    }
1636                                }
1637                                Ok(())
1638                            },
1639                        )))
1640                    }
1641                }
1642            }
1643            CoreDef::InstanceFlags(i) => Ok(Extern::Global(inner.instance_flags[*i].clone())),
1644        }
1645    }
1646
1647    /// Gets the core WASM export associated with the provided definition.
1648    fn core_export<T: Copy + Into<wasmtime_environ::EntityIndex>>(
1649        inner: &InstanceInner,
1650        ctx: impl AsContext,
1651        export: &CoreExport<T>,
1652    ) -> Option<Extern> {
1653        let name = match &export.item {
1654            ExportItem::Index(idx) => {
1655                &inner.component.0.export_mapping
1656                    [&inner.component.0.instance_modules[export.instance]][&(*idx).into()]
1657            }
1658            ExportItem::Name(s) => s,
1659        };
1660
1661        inner.instances[export.instance].get_export(&ctx.as_context().inner, name)
1662    }
1663
1664    /// Handles all global initializers and instantiates the set of WASM modules for this component.
1665    fn global_initialize(
1666        mut inner: InstanceInner,
1667        mut ctx: impl AsContextMut,
1668        linker: &Linker,
1669        resource_map: &FxHashMap<ResourceType, ResourceType>,
1670    ) -> Result<InstanceInner> {
1671        let mut destructors = Vec::new();
1672        for initializer in &inner.component.0.translation.component.initializers {
1673            match initializer {
1674                GlobalInitializer::InstantiateModule(InstantiateModule::Static(idx, def)) => {
1675                    let module = &inner.component.0.modules[idx];
1676                    let imports = Self::generate_imports(
1677                        &inner,
1678                        &mut ctx,
1679                        linker,
1680                        module,
1681                        def,
1682                        &mut destructors,
1683                        resource_map,
1684                    )?;
1685                    let instance = wasm_runtime_layer::Instance::new(
1686                        &mut ctx.as_context_mut().inner,
1687                        &module.module,
1688                        &imports,
1689                    )?;
1690                    inner.instances.push(instance);
1691                }
1692                GlobalInitializer::ExtractMemory(_) => {}
1693                GlobalInitializer::ExtractRealloc(_) => {}
1694                GlobalInitializer::ExtractPostReturn(_) => {}
1695                GlobalInitializer::LowerImport { .. } => {}
1696                GlobalInitializer::Resource(_) => {}
1697                _ => bail!("Not yet implemented {initializer:?}."),
1698            }
1699        }
1700
1701        Self::fill_destructors(inner, ctx, destructors, resource_map)
1702    }
1703
1704    /// Generates the set of core WASM imports for this component.
1705    fn generate_imports(
1706        inner: &InstanceInner,
1707        mut store: impl AsContextMut,
1708        linker: &Linker,
1709        module: &ModuleTranslation,
1710        defs: &[CoreDef],
1711        destructors: &mut Vec<TrampolineIndex>,
1712        resource_map: &FxHashMap<ResourceType, ResourceType>,
1713    ) -> Result<Imports> {
1714        let mut import_ty_map = FxHashMap::default();
1715
1716        let engine = store.as_context().engine().clone();
1717        for import in module.module.imports(&engine) {
1718            import_ty_map.insert((import.module, import.name), import.ty.clone());
1719        }
1720
1721        let mut imports = Imports::default();
1722
1723        for (host, name, def) in module
1724            .translation
1725            .imports()
1726            .zip(defs)
1727            .map(|((module, name, _), arg)| (module, name, arg))
1728        {
1729            let ty = import_ty_map
1730                .get(&(host, name))
1731                .context("Unrecognized import.")?
1732                .clone();
1733            imports.define(
1734                host,
1735                name,
1736                Self::core_import(
1737                    inner,
1738                    &mut store,
1739                    def,
1740                    linker,
1741                    ty,
1742                    destructors,
1743                    resource_map,
1744                )?,
1745            );
1746        }
1747
1748        Ok(imports)
1749    }
1750
1751    /// Gets an import from the linker for this component.
1752    fn get_component_import(
1753        import: &ComponentImport,
1754        linker: &Linker,
1755    ) -> Result<crate::func::Func> {
1756        let inst = if let Some(name) = &import.instance {
1757            linker
1758                .instance(name)
1759                .ok_or_else(|| Error::msg(format!("Could not find imported interface {name:?}")))?
1760        } else {
1761            linker.root()
1762        };
1763
1764        inst.func(&import.name)
1765            .ok_or_else(|| Error::msg(format!("Could not find function import {}", import.name)))
1766    }
1767
1768    /// Fills the resource tables with all resource destructors.
1769    fn fill_destructors(
1770        inner: InstanceInner,
1771        ctx: impl AsContext,
1772        destructors: Vec<TrampolineIndex>,
1773        resource_map: &FxHashMap<ResourceType, ResourceType>,
1774    ) -> Result<InstanceInner> {
1775        let mut tables = inner
1776            .state_table
1777            .resource_tables
1778            .try_lock()
1779            .expect("Could not get access to resource tables.");
1780
1781        for index in destructors {
1782            let (x, def) = require_matches!(
1783                &inner.component.0.generated_trampolines[&index],
1784                GeneratedTrampoline::ResourceDrop(x, def),
1785                (x, def)
1786            );
1787            if let Some(def) = def {
1788                let export = require_matches!(def, CoreDef::Export(x), x);
1789                tables[x.as_u32() as usize].set_destructor(Some(require_matches!(
1790                    Self::core_export(&inner, &ctx, export),
1791                    Some(Extern::Func(x)),
1792                    x
1793                )));
1794            }
1795        }
1796
1797        for (id, idx) in inner.component.0.resolve.types.iter().filter_map(|(i, _)| {
1798            let val = inner.component.0.resource_map[i.index()];
1799            (val.as_u32() < u32::MAX - 1).then_some((i, val))
1800        }) {
1801            let res = ResourceType::from_resolve(
1802                inner.component.0.type_identifiers[id.index()].clone(),
1803                id,
1804                &inner.component.0,
1805                Some(resource_map),
1806            )?;
1807            match res.host_destructor() {
1808                Some(Some(func)) => tables[idx.as_u32() as usize].set_destructor(Some(func)),
1809                Some(None) => tables[idx.as_u32() as usize]
1810                    .set_destructor(ctx.as_context().inner.data().drop_host_resource.clone()),
1811                _ => {}
1812            }
1813        }
1814
1815        drop(tables);
1816
1817        Ok(inner)
1818    }
1819}
1820
1821/// Provides the exports for an instance.
1822#[derive(Debug)]
1823pub struct Exports {
1824    /// The root interface of this instance.
1825    root: ExportInstance,
1826    /// All of this instance's exported interfaces.
1827    instances: FxHashMap<InterfaceIdentifier, ExportInstance>,
1828}
1829
1830impl Exports {
1831    /// Creates a new set of exports.
1832    pub(crate) fn new() -> Self {
1833        Self {
1834            root: ExportInstance::new(),
1835            instances: FxHashMap::default(),
1836        }
1837    }
1838
1839    /// Gets the root instance.
1840    pub fn root(&self) -> &ExportInstance {
1841        &self.root
1842    }
1843
1844    /// Gets the instance with the specified name, if any.
1845    pub fn instance(&self, name: &InterfaceIdentifier) -> Option<&ExportInstance> {
1846        self.instances.get(name)
1847    }
1848
1849    /// Gets an iterator over all instances by identifier.
1850    pub fn instances(&self) -> impl Iterator<Item = (&'_ InterfaceIdentifier, &'_ ExportInstance)> {
1851        self.instances.iter()
1852    }
1853}
1854
1855/// Represents a specific interface from a instance.
1856#[derive(Debug)]
1857pub struct ExportInstance {
1858    /// The functions of the interface.
1859    functions: FxHashMap<Arc<str>, crate::func::Func>,
1860    /// The resources of the interface.
1861    resources: FxHashMap<Arc<str>, ResourceType>,
1862    /// The instance that owns these exports.
1863    instance: Weak<InstanceInner>,
1864}
1865
1866impl ExportInstance {
1867    /// Creates a new, empty instance.
1868    pub(crate) fn new() -> Self {
1869        Self {
1870            functions: FxHashMap::default(),
1871            resources: FxHashMap::default(),
1872            instance: Weak::new(),
1873        }
1874    }
1875
1876    /// Gets the associated function by name, if any.
1877    pub fn func(&self, name: impl AsRef<str>) -> Option<crate::func::Func> {
1878        self.functions.get(name.as_ref()).map(|x| {
1879            x.instantiate(Instance(
1880                self.instance.upgrade().expect("Instance did not exist."),
1881            ))
1882        })
1883    }
1884
1885    /// Iterates over all associated functions by name.
1886    pub fn funcs(&self) -> impl Iterator<Item = (&'_ str, crate::func::Func)> {
1887        let inst = self.instance.upgrade().expect("Instance did not exist.");
1888        self.functions
1889            .iter()
1890            .map(move |(k, v)| (&**k, v.instantiate(Instance(inst.clone()))))
1891    }
1892
1893    /// Gets the associated abstract resource by name, if any.
1894    pub fn resource(&self, name: impl AsRef<str>) -> Option<ResourceType> {
1895        self.resources.get(name.as_ref()).cloned()
1896    }
1897
1898    /// Iterates over all associated functions by name.
1899    pub fn resources(&self) -> impl Iterator<Item = (&'_ str, ResourceType)> {
1900        self.resources.iter().map(|(k, v)| (&**k, v.clone()))
1901    }
1902}
1903
1904/// Stores the internal state for an instance.
1905#[derive(Debug)]
1906struct InstanceInner {
1907    /// The component from which this instance was created.
1908    pub component: Component,
1909    /// The exports of this instance.
1910    pub exports: Exports,
1911    /// The unique ID of this instance.
1912    pub id: u64,
1913    /// The flags associated with this instance.
1914    pub instance_flags: wasmtime_environ::PrimaryMap<RuntimeComponentInstanceIndex, Global>,
1915    /// The underlying instantiated WASM modules for this instance.
1916    pub instances: wasmtime_environ::PrimaryMap<RuntimeInstanceIndex, wasm_runtime_layer::Instance>,
1917    /// Stores the instance-specific state.
1918    pub state_table: Arc<StateTable>,
1919    /// The list of types for this instance.
1920    pub types: Arc<[crate::types::ValueType]>,
1921    /// The store ID associated with this instance.
1922    pub store_id: u64,
1923}
1924
1925/// Stores the instance-specific state for a component.
1926#[derive(Debug)]
1927struct StateTable {
1928    /// Whether this instance has been dropped.
1929    pub dropped: AtomicBool,
1930    /// The set of resource tables and destructors.
1931    pub resource_tables: Mutex<Vec<HandleTable>>,
1932}
1933
1934/// Details an import for a component.
1935#[derive(Clone, Debug)]
1936struct ComponentImport {
1937    /// The interface from which this export originates.
1938    pub instance: Option<InterfaceIdentifier>,
1939    /// The name of the import.
1940    pub name: Arc<str>,
1941    /// The function associated with the import.
1942    pub func: Function,
1943    /// The canonical options with which the import will be called.
1944    pub options: CanonicalOptions,
1945}
1946
1947/// Details an export from a component.
1948#[derive(Clone, Debug)]
1949struct ComponentExport {
1950    /// The canonical options with which the export will be called.
1951    pub options: CanonicalOptions,
1952    /// The function associated with the export.
1953    pub func: Function,
1954    /// The definition of the export.
1955    pub def: CoreExport<wasmtime_environ::EntityIndex>,
1956    /// The type of export.
1957    pub ty: crate::types::FuncType,
1958}
1959
1960/// The store represents all global state that can be manipulated by
1961/// WebAssembly programs. It consists of the runtime representation
1962/// of all instances of functions, tables, memories, and globals that
1963/// have been allocated during the lifetime of the abstract machine.
1964///
1965/// The `Store` holds the engine (that is —amongst many things— used to compile
1966/// the Wasm bytes into a valid module artifact).
1967///
1968/// Spec: <https://webassembly.github.io/spec/core/exec/runtime.html#store>
1969pub struct Store<T, E: backend::WasmEngine> {
1970    /// The backing implementation.
1971    inner: wasm_runtime_layer::Store<StoreInner<T, E>, E>,
1972}
1973
1974impl<T, E: backend::WasmEngine> Store<T, E> {
1975    /// Creates a new [`Store`] with a specific [`Engine`].
1976    pub fn new(engine: &Engine<E>, data: T) -> Self {
1977        /// A counter that uniquely identifies stores.
1978        static ID_COUNTER: AtomicU64 = AtomicU64::new(0);
1979
1980        let mut inner = wasm_runtime_layer::Store::new(
1981            engine,
1982            StoreInner {
1983                id: ID_COUNTER.fetch_add(1, Ordering::AcqRel),
1984                data,
1985                host_functions: FuncVec::default(),
1986                host_resources: Slab::default(),
1987                drop_host_resource: None,
1988            },
1989        );
1990
1991        inner.data_mut().drop_host_resource = Some(wasm_runtime_layer::Func::new(
1992            &mut inner,
1993            wasm_runtime_layer::FuncType::new([wasm_runtime_layer::ValueType::I32], [])
1994                .with_name("drop-host-resources"),
1995            |mut ctx, args, _| {
1996                if let wasm_runtime_layer::Value::I32(index) = &args[0] {
1997                    ctx.data_mut().host_resources.remove(*index as usize);
1998                    Ok(())
1999                } else {
2000                    bail!("Could not drop resource.");
2001                }
2002            },
2003        ));
2004
2005        Self { inner }
2006    }
2007
2008    /// Returns the [`Engine`] that this store is associated with.
2009    pub fn engine(&self) -> &Engine<E> {
2010        self.inner.engine()
2011    }
2012
2013    /// Returns a shared reference to the user provided data owned by this [`Store`].
2014    pub fn data(&self) -> &T {
2015        &self.inner.data().data
2016    }
2017
2018    /// Returns an exclusive reference to the user provided data owned by this [`Store`].
2019    pub fn data_mut(&mut self) -> &mut T {
2020        &mut self.inner.data_mut().data
2021    }
2022
2023    /// Consumes `self` and returns its user provided data.
2024    pub fn into_data(self) -> T {
2025        self.inner.into_data().data
2026    }
2027}
2028
2029/// A temporary handle to a [`&Store<T>`][`Store`].
2030///
2031/// This type is suitable for [`AsContext`] trait bounds on methods if desired.
2032/// For more information, see [`Store`].
2033pub struct StoreContext<'a, T: 'a, E: backend::WasmEngine> {
2034    /// The backing implementation.
2035    inner: wasm_runtime_layer::StoreContext<'a, StoreInner<T, E>, E>,
2036}
2037
2038impl<'a, T: 'a, E: backend::WasmEngine> StoreContext<'a, T, E> {
2039    /// Returns the underlying [`Engine`] this store is connected to.
2040    pub fn engine(&self) -> &Engine<E> {
2041        self.inner.engine()
2042    }
2043
2044    /// Access the underlying data owned by this store.
2045    ///
2046    /// Same as [`Store::data`].
2047    pub fn data(&self) -> &T {
2048        &self.inner.data().data
2049    }
2050}
2051
2052/// A temporary handle to a [`&mut Store<T>`][`Store`].
2053///
2054/// This type is suitable for [`AsContextMut`] or [`AsContext`] trait bounds on methods if desired.
2055/// For more information, see [`Store`].
2056pub struct StoreContextMut<'a, T: 'a, E: backend::WasmEngine> {
2057    /// The backing implementation.
2058    inner: wasm_runtime_layer::StoreContextMut<'a, StoreInner<T, E>, E>,
2059}
2060
2061impl<'a, T: 'a, E: backend::WasmEngine> StoreContextMut<'a, T, E> {
2062    /// Returns the underlying [`Engine`] this store is connected to.
2063    pub fn engine(&self) -> &Engine<E> {
2064        self.inner.engine()
2065    }
2066
2067    /// Access the underlying data owned by this store.
2068    ///
2069    /// Same as [`Store::data`].
2070    pub fn data(&self) -> &T {
2071        &self.inner.data().data
2072    }
2073
2074    /// Access the underlying data owned by this store.
2075    ///
2076    /// Same as [`Store::data_mut`].
2077    pub fn data_mut(&mut self) -> &mut T {
2078        &mut self.inner.data_mut().data
2079    }
2080}
2081
2082/// A trait used to get shared access to a [`Store`].
2083pub trait AsContext {
2084    /// The engine type associated with the context.
2085    type Engine: backend::WasmEngine;
2086
2087    /// The user state associated with the [`Store`], aka the `T` in `Store<T>`.
2088    type UserState;
2089
2090    /// Returns the store context that this type provides access to.
2091    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine>;
2092}
2093
2094/// A trait used to get exclusive access to a [`Store`].
2095pub trait AsContextMut: AsContext {
2096    /// Returns the store context that this type provides access to.
2097    fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine>;
2098}
2099
2100impl<T, E: backend::WasmEngine> AsContext for Store<T, E> {
2101    type Engine = E;
2102
2103    type UserState = T;
2104
2105    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
2106        StoreContext {
2107            inner: wasm_runtime_layer::AsContext::as_context(&self.inner),
2108        }
2109    }
2110}
2111
2112impl<T, E: backend::WasmEngine> AsContextMut for Store<T, E> {
2113    fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine> {
2114        StoreContextMut {
2115            inner: wasm_runtime_layer::AsContextMut::as_context_mut(&mut self.inner),
2116        }
2117    }
2118}
2119
2120impl<T: AsContext> AsContext for &T {
2121    type Engine = T::Engine;
2122
2123    type UserState = T::UserState;
2124
2125    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
2126        (**self).as_context()
2127    }
2128}
2129
2130impl<T: AsContext> AsContext for &mut T {
2131    type Engine = T::Engine;
2132
2133    type UserState = T::UserState;
2134
2135    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
2136        (**self).as_context()
2137    }
2138}
2139
2140impl<T: AsContextMut> AsContextMut for &mut T {
2141    fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine> {
2142        (**self).as_context_mut()
2143    }
2144}
2145
2146impl<'a, T: 'a, E: backend::WasmEngine> AsContext for StoreContext<'a, T, E> {
2147    type Engine = E;
2148
2149    type UserState = T;
2150
2151    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
2152        StoreContext {
2153            inner: wasm_runtime_layer::AsContext::as_context(&self.inner),
2154        }
2155    }
2156}
2157
2158impl<'a, T: 'a, E: backend::WasmEngine> AsContext for StoreContextMut<'a, T, E> {
2159    type Engine = E;
2160
2161    type UserState = T;
2162
2163    fn as_context(&self) -> StoreContext<Self::UserState, Self::Engine> {
2164        StoreContext {
2165            inner: wasm_runtime_layer::AsContext::as_context(&self.inner),
2166        }
2167    }
2168}
2169
2170impl<'a, T: 'a, E: backend::WasmEngine> AsContextMut for StoreContextMut<'a, T, E> {
2171    fn as_context_mut(&mut self) -> StoreContextMut<Self::UserState, Self::Engine> {
2172        StoreContextMut {
2173            inner: wasm_runtime_layer::AsContextMut::as_context_mut(&mut self.inner),
2174        }
2175    }
2176}
2177
2178/// Holds the inner mutable state for a component model implementation.
2179struct StoreInner<T, E: backend::WasmEngine> {
2180    /// The unique ID of this store.
2181    pub id: u64,
2182    /// The consumer's custom data.
2183    pub data: T,
2184    /// The table of host functions.
2185    pub host_functions: FuncVec<T, E>,
2186    /// The table of host resources.
2187    pub host_resources: Slab<Box<dyn Any + Send + Sync>>,
2188    /// A function that drops a host resource from this store.
2189    pub drop_host_resource: Option<wasm_runtime_layer::Func>,
2190}
2191
2192/// Denotes a trampoline used by components to interact with the host.
2193#[allow(clippy::large_enum_variant)]
2194#[derive(Clone, Debug)]
2195enum GeneratedTrampoline {
2196    /// The guest would like to call an imported function.
2197    ImportedFunction(ComponentImport),
2198    /// The guest would like to create a new resource.
2199    ResourceNew(TypeResourceTableIndex),
2200    /// The guest would like to obtain the representation of a resource.
2201    ResourceRep(TypeResourceTableIndex),
2202    /// The guest would like to drop a resource.
2203    ResourceDrop(TypeResourceTableIndex, Option<CoreDef>),
2204}
2205
2206/// Represents a resource handle owned by a guest instance.
2207#[derive(Copy, Clone, Debug, Default)]
2208struct HandleElement {
2209    /// The originating instance's representation of the handle.
2210    pub rep: i32,
2211    /// Whether this handle is owned by this instance.
2212    pub own: bool,
2213    /// The number of times that this handle has been lent, without any borrows being returned.
2214    pub lend_count: i32,
2215}
2216
2217/// Stores a set of resource handles and associated type information.
2218#[derive(Clone, Debug, Default)]
2219struct HandleTable {
2220    /// The array of handles.
2221    array: Slab<HandleElement>,
2222    /// The destructor for this handle type.
2223    destructor: Option<wasm_runtime_layer::Func>,
2224}
2225
2226impl HandleTable {
2227    /// Gets the destructor for this handle table.
2228    pub fn destructor(&self) -> Option<&wasm_runtime_layer::Func> {
2229        self.destructor.as_ref()
2230    }
2231
2232    /// Sets the destructor for this handle table.
2233    pub fn set_destructor(&mut self, destructor: Option<wasm_runtime_layer::Func>) {
2234        self.destructor = destructor;
2235    }
2236
2237    /// Gets the element at the specified slot, or fails if it is empty.
2238    pub fn get(&self, i: i32) -> Result<&HandleElement> {
2239        self.array.get(i as usize).context("Invalid handle index.")
2240    }
2241
2242    /// Sets the element at the specified slot, panicking if an element was
2243    /// not already there.
2244    pub fn set(&mut self, i: i32, element: HandleElement) {
2245        *self
2246            .array
2247            .get_mut(i as usize)
2248            .expect("Invalid handle index.") = element;
2249    }
2250
2251    /// Inserts a new handle into this table, returning its index.
2252    pub fn add(&mut self, handle: HandleElement) -> i32 {
2253        self.array.insert(handle) as i32
2254    }
2255
2256    /// Removes the handle at the provided index from the table,
2257    /// or fails if there was no handle present.
2258    pub fn remove(&mut self, i: i32) -> Result<HandleElement> {
2259        Ok(self.array.remove(i as usize))
2260    }
2261}