wasmtime_environ/component/
types.rs

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