Skip to main content

wasmtime_environ/component/
types.rs

1use crate::component::{MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
2use crate::{EntityType, ModuleInternedTypeIndex, ModuleTypes, PanicOnOom as _};
3use crate::{TypeTrace, prelude::*};
4use core::hash::{Hash, Hasher};
5use core::ops::Index;
6use serde_derive::{Deserialize, Serialize};
7use wasmparser::component_types::ComponentAnyTypeId;
8use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9
10pub use crate::StaticModuleIndex;
11
12macro_rules! indices {
13    ($(
14        $(#[$a:meta])*
15        pub struct $name:ident(u32);
16    )*) => ($(
17        $(#[$a])*
18        #[derive(
19            Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
20            Serialize, Deserialize,
21        )]
22        #[repr(transparent)]
23        pub struct $name(u32);
24        cranelift_entity::entity_impl!($name);
25        impl TryClone for $name {
26            #[inline]
27            fn try_clone(&self) -> Result<Self, OutOfMemory> {
28                Ok(*self)
29            }
30        }
31    )*);
32}
33
34indices! {
35    // ========================================================================
36    // These indices are used during compile time only when we're translating a
37    // component at this time. The actual indices are not persisted beyond the
38    // compile phase to when we're actually working with the component at
39    // runtime.
40
41    /// Index within a component's component type index space.
42    pub struct ComponentTypeIndex(u32);
43
44    /// Index within a component's module index space.
45    pub struct ModuleIndex(u32);
46
47    /// Index within a component's component index space.
48    pub struct ComponentIndex(u32);
49
50    /// Index within a component's module instance index space.
51    pub struct ModuleInstanceIndex(u32);
52
53    /// Index within a component's component instance index space.
54    pub struct ComponentInstanceIndex(u32);
55
56    /// Index within a component's component function index space.
57    pub struct ComponentFuncIndex(u32);
58
59    // ========================================================================
60    // These indices are used to lookup type information within a `TypeTables`
61    // structure. These represent generally deduplicated type information across
62    // an entire component and are a form of RTTI in a sense.
63
64    /// Index pointing to a component's type (exports/imports with
65    /// component-model types)
66    pub struct TypeComponentIndex(u32);
67
68    /// Index pointing to a component instance's type (exports with
69    /// component-model types, no imports)
70    pub struct TypeComponentInstanceIndex(u32);
71
72    /// Index pointing to a core wasm module's type (exports/imports with
73    /// core wasm types)
74    pub struct TypeModuleIndex(u32);
75
76    /// Index pointing to a component model function type with arguments/result
77    /// as interface types.
78    pub struct TypeFuncIndex(u32);
79
80    /// Index pointing to a record type in the component model (aka a struct).
81    pub struct TypeRecordIndex(u32);
82    /// Index pointing to a variant type in the component model (aka an enum).
83    pub struct TypeVariantIndex(u32);
84    /// Index pointing to a tuple type in the component model.
85    pub struct TypeTupleIndex(u32);
86    /// Index pointing to a flags type in the component model.
87    pub struct TypeFlagsIndex(u32);
88    /// Index pointing to an enum type in the component model.
89    pub struct TypeEnumIndex(u32);
90    /// Index pointing to an option type in the component model (aka a
91    /// `Option<T, E>`)
92    pub struct TypeOptionIndex(u32);
93    /// Index pointing to an result type in the component model (aka a
94    /// `Result<T, E>`)
95    pub struct TypeResultIndex(u32);
96    /// Index pointing to a list type in the component model.
97    pub struct TypeListIndex(u32);
98    /// Index pointing to a map type in the component model.
99    pub struct TypeMapIndex(u32);
100    /// Index pointing to a fixed size list type in the component model.
101    pub struct TypeFixedLengthListIndex(u32);
102    /// Index pointing to a future type in the component model.
103    pub struct TypeFutureIndex(u32);
104
105    /// Index pointing to a future table within a component.
106    ///
107    /// This is analogous to `TypeResourceTableIndex` in that it tracks
108    /// ownership of futures within each (sub)component instance.
109    pub struct TypeFutureTableIndex(u32);
110
111    /// Index pointing to a stream type in the component model.
112    pub struct TypeStreamIndex(u32);
113
114    /// Index pointing to a stream table within a component.
115    ///
116    /// This is analogous to `TypeResourceTableIndex` in that it tracks
117    /// ownership of stream within each (sub)component instance.
118    pub struct TypeStreamTableIndex(u32);
119
120    /// Index pointing to a error context table within a component.
121    ///
122    /// This is analogous to `TypeResourceTableIndex` in that it tracks
123    /// ownership of error contexts within each (sub)component instance.
124    pub struct TypeComponentLocalErrorContextTableIndex(u32);
125
126    /// Index pointing to a (component) globally tracked error context table entry
127    ///
128    /// Unlike [`TypeComponentLocalErrorContextTableIndex`], this index refers to
129    /// the global state table for error contexts at the level of the entire component,
130    /// not just a subcomponent.
131    pub struct TypeComponentGlobalErrorContextTableIndex(u32);
132
133    /// Index pointing to a resource table within a component.
134    ///
135    /// This is a Wasmtime-specific type index which isn't part of the component
136    /// model per-se (or at least not the binary format). This index represents
137    /// a pointer to a table of runtime information tracking state for resources
138    /// within a component. Tables are generated per-resource-per-component
139    /// meaning that if the exact same resource is imported into 4 subcomponents
140    /// then that's 5 tables: one for the defining component and one for each
141    /// subcomponent.
142    ///
143    /// All resource-related intrinsics operate on table-local indices which
144    /// indicate which table the intrinsic is modifying. Each resource table has
145    /// an origin resource type (defined by `ResourceIndex`) along with a
146    /// component instance that it's recorded for.
147    pub struct TypeResourceTableIndex(u32);
148
149    /// Index pointing to a resource within a component.
150    ///
151    /// This index space covers all unique resource type definitions. For
152    /// example all unique imports come first and then all locally-defined
153    /// resources come next. Note that this does not count the number of runtime
154    /// tables required to track resources (that's `TypeResourceTableIndex`
155    /// instead). Instead this is a count of the number of unique
156    /// `(type (resource (rep ..)))` declarations within a component, plus
157    /// imports.
158    ///
159    /// This is then used for correlating various information such as
160    /// destructors, origin information, etc.
161    pub struct ResourceIndex(u32);
162
163    /// Index pointing to a local resource defined within a component.
164    ///
165    /// This is similar to `FooIndex` and `DefinedFooIndex` for core wasm and
166    /// the idea here is that this is guaranteed to be a wasm-defined resource
167    /// which is connected to a component instance for example.
168    pub struct DefinedResourceIndex(u32);
169
170    // ========================================================================
171    // Index types used to identify modules and components during compilation.
172
173    /// Index into a "closed over variables" list for components used to
174    /// implement outer aliases. For more information on this see the
175    /// documentation for the `LexicalScope` structure.
176    pub struct ModuleUpvarIndex(u32);
177
178    /// Same as `ModuleUpvarIndex` but for components.
179    pub struct ComponentUpvarIndex(u32);
180
181    /// Same as `StaticModuleIndex` but for components.
182    pub struct StaticComponentIndex(u32);
183
184    // ========================================================================
185    // These indices are actually used at runtime when managing a component at
186    // this time.
187
188    /// Index that represents a core wasm instance created at runtime.
189    ///
190    /// This is used to keep track of when instances are created and is able to
191    /// refer back to previously created instances for exports and such.
192    pub struct RuntimeInstanceIndex(u32);
193
194    /// Same as `RuntimeInstanceIndex` but tracks component instances instead.
195    pub struct RuntimeComponentInstanceIndex(u32);
196
197    /// Used to index imports into a `Component`
198    ///
199    /// This does not correspond to anything in the binary format for the
200    /// component model.
201    pub struct ImportIndex(u32);
202
203    /// Index that represents a leaf item imported into a component where a
204    /// "leaf" means "not an instance".
205    ///
206    /// This does not correspond to anything in the binary format for the
207    /// component model.
208    pub struct RuntimeImportIndex(u32);
209
210    /// Index that represents a lowered host function and is used to represent
211    /// host function lowerings with options and such.
212    ///
213    /// This does not correspond to anything in the binary format for the
214    /// component model.
215    pub struct LoweredIndex(u32);
216
217    /// Index representing a linear memory extracted from a wasm instance
218    /// which is stored in a `VMComponentContext`. This is used to deduplicate
219    /// references to the same linear memory where it's only stored once in a
220    /// `VMComponentContext`.
221    ///
222    /// This does not correspond to anything in the binary format for the
223    /// component model.
224    pub struct RuntimeMemoryIndex(u32);
225
226    /// Same as `RuntimeMemoryIndex` except for the `realloc` function.
227    pub struct RuntimeReallocIndex(u32);
228
229    /// Same as `RuntimeMemoryIndex` except for the `callback` function.
230    pub struct RuntimeCallbackIndex(u32);
231
232    /// Same as `RuntimeMemoryIndex` except for the `post-return` function.
233    pub struct RuntimePostReturnIndex(u32);
234
235    /// Index representing a table extracted from a wasm instance which is
236    /// stored in a `VMComponentContext`. This is used to deduplicate references
237    /// to the same table when it's only stored once in a `VMComponentContext`.
238    ///
239    /// This does not correspond to anything in the binary format for the
240    /// component model.
241    pub struct RuntimeTableIndex(u32);
242
243    /// Index for all trampolines that are compiled in Cranelift for a
244    /// component.
245    ///
246    /// This is used to point to various bits of metadata within a compiled
247    /// component and is stored in the final compilation artifact. This does not
248    /// have a direct correspondence to any wasm definition.
249    pub struct TrampolineIndex(u32);
250
251    /// An index into `Component::export_items` at the end of compilation.
252    pub struct ExportIndex(u32);
253
254    /// An index into `Component::options` at the end of compilation.
255    pub struct OptionsIndex(u32);
256
257    /// An index that doesn't actually index into a list but instead represents
258    /// a unique counter.
259    ///
260    /// This is used for "abstract" resources which aren't actually instantiated
261    /// in the component model. For example this represents a resource in a
262    /// component or instance type, but not an actual concrete instance.
263    pub struct AbstractResourceIndex(u32);
264}
265
266// Reexport for convenience some core-wasm indices which are also used in the
267// component model, typically for when aliasing exports of core wasm modules.
268pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
269
270/// Equivalent of `EntityIndex` but for the component model instead of core
271/// wasm.
272#[derive(Debug, Clone, Copy)]
273#[expect(missing_docs, reason = "self-describing variants")]
274pub enum ComponentItem {
275    Func(ComponentFuncIndex),
276    Module(ModuleIndex),
277    Component(ComponentIndex),
278    ComponentInstance(ComponentInstanceIndex),
279    Type(ComponentAnyTypeId),
280}
281
282/// Runtime information about the type information contained within a component.
283///
284/// One of these is created per top-level component which describes all of the
285/// types contained within the top-level component itself. Each sub-component
286/// will have a pointer to this value as well.
287#[derive(Default, Serialize, Deserialize)]
288pub struct ComponentTypes {
289    pub(super) modules: TryPrimaryMap<TypeModuleIndex, TypeModule>,
290    pub(super) components: TryPrimaryMap<TypeComponentIndex, TypeComponent>,
291    pub(super) component_instances:
292        TryPrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
293    pub(super) functions: TryPrimaryMap<TypeFuncIndex, TypeFunc>,
294    pub(super) lists: TryPrimaryMap<TypeListIndex, TypeList>,
295    pub(super) maps: TryPrimaryMap<TypeMapIndex, TypeMap>,
296    pub(super) records: TryPrimaryMap<TypeRecordIndex, TypeRecord>,
297    pub(super) variants: TryPrimaryMap<TypeVariantIndex, TypeVariant>,
298    pub(super) tuples: TryPrimaryMap<TypeTupleIndex, TypeTuple>,
299    pub(super) enums: TryPrimaryMap<TypeEnumIndex, TypeEnum>,
300    pub(super) flags: TryPrimaryMap<TypeFlagsIndex, TypeFlags>,
301    pub(super) options: TryPrimaryMap<TypeOptionIndex, TypeOption>,
302    pub(super) results: TryPrimaryMap<TypeResultIndex, TypeResult>,
303    pub(super) resource_tables: TryPrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
304    pub(super) module_types: Option<ModuleTypes>,
305    pub(super) futures: TryPrimaryMap<TypeFutureIndex, TypeFuture>,
306    pub(super) future_tables: TryPrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
307    pub(super) streams: TryPrimaryMap<TypeStreamIndex, TypeStream>,
308    pub(super) stream_tables: TryPrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
309    pub(super) error_context_tables:
310        TryPrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
311    pub(super) fixed_length_lists: TryPrimaryMap<TypeFixedLengthListIndex, TypeFixedLengthList>,
312}
313
314impl TypeTrace for ComponentTypes {
315    fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
316    where
317        F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
318    {
319        for (_, m) in &self.modules {
320            m.trace(func)?;
321        }
322        if let Some(m) = self.module_types.as_ref() {
323            m.trace(func)?;
324        }
325        Ok(())
326    }
327
328    fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
329    where
330        F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
331    {
332        for (_, m) in &mut self.modules {
333            m.trace_mut(func)?;
334        }
335        if let Some(m) = self.module_types.as_mut() {
336            m.trace_mut(func)?;
337        }
338        Ok(())
339    }
340}
341
342impl ComponentTypes {
343    /// Returns whether the resource that `ty` points to is owned by the very
344    /// instance that `ty` itself belongs to.
345    pub fn resource_owned_by_own_instance(
346        &self,
347        ty: TypeResourceTableIndex,
348        defined_resource_instance: impl FnOnce(ResourceIndex) -> Option<RuntimeComponentInstanceIndex>,
349    ) -> bool {
350        let (resource_ty, resource_instance) = match self[ty] {
351            TypeResourceTable::Concrete { ty, instance } => (ty, instance),
352            // Abstract tables don't exist at runtime, so there's nothing to
353            // own them.
354            TypeResourceTable::Abstract(_) => return false,
355        };
356        // An imported resource is never defined by, and so never owned by, an
357        // instance within this component.
358        defined_resource_instance(resource_ty) == Some(resource_instance)
359    }
360
361    /// Returns the core wasm module types known within this component.
362    pub fn module_types(&self) -> &ModuleTypes {
363        self.module_types.as_ref().unwrap()
364    }
365
366    /// Returns the core wasm module types known within this component.
367    pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
368        self.module_types.as_mut().unwrap()
369    }
370
371    /// Returns the canonical ABI information about the specified type.
372    pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
373        match ty {
374            InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
375                &CanonicalAbiInfo::SCALAR1
376            }
377
378            InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
379
380            InterfaceType::U32
381            | InterfaceType::S32
382            | InterfaceType::Float32
383            | InterfaceType::Char
384            | InterfaceType::Own(_)
385            | InterfaceType::Borrow(_)
386            | InterfaceType::Future(_)
387            | InterfaceType::Stream(_)
388            | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
389
390            InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
391                &CanonicalAbiInfo::SCALAR8
392            }
393
394            InterfaceType::String | InterfaceType::List(_) | InterfaceType::Map(_) => {
395                &CanonicalAbiInfo::POINTER_PAIR
396            }
397
398            InterfaceType::Record(i) => &self[*i].abi,
399            InterfaceType::Variant(i) => &self[*i].abi,
400            InterfaceType::Tuple(i) => &self[*i].abi,
401            InterfaceType::Flags(i) => &self[*i].abi,
402            InterfaceType::Enum(i) => &self[*i].abi,
403            InterfaceType::Option(i) => &self[*i].abi,
404            InterfaceType::Result(i) => &self[*i].abi,
405            InterfaceType::FixedLengthList(i) => &self[*i].abi,
406        }
407    }
408
409    /// Adds a new `table` to the list of resource tables for this component.
410    pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
411        self.resource_tables.push(table).panic_on_oom()
412    }
413}
414
415macro_rules! impl_index {
416    ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
417        impl core::ops::Index<$ty> for ComponentTypes {
418            type Output = $output;
419            #[inline]
420            fn index(&self, idx: $ty) -> &$output {
421                &self.$field[idx]
422            }
423        }
424
425        #[cfg(feature = "compile")]
426        impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
427            type Output = $output;
428            #[inline]
429            fn index(&self, idx: $ty) -> &$output {
430                &self.component_types()[idx]
431            }
432        }
433    )*)
434}
435
436impl_index! {
437    impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
438    impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
439    impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
440    impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
441    impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
442    impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
443    impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
444    impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
445    impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
446    impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
447    impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
448    impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
449    impl Index<TypeMapIndex> for ComponentTypes { TypeMap => maps }
450    impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
451    impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
452    impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
453    impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
454    impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
455    impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
456    impl Index<TypeFixedLengthListIndex> for ComponentTypes { TypeFixedLengthList => fixed_length_lists }
457}
458
459// Additionally forward anything that can index `ModuleTypes` to `ModuleTypes`
460// (aka `SignatureIndex`)
461impl<T> Index<T> for ComponentTypes
462where
463    ModuleTypes: Index<T>,
464{
465    type Output = <ModuleTypes as Index<T>>::Output;
466    fn index(&self, idx: T) -> &Self::Output {
467        self.module_types.as_ref().unwrap().index(idx)
468    }
469}
470
471/// An import or an export of a component or a component instance.
472///
473/// This records the type of the item that is being imported or exported along
474/// with any metadata associated with the item.
475#[derive(Debug, Serialize, Deserialize)]
476pub struct ComponentExtern {
477    /// Metadata associated with this item's name, such as
478    /// `(implements "...")`.
479    pub data: ComponentExternData,
480    /// The type of this item.
481    pub ty: TypeDef,
482}
483
484impl TryClone for ComponentExtern {
485    fn try_clone(&self) -> Result<Self, OutOfMemory> {
486        Ok(ComponentExtern {
487            data: self.data.try_clone()?,
488            ty: self.ty,
489        })
490    }
491}
492
493/// Metadata associated with the name of a component import or export.
494#[derive(Debug, Serialize, Deserialize)]
495pub struct ComponentExternData {
496    /// The `(implements "...")` annotation, if present: the name of the
497    /// interface that this item implements.
498    ///
499    /// This is metadata only: imports are resolved by their own name (e.g.
500    /// `my-label`), not by this interface name. Embedders can use it to find
501    /// out which interface a labelled item implements.
502    pub implements: Option<TryString>,
503    /// The `(external-id "...")` annotation, if present: a free-form
504    /// host-defined identifier which is ignored by type checking.
505    pub external_id: Option<TryString>,
506}
507
508impl TryClone for ComponentExternData {
509    fn try_clone(&self) -> Result<Self, OutOfMemory> {
510        Ok(ComponentExternData {
511            implements: self.implements.try_clone()?,
512            external_id: self.external_id.try_clone()?,
513        })
514    }
515}
516
517/// Types of imports and exports in the component model.
518///
519/// These types are what's available for import and export in components. Note
520/// that all indirect indices contained here are intended to be looked up
521/// through a sibling `ComponentTypes` structure.
522#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
523pub enum TypeDef {
524    /// A component and its type.
525    Component(TypeComponentIndex),
526    /// An instance of a component.
527    ComponentInstance(TypeComponentInstanceIndex),
528    /// A component function, not to be confused with a core wasm function.
529    ComponentFunc(TypeFuncIndex),
530    /// An type in an interface.
531    Interface(InterfaceType),
532    /// A core wasm module and its type.
533    Module(TypeModuleIndex),
534    /// A core wasm function using only core wasm types.
535    CoreFunc(ModuleInternedTypeIndex),
536    /// A resource type which operates on the specified resource table.
537    ///
538    /// Note that different resource tables may point to the same underlying
539    /// actual resource type, but that's a private detail.
540    Resource(TypeResourceTableIndex),
541}
542
543impl TypeDef {
544    /// A human readable description of what kind of type definition this is.
545    pub fn desc(&self) -> &str {
546        match self {
547            TypeDef::Component(_) => "component",
548            TypeDef::ComponentInstance(_) => "instance",
549            TypeDef::ComponentFunc(_) => "function",
550            TypeDef::Interface(_) => "type",
551            TypeDef::Module(_) => "core module",
552            TypeDef::CoreFunc(_) => "core function",
553            TypeDef::Resource(_) => "resource",
554        }
555    }
556}
557
558// NB: Note that maps below are stored as an `IndexMap` now but the order
559// typically does not matter. As a minor implementation detail we want the
560// serialization of this type to always be deterministic and using `IndexMap`
561// gets us that over using a `HashMap` for example.
562
563/// The type of a module in the component model.
564///
565/// Note that this is not to be confused with `TypeComponent` below. This is
566/// intended only for core wasm modules, not for components.
567#[derive(Serialize, Deserialize, Default)]
568pub struct TypeModule {
569    /// The values that this module imports.
570    ///
571    /// Note that the value of this map is a core wasm `EntityType`, not a
572    /// component model `TypeRef`. Additionally note that this reflects the
573    /// two-level namespace of core WebAssembly, but unlike core wasm all import
574    /// names are required to be unique to describe a module in the component
575    /// model.
576    pub imports: TryIndexMap<(TryString, TryString), EntityType>,
577
578    /// The values that this module exports.
579    ///
580    /// Note that the value of this map is the core wasm `EntityType` to
581    /// represent that core wasm items are being exported.
582    pub exports: TryIndexMap<TryString, EntityType>,
583}
584
585impl TypeTrace for TypeModule {
586    fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
587    where
588        F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
589    {
590        for ty in self.imports.values() {
591            ty.trace(func)?;
592        }
593        for ty in self.exports.values() {
594            ty.trace(func)?;
595        }
596        Ok(())
597    }
598
599    fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
600    where
601        F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
602    {
603        for ty in self.imports.values_mut() {
604            ty.trace_mut(func)?;
605        }
606        for ty in self.exports.values_mut() {
607            ty.trace_mut(func)?;
608        }
609        Ok(())
610    }
611}
612
613/// The type of a component in the component model.
614#[derive(Serialize, Deserialize, Default)]
615pub struct TypeComponent {
616    /// The named values that this component imports.
617    pub imports: TryIndexMap<TryString, ComponentExtern>,
618    /// The named values that this component exports.
619    pub exports: TryIndexMap<TryString, ComponentExtern>,
620}
621
622/// The type of a component instance in the component model, or an instantiated
623/// component.
624///
625/// Component instances only have exports of types in the component model.
626#[derive(Serialize, Deserialize, Default)]
627pub struct TypeComponentInstance {
628    /// The list of exports that this component has along with their types.
629    pub exports: TryIndexMap<TryString, ComponentExtern>,
630}
631
632/// A component function type in the component model.
633#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
634pub struct TypeFunc {
635    /// Whether or not this is an async function.
636    pub async_: bool,
637    /// Names of parameters.
638    pub param_names: TryVec<TryString>,
639    /// Parameters to the function represented as a tuple.
640    pub params: TypeTupleIndex,
641    /// Results of the function represented as a tuple.
642    pub results: TypeTupleIndex,
643}
644
645impl TryClone for TypeFunc {
646    fn try_clone(&self) -> Result<Self, OutOfMemory> {
647        Ok(TypeFunc {
648            async_: self.async_,
649            param_names: self.param_names.try_clone()?,
650            params: self.params,
651            results: self.results,
652        })
653    }
654}
655
656/// All possible interface types that values can have.
657///
658/// This list represents an exhaustive listing of interface types and the
659/// shapes that they can take. Note that this enum is considered an "index" of
660/// forms where for non-primitive types a `ComponentTypes` structure is used to
661/// lookup further information based on the index found here.
662#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
663#[expect(missing_docs, reason = "self-describing variants")]
664pub enum InterfaceType {
665    Bool,
666    S8,
667    U8,
668    S16,
669    U16,
670    S32,
671    U32,
672    S64,
673    U64,
674    Float32,
675    Float64,
676    Char,
677    String,
678    Record(TypeRecordIndex),
679    Variant(TypeVariantIndex),
680    List(TypeListIndex),
681    Tuple(TypeTupleIndex),
682    Map(TypeMapIndex),
683    Flags(TypeFlagsIndex),
684    Enum(TypeEnumIndex),
685    Option(TypeOptionIndex),
686    Result(TypeResultIndex),
687    Own(TypeResourceTableIndex),
688    Borrow(TypeResourceTableIndex),
689    Future(TypeFutureTableIndex),
690    Stream(TypeStreamTableIndex),
691    ErrorContext(TypeComponentLocalErrorContextTableIndex),
692    FixedLengthList(TypeFixedLengthListIndex),
693}
694
695impl TryClone for InterfaceType {
696    fn try_clone(&self) -> Result<Self, OutOfMemory> {
697        Ok(*self)
698    }
699}
700
701/// Bye information about a type in the canonical ABI, with metadata for both
702/// memory32 and memory64-based types.
703#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
704pub struct CanonicalAbiInfo {
705    /// The byte-size of this type in a 32-bit memory.
706    pub size32: u32,
707    /// The byte-alignment of this type in a 32-bit memory.
708    pub align32: u32,
709    /// The byte-size of this type in a 64-bit memory.
710    pub size64: u32,
711    /// The byte-alignment of this type in a 64-bit memory.
712    pub align64: u32,
713    /// The number of types it takes to represents this type in the "flat"
714    /// representation of the canonical abi where everything is passed as
715    /// immediate arguments or results.
716    ///
717    /// If this is `None` then this type is not representable in the flat ABI
718    /// because it is too large.
719    pub flat_count: Option<u8>,
720}
721
722impl Default for CanonicalAbiInfo {
723    fn default() -> CanonicalAbiInfo {
724        CanonicalAbiInfo {
725            size32: 0,
726            align32: 1,
727            size64: 0,
728            align64: 1,
729            flat_count: Some(0),
730        }
731    }
732}
733
734const fn align_to(a: u32, b: u32) -> u32 {
735    assert!(b.is_power_of_two());
736    (a + (b - 1)) & !(b - 1)
737}
738
739const fn max(a: u32, b: u32) -> u32 {
740    if a > b { a } else { b }
741}
742
743impl CanonicalAbiInfo {
744    /// ABI information for zero-sized types.
745    pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
746        size32: 0,
747        align32: 1,
748        size64: 0,
749        align64: 1,
750        flat_count: Some(0),
751    };
752
753    /// ABI information for one-byte scalars.
754    pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
755    /// ABI information for two-byte scalars.
756    pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
757    /// ABI information for four-byte scalars.
758    pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
759    /// ABI information for eight-byte scalars.
760    pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
761
762    const fn scalar(size: u32) -> CanonicalAbiInfo {
763        CanonicalAbiInfo {
764            size32: size,
765            align32: size,
766            size64: size,
767            align64: size,
768            flat_count: Some(1),
769        }
770    }
771
772    /// ABI information for lists/strings which are "pointer pairs"
773    pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
774        size32: 8,
775        align32: 4,
776        size64: 16,
777        align64: 8,
778        flat_count: Some(2),
779    };
780
781    /// Returns the abi for a record represented by the specified fields.
782    pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
783        // NB: this is basically a duplicate copy of
784        // `CanonicalAbiInfo::record_static` and the two should be kept in sync.
785
786        let mut ret = CanonicalAbiInfo::default();
787        for field in fields {
788            ret.size32 = align_to(ret.size32, field.align32) + field.size32;
789            ret.align32 = ret.align32.max(field.align32);
790            ret.size64 = align_to(ret.size64, field.align64) + field.size64;
791            ret.align64 = ret.align64.max(field.align64);
792            ret.flat_count = add_flat(ret.flat_count, field.flat_count);
793        }
794        ret.size32 = align_to(ret.size32, ret.align32);
795        ret.size64 = align_to(ret.size64, ret.align64);
796        return ret;
797    }
798
799    /// Same as `CanonicalAbiInfo::record` but in a `const`-friendly context.
800    pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
801        // NB: this is basically a duplicate copy of `CanonicalAbiInfo::record`
802        // and the two should be kept in sync.
803
804        let mut ret = CanonicalAbiInfo::ZERO;
805        let mut i = 0;
806        while i < fields.len() {
807            let field = &fields[i];
808            ret.size32 = align_to(ret.size32, field.align32) + field.size32;
809            ret.align32 = max(ret.align32, field.align32);
810            ret.size64 = align_to(ret.size64, field.align64) + field.size64;
811            ret.align64 = max(ret.align64, field.align64);
812            ret.flat_count = add_flat(ret.flat_count, field.flat_count);
813            i += 1;
814        }
815        ret.size32 = align_to(ret.size32, ret.align32);
816        ret.size64 = align_to(ret.size64, ret.align64);
817        return ret;
818    }
819
820    /// Returns the abi for a fixed length list
821    pub const fn fixed_length_list_static(
822        element: &CanonicalAbiInfo,
823        count: usize,
824    ) -> CanonicalAbiInfo {
825        if count <= u32::MAX as usize {
826            let count = count as u32;
827            CanonicalAbiInfo {
828                size32: element.size32.saturating_mul(count),
829                align32: element.align32,
830                size64: element.size64.saturating_mul(count),
831                align64: element.align64,
832
833                flat_count: match element.flat_count {
834                    None => None,
835                    Some(c) =>
836                    // .and_then(|c| u8::try_from(c).ok()) is not yet const
837                    {
838                        match count.checked_mul(c as u32) {
839                            Some(product) => {
840                                if product as usize > MAX_FLAT_TYPES || product > u8::MAX as u32 {
841                                    None
842                                } else {
843                                    Some(product as u8)
844                                }
845                            }
846                            None => None,
847                        }
848                    }
849                },
850            }
851        } else {
852            CanonicalAbiInfo {
853                size32: u32::MAX,
854                align32: element.align32,
855                size64: u32::MAX,
856                align64: element.align64,
857                flat_count: None,
858            }
859        }
860    }
861
862    /// Returns the delta from the current value of `offset` to align properly
863    /// and read the next record field of type `abi` for 32-bit memories.
864    pub fn next_field32(&self, offset: &mut u32) -> u32 {
865        *offset = align_to(*offset, self.align32) + self.size32;
866        *offset - self.size32
867    }
868
869    /// Same as `next_field32`, but bumps a usize pointer
870    pub fn next_field32_size(&self, offset: &mut usize) -> usize {
871        let cur = u32::try_from(*offset).unwrap();
872        let cur = align_to(cur, self.align32) + self.size32;
873        *offset = usize::try_from(cur).unwrap();
874        usize::try_from(cur - self.size32).unwrap()
875    }
876
877    /// Returns the delta from the current value of `offset` to align properly
878    /// and read the next record field of type `abi` for 64-bit memories.
879    pub fn next_field64(&self, offset: &mut u32) -> u32 {
880        *offset = align_to(*offset, self.align64) + self.size64;
881        *offset - self.size64
882    }
883
884    /// Same as `next_field64`, but bumps a usize pointer
885    pub fn next_field64_size(&self, offset: &mut usize) -> usize {
886        let cur = u32::try_from(*offset).unwrap();
887        let cur = align_to(cur, self.align64) + self.size64;
888        *offset = usize::try_from(cur).unwrap();
889        usize::try_from(cur - self.size64).unwrap()
890    }
891
892    /// Returns ABI information for a structure which contains `count` flags.
893    pub const fn flags(count: usize) -> CanonicalAbiInfo {
894        let (size, align, flat_count) = match FlagsSize::from_count(count) {
895            FlagsSize::Size0 => (0, 1, 0),
896            FlagsSize::Size1 => (1, 1, 1),
897            FlagsSize::Size2 => (2, 2, 1),
898            FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
899        };
900        CanonicalAbiInfo {
901            size32: size,
902            align32: align,
903            size64: size,
904            align64: align,
905            flat_count: Some(flat_count),
906        }
907    }
908
909    fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
910    where
911        I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
912        I::IntoIter: ExactSizeIterator,
913    {
914        // NB: this is basically a duplicate definition of
915        // `CanonicalAbiInfo::variant_static`, these should be kept in sync.
916
917        let cases = cases.into_iter();
918        let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
919        let mut max_size32 = 0;
920        let mut max_align32 = discrim_size;
921        let mut max_size64 = 0;
922        let mut max_align64 = discrim_size;
923        let mut max_case_count = Some(0);
924        for case in cases {
925            if let Some(case) = case {
926                max_size32 = max_size32.max(case.size32);
927                max_align32 = max_align32.max(case.align32);
928                max_size64 = max_size64.max(case.size64);
929                max_align64 = max_align64.max(case.align64);
930                max_case_count = max_flat(max_case_count, case.flat_count);
931            }
932        }
933        CanonicalAbiInfo {
934            size32: align_to(
935                align_to(discrim_size, max_align32) + max_size32,
936                max_align32,
937            ),
938            align32: max_align32,
939            size64: align_to(
940                align_to(discrim_size, max_align64) + max_size64,
941                max_align64,
942            ),
943            align64: max_align64,
944            flat_count: add_flat(max_case_count, Some(1)),
945        }
946    }
947
948    /// Same as `CanonicalAbiInfo::variant` but `const`-safe
949    pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
950        // NB: this is basically a duplicate definition of
951        // `CanonicalAbiInfo::variant`, these should be kept in sync.
952
953        let discrim_size = match DiscriminantSize::from_count(cases.len()) {
954            Some(size) => size.byte_size(),
955            None => unreachable!(),
956        };
957        let mut max_size32 = 0;
958        let mut max_align32 = discrim_size;
959        let mut max_size64 = 0;
960        let mut max_align64 = discrim_size;
961        let mut max_case_count = Some(0);
962        let mut i = 0;
963        while i < cases.len() {
964            let case = &cases[i];
965            if let Some(case) = case {
966                max_size32 = max(max_size32, case.size32);
967                max_align32 = max(max_align32, case.align32);
968                max_size64 = max(max_size64, case.size64);
969                max_align64 = max(max_align64, case.align64);
970                max_case_count = max_flat(max_case_count, case.flat_count);
971            }
972            i += 1;
973        }
974        CanonicalAbiInfo {
975            size32: align_to(
976                align_to(discrim_size, max_align32) + max_size32,
977                max_align32,
978            ),
979            align32: max_align32,
980            size64: align_to(
981                align_to(discrim_size, max_align64) + max_size64,
982                max_align64,
983            ),
984            align64: max_align64,
985            flat_count: add_flat(max_case_count, Some(1)),
986        }
987    }
988
989    /// Calculates ABI information for an enum with `cases` cases.
990    pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
991        // NB: this is basically a duplicate definition of
992        // `CanonicalAbiInfo::variant`, these should be kept in sync.
993
994        let discrim_size = match DiscriminantSize::from_count(cases) {
995            Some(size) => size.byte_size(),
996            None => unreachable!(),
997        };
998        CanonicalAbiInfo {
999            size32: discrim_size,
1000            align32: discrim_size,
1001            size64: discrim_size,
1002            align64: discrim_size,
1003            flat_count: Some(1),
1004        }
1005    }
1006
1007    /// Returns the flat count of this ABI information so long as the count
1008    /// doesn't exceed the `max` specified.
1009    pub fn flat_count(&self, max: usize) -> Option<usize> {
1010        let flat = usize::from(self.flat_count?);
1011        if flat > max { None } else { Some(flat) }
1012    }
1013}
1014
1015/// ABI information about the representation of a variant.
1016#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1017pub struct VariantInfo {
1018    /// The size of the discriminant used.
1019    #[serde(with = "serde_discrim_size")]
1020    pub size: DiscriminantSize,
1021    /// The offset of the payload from the start of the variant in 32-bit
1022    /// memories.
1023    pub payload_offset32: u32,
1024    /// The offset of the payload from the start of the variant in 64-bit
1025    /// memories.
1026    pub payload_offset64: u32,
1027}
1028
1029impl VariantInfo {
1030    /// Returns the abi information for a variant represented by the specified
1031    /// cases.
1032    pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
1033    where
1034        I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
1035        I::IntoIter: ExactSizeIterator,
1036    {
1037        let cases = cases.into_iter();
1038        let size = DiscriminantSize::from_count(cases.len()).unwrap();
1039        let abi = CanonicalAbiInfo::variant(cases);
1040        (
1041            VariantInfo {
1042                size,
1043                payload_offset32: align_to(u32::from(size), abi.align32),
1044                payload_offset64: align_to(u32::from(size), abi.align64),
1045            },
1046            abi,
1047        )
1048    }
1049    /// TODO
1050    pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
1051        let size = match DiscriminantSize::from_count(cases.len()) {
1052            Some(size) => size,
1053            None => unreachable!(),
1054        };
1055        let abi = CanonicalAbiInfo::variant_static(cases);
1056        VariantInfo {
1057            size,
1058            payload_offset32: align_to(size.byte_size(), abi.align32),
1059            payload_offset64: align_to(size.byte_size(), abi.align64),
1060        }
1061    }
1062}
1063
1064mod serde_discrim_size {
1065    use super::DiscriminantSize;
1066    use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
1067
1068    pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
1069    where
1070        S: Serializer,
1071    {
1072        u32::from(*disc).serialize(ser)
1073    }
1074
1075    pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
1076    where
1077        D: Deserializer<'de>,
1078    {
1079        match u32::deserialize(deser)? {
1080            1 => Ok(DiscriminantSize::Size1),
1081            2 => Ok(DiscriminantSize::Size2),
1082            4 => Ok(DiscriminantSize::Size4),
1083            _ => Err(D::Error::custom("invalid discriminant size")),
1084        }
1085    }
1086}
1087
1088/// Shape of a "record" type in interface types.
1089///
1090/// This is equivalent to a `struct` in Rust.
1091#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
1092pub struct TypeRecord {
1093    /// The fields that are contained within this struct type.
1094    pub fields: TryVec<RecordField>,
1095    /// Byte information about this type in the canonical ABI.
1096    pub abi: CanonicalAbiInfo,
1097}
1098
1099impl TryClone for TypeRecord {
1100    fn try_clone(&self) -> Result<Self, OutOfMemory> {
1101        Ok(TypeRecord {
1102            fields: self.fields.try_clone()?,
1103            abi: self.abi.clone(),
1104        })
1105    }
1106}
1107
1108/// One field within a record.
1109#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
1110pub struct RecordField {
1111    /// The name of the field, unique amongst all fields in a record.
1112    pub name: TryString,
1113    /// The type that this field contains.
1114    pub ty: InterfaceType,
1115}
1116
1117impl TryClone for RecordField {
1118    fn try_clone(&self) -> Result<Self, OutOfMemory> {
1119        Ok(RecordField {
1120            name: self.name.try_clone()?,
1121            ty: self.ty,
1122        })
1123    }
1124}
1125
1126/// Shape of a "variant" type in interface types.
1127///
1128/// Variants are close to Rust `enum` declarations where a value is one of many
1129/// cases and each case has a unique name and an optional payload associated
1130/// with it.
1131#[derive(Serialize, Deserialize, Debug)]
1132pub struct TypeVariant {
1133    /// The list of cases that this variant can take.
1134    pub cases: TryIndexMap<TryString, Option<InterfaceType>>,
1135    /// Byte information about this type in the canonical ABI.
1136    pub abi: CanonicalAbiInfo,
1137    /// Byte information about this variant type.
1138    pub info: VariantInfo,
1139}
1140
1141// NB: the order of `cases` matter, so this `PartialEq` disagrees with
1142// `IndexMap`'s implementation.
1143impl PartialEq for TypeVariant {
1144    fn eq(&self, other: &TypeVariant) -> bool {
1145        let TypeVariant { cases, abi, info } = self;
1146        cases.len() == other.cases.len()
1147            && cases.iter().eq(other.cases.iter())
1148            && *abi == other.abi
1149            && *info == other.info
1150    }
1151}
1152
1153impl Eq for TypeVariant {}
1154
1155impl TryClone for TypeVariant {
1156    fn try_clone(&self) -> Result<Self, OutOfMemory> {
1157        Ok(TypeVariant {
1158            cases: self.cases.try_clone()?,
1159            abi: self.abi.clone(),
1160            info: self.info.clone(),
1161        })
1162    }
1163}
1164
1165impl Hash for TypeVariant {
1166    fn hash<H: Hasher>(&self, h: &mut H) {
1167        let TypeVariant { cases, abi, info } = self;
1168        cases.len().hash(h);
1169        for pair in cases {
1170            pair.hash(h);
1171        }
1172        abi.hash(h);
1173        info.hash(h);
1174    }
1175}
1176
1177/// Shape of a "tuple" type in interface types.
1178///
1179/// This is largely the same as a tuple in Rust, basically a record with
1180/// unnamed fields.
1181#[derive(Serialize, Deserialize, Hash, Eq, PartialEq, Debug)]
1182pub struct TypeTuple {
1183    /// The types that are contained within this tuple.
1184    pub types: TryVec<InterfaceType>,
1185    /// Byte information about this type in the canonical ABI.
1186    pub abi: CanonicalAbiInfo,
1187}
1188
1189impl TryClone for TypeTuple {
1190    fn try_clone(&self) -> Result<Self, OutOfMemory> {
1191        Ok(TypeTuple {
1192            types: self.types.try_clone()?,
1193            abi: self.abi.clone(),
1194        })
1195    }
1196}
1197
1198/// Shape of a "flags" type in interface types.
1199///
1200/// This can be thought of as a record-of-bools, although the representation is
1201/// more efficient as bitflags.
1202#[derive(Serialize, Deserialize, Debug)]
1203pub struct TypeFlags {
1204    /// The names of all flags, all of which are unique.
1205    pub names: TryIndexSet<TryString>,
1206    /// Byte information about this type in the canonical ABI.
1207    pub abi: CanonicalAbiInfo,
1208}
1209
1210// NB: the order of `names` matter, so this `PartialEq` disagrees with
1211// `IndexMap`'s implementation.
1212impl PartialEq for TypeFlags {
1213    fn eq(&self, other: &TypeFlags) -> bool {
1214        let TypeFlags { names, abi } = self;
1215        names.len() == other.names.len() && names.iter().eq(other.names.iter()) && *abi == other.abi
1216    }
1217}
1218
1219impl Eq for TypeFlags {}
1220
1221impl TryClone for TypeFlags {
1222    fn try_clone(&self) -> Result<Self, OutOfMemory> {
1223        Ok(TypeFlags {
1224            names: self.names.try_clone()?,
1225            abi: self.abi.clone(),
1226        })
1227    }
1228}
1229
1230impl Hash for TypeFlags {
1231    fn hash<H: Hasher>(&self, h: &mut H) {
1232        let TypeFlags { names, abi } = self;
1233        names.len().hash(h);
1234        for name in names {
1235            name.hash(h);
1236        }
1237        abi.hash(h);
1238    }
1239}
1240
1241/// Shape of an "enum" type in interface types, not to be confused with a Rust
1242/// `enum` type.
1243///
1244/// In interface types enums are simply a bag of names, and can be seen as a
1245/// variant where all payloads are `Unit`.
1246#[derive(Serialize, Deserialize, Debug)]
1247pub struct TypeEnum {
1248    /// The names of this enum, all of which are unique.
1249    pub names: TryIndexSet<TryString>,
1250    /// Byte information about this type in the canonical ABI.
1251    pub abi: CanonicalAbiInfo,
1252    /// Byte information about this variant type.
1253    pub info: VariantInfo,
1254}
1255
1256// NB: the order of `names` matter, so this `PartialEq` disagrees with
1257// `IndexMap`'s implementation.
1258impl PartialEq for TypeEnum {
1259    fn eq(&self, other: &TypeEnum) -> bool {
1260        let TypeEnum { names, abi, info } = self;
1261        names.len() == other.names.len()
1262            && names.iter().eq(other.names.iter())
1263            && *abi == other.abi
1264            && *info == other.info
1265    }
1266}
1267
1268impl Eq for TypeEnum {}
1269
1270impl TryClone for TypeEnum {
1271    fn try_clone(&self) -> Result<Self, OutOfMemory> {
1272        Ok(TypeEnum {
1273            names: self.names.try_clone()?,
1274            abi: self.abi.clone(),
1275            info: self.info.clone(),
1276        })
1277    }
1278}
1279
1280impl Hash for TypeEnum {
1281    fn hash<H: Hasher>(&self, h: &mut H) {
1282        let TypeEnum { names, abi, info } = self;
1283        names.len().hash(h);
1284        for name in names {
1285            name.hash(h);
1286        }
1287        abi.hash(h);
1288        info.hash(h);
1289    }
1290}
1291
1292/// Shape of an "option" interface type.
1293#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1294pub struct TypeOption {
1295    /// The `T` in `Result<T, E>`
1296    pub ty: InterfaceType,
1297    /// Byte information about this type in the canonical ABI.
1298    pub abi: CanonicalAbiInfo,
1299    /// Byte information about this variant type.
1300    pub info: VariantInfo,
1301}
1302
1303/// Shape of a "result" interface type.
1304#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1305pub struct TypeResult {
1306    /// The `T` in `Result<T, E>`
1307    pub ok: Option<InterfaceType>,
1308    /// The `E` in `Result<T, E>`
1309    pub err: Option<InterfaceType>,
1310    /// Byte information about this type in the canonical ABI.
1311    pub abi: CanonicalAbiInfo,
1312    /// Byte information about this variant type.
1313    pub info: VariantInfo,
1314}
1315
1316/// Shape of a "future" interface type.
1317#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1318pub struct TypeFuture {
1319    /// The `T` in `future<T>`
1320    pub payload: Option<InterfaceType>,
1321}
1322
1323/// Metadata about a future table added to a component.
1324#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1325pub struct TypeFutureTable {
1326    /// The specific future type this table is used for.
1327    pub ty: TypeFutureIndex,
1328    /// The specific component instance this table is used for.
1329    pub instance: RuntimeComponentInstanceIndex,
1330}
1331
1332/// Shape of a "stream" interface type.
1333#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1334pub struct TypeStream {
1335    /// The `T` in `stream<T>`
1336    pub payload: Option<InterfaceType>,
1337}
1338
1339/// Metadata about a stream table added to a component.
1340#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1341pub struct TypeStreamTable {
1342    /// The specific stream type this table is used for.
1343    pub ty: TypeStreamIndex,
1344    /// The specific component instance this table is used for.
1345    pub instance: RuntimeComponentInstanceIndex,
1346}
1347
1348/// Metadata about a error context table added to a component.
1349#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1350pub struct TypeErrorContextTable {
1351    /// The specific component instance this table is used for.
1352    pub instance: RuntimeComponentInstanceIndex,
1353}
1354
1355/// Metadata about a resource table added to a component.
1356#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1357pub enum TypeResourceTable {
1358    /// This resource is for an actual concrete resource which has runtime state
1359    /// associated with it.
1360    ///
1361    /// This is used for any resource which might actually enter a component.
1362    /// For example when a resource is either imported or defined in a component
1363    /// it'll get this case.
1364    Concrete {
1365        /// The original resource that this table contains.
1366        ///
1367        /// This is used when destroying resources within this table since this
1368        /// original definition will know how to execute destructors.
1369        ty: ResourceIndex,
1370
1371        /// The component instance that contains this resource table.
1372        instance: RuntimeComponentInstanceIndex,
1373    },
1374
1375    /// This table does not actually exist at runtime but instead represents
1376    /// type information for an uninstantiable resource. This tracks, for
1377    /// example, resources in component and instance types.
1378    Abstract(AbstractResourceIndex),
1379}
1380
1381impl TypeResourceTable {
1382    /// Asserts that this is `TypeResourceTable::Concrete` and returns the `ty`
1383    /// field.
1384    ///
1385    /// # Panics
1386    ///
1387    /// Panics if this is `TypeResourceTable::Abstract`.
1388    pub fn unwrap_concrete_ty(&self) -> ResourceIndex {
1389        match self {
1390            TypeResourceTable::Concrete { ty, .. } => *ty,
1391            TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1392        }
1393    }
1394
1395    /// Asserts that this is `TypeResourceTable::Concrete` and returns the
1396    /// `instance` field.
1397    ///
1398    /// # Panics
1399    ///
1400    /// Panics if this is `TypeResourceTable::Abstract`.
1401    pub fn unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex {
1402        match self {
1403            TypeResourceTable::Concrete { instance, .. } => *instance,
1404            TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1405        }
1406    }
1407}
1408
1409/// Shape of a "list" interface type.
1410#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1411pub struct TypeList {
1412    /// The element type of the list.
1413    pub element: InterfaceType,
1414}
1415
1416/// Shape of a "map" interface type.
1417#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1418pub struct TypeMap {
1419    /// The key type of the map.
1420    pub key: InterfaceType,
1421    /// The value type of the map.
1422    pub value: InterfaceType,
1423    /// Byte information for each map entry represented as `tuple<key, value>`.
1424    pub entry_abi: CanonicalAbiInfo,
1425    /// Offset in bytes from the start of the entry tuple to the value field in
1426    /// memory32.
1427    pub value_offset32: u32,
1428    /// Offset in bytes from the start of the entry tuple to the value field in
1429    /// memory64.
1430    pub value_offset64: u32,
1431}
1432
1433/// Shape of a "fixed size list" interface type.
1434#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1435pub struct TypeFixedLengthList {
1436    /// The element type of the list.
1437    pub element: InterfaceType,
1438    /// The fixed length of the list.
1439    pub size: u32,
1440    /// Byte information about this type in the canonical ABI.
1441    pub abi: CanonicalAbiInfo,
1442}
1443
1444macro_rules! impl_try_clone_via_clone {
1445    ($($ty:ty),* $(,)?) => {$(
1446        impl TryClone for $ty {
1447            fn try_clone(&self) -> Result<Self, OutOfMemory> {
1448                Ok(self.clone())
1449            }
1450        }
1451    )*};
1452}
1453
1454// These types don't contain any heap allocations, so cloning them can't fail.
1455impl_try_clone_via_clone! {
1456    TypeOption,
1457    TypeResult,
1458    TypeFuture,
1459    TypeFutureTable,
1460    TypeStream,
1461    TypeStreamTable,
1462    TypeErrorContextTable,
1463    TypeResourceTable,
1464    TypeList,
1465    TypeMap,
1466    TypeFixedLengthList,
1467}
1468
1469/// Maximum number of flat types, for either params or results.
1470pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1471    MAX_FLAT_PARAMS
1472} else {
1473    MAX_FLAT_RESULTS
1474};
1475
1476const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1477    const MAX: u8 = MAX_FLAT_TYPES as u8;
1478    let sum = match (a, b) {
1479        (Some(a), Some(b)) => match a.checked_add(b) {
1480            Some(c) => c,
1481            None => return None,
1482        },
1483        _ => return None,
1484    };
1485    if sum > MAX { None } else { Some(sum) }
1486}
1487
1488const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1489    match (a, b) {
1490        (Some(a), Some(b)) => {
1491            if a > b {
1492                Some(a)
1493            } else {
1494                Some(b)
1495            }
1496        }
1497        _ => None,
1498    }
1499}
1500
1501/// Flat representation of a type in just core wasm types.
1502pub struct FlatTypes<'a> {
1503    /// The flat representation of this type in 32-bit memories.
1504    pub memory32: &'a [FlatType],
1505    /// The flat representation of this type in 64-bit memories.
1506    pub memory64: &'a [FlatType],
1507}
1508
1509impl FlatTypes<'_> {
1510    /// Returns the number of flat types used to represent this type.
1511    ///
1512    /// Note that this length is the same regardless to the size of memory.
1513    pub fn len(&self) -> usize {
1514        assert_eq!(self.memory32.len(), self.memory64.len());
1515        self.memory32.len()
1516    }
1517}
1518
1519// Note that this is intentionally duplicated here to keep the size to 1 byte
1520// regardless to changes in the core wasm type system since this will only
1521// ever use integers/floats for the foreseeable future.
1522#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1523#[expect(missing_docs, reason = "self-describing variants")]
1524pub enum FlatType {
1525    I32,
1526    I64,
1527    F32,
1528    F64,
1529}
1530
1531#[cfg(test)]
1532mod tests {
1533    use super::*;
1534
1535    fn variant(cases: &[(&str, InterfaceType)]) -> TypeVariant {
1536        TypeVariant {
1537            cases: cases
1538                .iter()
1539                .map(|(name, ty)| Ok((TryString::try_from(*name)?, Some(*ty))))
1540                .try_collect::<_, OutOfMemory>()
1541                .panic_on_oom(),
1542            abi: CanonicalAbiInfo::default(),
1543            info: VariantInfo {
1544                size: DiscriminantSize::Size1,
1545                payload_offset32: 4,
1546                payload_offset64: 8,
1547            },
1548        }
1549    }
1550
1551    fn flags(names: &[&str]) -> TypeFlags {
1552        TypeFlags {
1553            names: names
1554                .iter()
1555                .map(|n| TryString::try_from(*n))
1556                .try_collect::<_, OutOfMemory>()
1557                .panic_on_oom(),
1558            abi: CanonicalAbiInfo::default(),
1559        }
1560    }
1561
1562    fn enum_(names: &[&str]) -> TypeEnum {
1563        TypeEnum {
1564            names: names
1565                .iter()
1566                .map(|n| TryString::try_from(*n))
1567                .try_collect::<_, OutOfMemory>()
1568                .panic_on_oom(),
1569            abi: CanonicalAbiInfo::default(),
1570            info: VariantInfo {
1571                size: DiscriminantSize::Size1,
1572                payload_offset32: 4,
1573                payload_offset64: 8,
1574            },
1575        }
1576    }
1577
1578    #[test]
1579    fn variant_case_order_is_significant() {
1580        let a = variant(&[("n", InterfaceType::U32), ("s", InterfaceType::String)]);
1581        let b = variant(&[("s", InterfaceType::String), ("n", InterfaceType::U32)]);
1582        assert_ne!(a, b);
1583        assert_eq!(a, a.clone_panic_on_oom());
1584    }
1585
1586    #[test]
1587    fn flags_name_order_is_significant() {
1588        let a = flags(&["a", "b", "c"]);
1589        let b = flags(&["c", "b", "a"]);
1590
1591        assert_ne!(a, b);
1592        assert_eq!(a, a.clone_panic_on_oom());
1593    }
1594
1595    #[test]
1596    fn enum_name_order_is_significant() {
1597        let a = enum_(&["red", "green", "blue"]);
1598        let b = enum_(&["blue", "green", "red"]);
1599
1600        assert_ne!(a, b);
1601        assert_eq!(a, a.clone_panic_on_oom());
1602    }
1603}