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    /// Names of parameters.
554    pub param_names: Vec<String>,
555    /// Parameters to the function represented as a tuple.
556    pub params: TypeTupleIndex,
557    /// Results of the function represented as a tuple.
558    pub results: TypeTupleIndex,
559}
560
561/// All possible interface types that values can have.
562///
563/// This list represents an exhaustive listing of interface types and the
564/// shapes that they can take. Note that this enum is considered an "index" of
565/// forms where for non-primitive types a `ComponentTypes` structure is used to
566/// lookup further information based on the index found here.
567#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
568#[expect(missing_docs, reason = "self-describing variants")]
569pub enum InterfaceType {
570    Bool,
571    S8,
572    U8,
573    S16,
574    U16,
575    S32,
576    U32,
577    S64,
578    U64,
579    Float32,
580    Float64,
581    Char,
582    String,
583    Record(TypeRecordIndex),
584    Variant(TypeVariantIndex),
585    List(TypeListIndex),
586    Tuple(TypeTupleIndex),
587    Flags(TypeFlagsIndex),
588    Enum(TypeEnumIndex),
589    Option(TypeOptionIndex),
590    Result(TypeResultIndex),
591    Own(TypeResourceTableIndex),
592    Borrow(TypeResourceTableIndex),
593    Future(TypeFutureTableIndex),
594    Stream(TypeStreamTableIndex),
595    ErrorContext(TypeComponentLocalErrorContextTableIndex),
596}
597
598/// Bye information about a type in the canonical ABI, with metadata for both
599/// memory32 and memory64-based types.
600#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
601pub struct CanonicalAbiInfo {
602    /// The byte-size of this type in a 32-bit memory.
603    pub size32: u32,
604    /// The byte-alignment of this type in a 32-bit memory.
605    pub align32: u32,
606    /// The byte-size of this type in a 64-bit memory.
607    pub size64: u32,
608    /// The byte-alignment of this type in a 64-bit memory.
609    pub align64: u32,
610    /// The number of types it takes to represents this type in the "flat"
611    /// representation of the canonical abi where everything is passed as
612    /// immediate arguments or results.
613    ///
614    /// If this is `None` then this type is not representable in the flat ABI
615    /// because it is too large.
616    pub flat_count: Option<u8>,
617}
618
619impl Default for CanonicalAbiInfo {
620    fn default() -> CanonicalAbiInfo {
621        CanonicalAbiInfo {
622            size32: 0,
623            align32: 1,
624            size64: 0,
625            align64: 1,
626            flat_count: Some(0),
627        }
628    }
629}
630
631const fn align_to(a: u32, b: u32) -> u32 {
632    assert!(b.is_power_of_two());
633    (a + (b - 1)) & !(b - 1)
634}
635
636const fn max(a: u32, b: u32) -> u32 {
637    if a > b { a } else { b }
638}
639
640impl CanonicalAbiInfo {
641    /// ABI information for zero-sized types.
642    pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
643        size32: 0,
644        align32: 1,
645        size64: 0,
646        align64: 1,
647        flat_count: Some(0),
648    };
649
650    /// ABI information for one-byte scalars.
651    pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
652    /// ABI information for two-byte scalars.
653    pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
654    /// ABI information for four-byte scalars.
655    pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
656    /// ABI information for eight-byte scalars.
657    pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
658
659    const fn scalar(size: u32) -> CanonicalAbiInfo {
660        CanonicalAbiInfo {
661            size32: size,
662            align32: size,
663            size64: size,
664            align64: size,
665            flat_count: Some(1),
666        }
667    }
668
669    /// ABI information for lists/strings which are "pointer pairs"
670    pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
671        size32: 8,
672        align32: 4,
673        size64: 16,
674        align64: 8,
675        flat_count: Some(2),
676    };
677
678    /// Returns the abi for a record represented by the specified fields.
679    pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
680        // NB: this is basically a duplicate copy of
681        // `CanonicalAbiInfo::record_static` and the two should be kept in sync.
682
683        let mut ret = CanonicalAbiInfo::default();
684        for field in fields {
685            ret.size32 = align_to(ret.size32, field.align32) + field.size32;
686            ret.align32 = ret.align32.max(field.align32);
687            ret.size64 = align_to(ret.size64, field.align64) + field.size64;
688            ret.align64 = ret.align64.max(field.align64);
689            ret.flat_count = add_flat(ret.flat_count, field.flat_count);
690        }
691        ret.size32 = align_to(ret.size32, ret.align32);
692        ret.size64 = align_to(ret.size64, ret.align64);
693        return ret;
694    }
695
696    /// Same as `CanonicalAbiInfo::record` but in a `const`-friendly context.
697    pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
698        // NB: this is basically a duplicate copy of `CanonicalAbiInfo::record`
699        // and the two should be kept in sync.
700
701        let mut ret = CanonicalAbiInfo::ZERO;
702        let mut i = 0;
703        while i < fields.len() {
704            let field = &fields[i];
705            ret.size32 = align_to(ret.size32, field.align32) + field.size32;
706            ret.align32 = max(ret.align32, field.align32);
707            ret.size64 = align_to(ret.size64, field.align64) + field.size64;
708            ret.align64 = max(ret.align64, field.align64);
709            ret.flat_count = add_flat(ret.flat_count, field.flat_count);
710            i += 1;
711        }
712        ret.size32 = align_to(ret.size32, ret.align32);
713        ret.size64 = align_to(ret.size64, ret.align64);
714        return ret;
715    }
716
717    /// Returns the delta from the current value of `offset` to align properly
718    /// and read the next record field of type `abi` for 32-bit memories.
719    pub fn next_field32(&self, offset: &mut u32) -> u32 {
720        *offset = align_to(*offset, self.align32) + self.size32;
721        *offset - self.size32
722    }
723
724    /// Same as `next_field32`, but bumps a usize pointer
725    pub fn next_field32_size(&self, offset: &mut usize) -> usize {
726        let cur = u32::try_from(*offset).unwrap();
727        let cur = align_to(cur, self.align32) + self.size32;
728        *offset = usize::try_from(cur).unwrap();
729        usize::try_from(cur - self.size32).unwrap()
730    }
731
732    /// Returns the delta from the current value of `offset` to align properly
733    /// and read the next record field of type `abi` for 64-bit memories.
734    pub fn next_field64(&self, offset: &mut u32) -> u32 {
735        *offset = align_to(*offset, self.align64) + self.size64;
736        *offset - self.size64
737    }
738
739    /// Same as `next_field64`, but bumps a usize pointer
740    pub fn next_field64_size(&self, offset: &mut usize) -> usize {
741        let cur = u32::try_from(*offset).unwrap();
742        let cur = align_to(cur, self.align64) + self.size64;
743        *offset = usize::try_from(cur).unwrap();
744        usize::try_from(cur - self.size64).unwrap()
745    }
746
747    /// Returns ABI information for a structure which contains `count` flags.
748    pub const fn flags(count: usize) -> CanonicalAbiInfo {
749        let (size, align, flat_count) = match FlagsSize::from_count(count) {
750            FlagsSize::Size0 => (0, 1, 0),
751            FlagsSize::Size1 => (1, 1, 1),
752            FlagsSize::Size2 => (2, 2, 1),
753            FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
754        };
755        CanonicalAbiInfo {
756            size32: size,
757            align32: align,
758            size64: size,
759            align64: align,
760            flat_count: Some(flat_count),
761        }
762    }
763
764    fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
765    where
766        I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
767        I::IntoIter: ExactSizeIterator,
768    {
769        // NB: this is basically a duplicate definition of
770        // `CanonicalAbiInfo::variant_static`, these should be kept in sync.
771
772        let cases = cases.into_iter();
773        let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
774        let mut max_size32 = 0;
775        let mut max_align32 = discrim_size;
776        let mut max_size64 = 0;
777        let mut max_align64 = discrim_size;
778        let mut max_case_count = Some(0);
779        for case in cases {
780            if let Some(case) = case {
781                max_size32 = max_size32.max(case.size32);
782                max_align32 = max_align32.max(case.align32);
783                max_size64 = max_size64.max(case.size64);
784                max_align64 = max_align64.max(case.align64);
785                max_case_count = max_flat(max_case_count, case.flat_count);
786            }
787        }
788        CanonicalAbiInfo {
789            size32: align_to(
790                align_to(discrim_size, max_align32) + max_size32,
791                max_align32,
792            ),
793            align32: max_align32,
794            size64: align_to(
795                align_to(discrim_size, max_align64) + max_size64,
796                max_align64,
797            ),
798            align64: max_align64,
799            flat_count: add_flat(max_case_count, Some(1)),
800        }
801    }
802
803    /// Same as `CanonicalAbiInfo::variant` but `const`-safe
804    pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
805        // NB: this is basically a duplicate definition of
806        // `CanonicalAbiInfo::variant`, these should be kept in sync.
807
808        let discrim_size = match DiscriminantSize::from_count(cases.len()) {
809            Some(size) => size.byte_size(),
810            None => unreachable!(),
811        };
812        let mut max_size32 = 0;
813        let mut max_align32 = discrim_size;
814        let mut max_size64 = 0;
815        let mut max_align64 = discrim_size;
816        let mut max_case_count = Some(0);
817        let mut i = 0;
818        while i < cases.len() {
819            let case = &cases[i];
820            if let Some(case) = case {
821                max_size32 = max(max_size32, case.size32);
822                max_align32 = max(max_align32, case.align32);
823                max_size64 = max(max_size64, case.size64);
824                max_align64 = max(max_align64, case.align64);
825                max_case_count = max_flat(max_case_count, case.flat_count);
826            }
827            i += 1;
828        }
829        CanonicalAbiInfo {
830            size32: align_to(
831                align_to(discrim_size, max_align32) + max_size32,
832                max_align32,
833            ),
834            align32: max_align32,
835            size64: align_to(
836                align_to(discrim_size, max_align64) + max_size64,
837                max_align64,
838            ),
839            align64: max_align64,
840            flat_count: add_flat(max_case_count, Some(1)),
841        }
842    }
843
844    /// Calculates ABI information for an enum with `cases` cases.
845    pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
846        // NB: this is basically a duplicate definition of
847        // `CanonicalAbiInfo::variant`, these should be kept in sync.
848
849        let discrim_size = match DiscriminantSize::from_count(cases) {
850            Some(size) => size.byte_size(),
851            None => unreachable!(),
852        };
853        CanonicalAbiInfo {
854            size32: discrim_size,
855            align32: discrim_size,
856            size64: discrim_size,
857            align64: discrim_size,
858            flat_count: Some(1),
859        }
860    }
861
862    /// Returns the flat count of this ABI information so long as the count
863    /// doesn't exceed the `max` specified.
864    pub fn flat_count(&self, max: usize) -> Option<usize> {
865        let flat = usize::from(self.flat_count?);
866        if flat > max { None } else { Some(flat) }
867    }
868}
869
870/// ABI information about the representation of a variant.
871#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
872pub struct VariantInfo {
873    /// The size of the discriminant used.
874    #[serde(with = "serde_discrim_size")]
875    pub size: DiscriminantSize,
876    /// The offset of the payload from the start of the variant in 32-bit
877    /// memories.
878    pub payload_offset32: u32,
879    /// The offset of the payload from the start of the variant in 64-bit
880    /// memories.
881    pub payload_offset64: u32,
882}
883
884impl VariantInfo {
885    /// Returns the abi information for a variant represented by the specified
886    /// cases.
887    pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
888    where
889        I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
890        I::IntoIter: ExactSizeIterator,
891    {
892        let cases = cases.into_iter();
893        let size = DiscriminantSize::from_count(cases.len()).unwrap();
894        let abi = CanonicalAbiInfo::variant(cases);
895        (
896            VariantInfo {
897                size,
898                payload_offset32: align_to(u32::from(size), abi.align32),
899                payload_offset64: align_to(u32::from(size), abi.align64),
900            },
901            abi,
902        )
903    }
904    /// TODO
905    pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
906        let size = match DiscriminantSize::from_count(cases.len()) {
907            Some(size) => size,
908            None => unreachable!(),
909        };
910        let abi = CanonicalAbiInfo::variant_static(cases);
911        VariantInfo {
912            size,
913            payload_offset32: align_to(size.byte_size(), abi.align32),
914            payload_offset64: align_to(size.byte_size(), abi.align64),
915        }
916    }
917}
918
919mod serde_discrim_size {
920    use super::DiscriminantSize;
921    use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
922
923    pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
924    where
925        S: Serializer,
926    {
927        u32::from(*disc).serialize(ser)
928    }
929
930    pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
931    where
932        D: Deserializer<'de>,
933    {
934        match u32::deserialize(deser)? {
935            1 => Ok(DiscriminantSize::Size1),
936            2 => Ok(DiscriminantSize::Size2),
937            4 => Ok(DiscriminantSize::Size4),
938            _ => Err(D::Error::custom("invalid discriminant size")),
939        }
940    }
941}
942
943/// Shape of a "record" type in interface types.
944///
945/// This is equivalent to a `struct` in Rust.
946#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
947pub struct TypeRecord {
948    /// The fields that are contained within this struct type.
949    pub fields: Box<[RecordField]>,
950    /// Byte information about this type in the canonical ABI.
951    pub abi: CanonicalAbiInfo,
952}
953
954/// One field within a record.
955#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
956pub struct RecordField {
957    /// The name of the field, unique amongst all fields in a record.
958    pub name: String,
959    /// The type that this field contains.
960    pub ty: InterfaceType,
961}
962
963/// Shape of a "variant" type in interface types.
964///
965/// Variants are close to Rust `enum` declarations where a value is one of many
966/// cases and each case has a unique name and an optional payload associated
967/// with it.
968#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
969pub struct TypeVariant {
970    /// The list of cases that this variant can take.
971    pub cases: IndexMap<String, Option<InterfaceType>>,
972    /// Byte information about this type in the canonical ABI.
973    pub abi: CanonicalAbiInfo,
974    /// Byte information about this variant type.
975    pub info: VariantInfo,
976}
977
978impl Hash for TypeVariant {
979    fn hash<H: Hasher>(&self, h: &mut H) {
980        let TypeVariant { cases, abi, info } = self;
981        cases.len().hash(h);
982        for pair in cases {
983            pair.hash(h);
984        }
985        abi.hash(h);
986        info.hash(h);
987    }
988}
989
990/// Shape of a "tuple" type in interface types.
991///
992/// This is largely the same as a tuple in Rust, basically a record with
993/// unnamed fields.
994#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
995pub struct TypeTuple {
996    /// The types that are contained within this tuple.
997    pub types: Box<[InterfaceType]>,
998    /// Byte information about this type in the canonical ABI.
999    pub abi: CanonicalAbiInfo,
1000}
1001
1002/// Shape of a "flags" type in interface types.
1003///
1004/// This can be thought of as a record-of-bools, although the representation is
1005/// more efficient as bitflags.
1006#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1007pub struct TypeFlags {
1008    /// The names of all flags, all of which are unique.
1009    pub names: IndexSet<String>,
1010    /// Byte information about this type in the canonical ABI.
1011    pub abi: CanonicalAbiInfo,
1012}
1013
1014impl Hash for TypeFlags {
1015    fn hash<H: Hasher>(&self, h: &mut H) {
1016        let TypeFlags { names, abi } = self;
1017        names.len().hash(h);
1018        for name in names {
1019            name.hash(h);
1020        }
1021        abi.hash(h);
1022    }
1023}
1024
1025/// Shape of an "enum" type in interface types, not to be confused with a Rust
1026/// `enum` type.
1027///
1028/// In interface types enums are simply a bag of names, and can be seen as a
1029/// variant where all payloads are `Unit`.
1030#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1031pub struct TypeEnum {
1032    /// The names of this enum, all of which are unique.
1033    pub names: IndexSet<String>,
1034    /// Byte information about this type in the canonical ABI.
1035    pub abi: CanonicalAbiInfo,
1036    /// Byte information about this variant type.
1037    pub info: VariantInfo,
1038}
1039
1040impl Hash for TypeEnum {
1041    fn hash<H: Hasher>(&self, h: &mut H) {
1042        let TypeEnum { names, abi, info } = self;
1043        names.len().hash(h);
1044        for name in names {
1045            name.hash(h);
1046        }
1047        abi.hash(h);
1048        info.hash(h);
1049    }
1050}
1051
1052/// Shape of an "option" interface type.
1053#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1054pub struct TypeOption {
1055    /// The `T` in `Result<T, E>`
1056    pub ty: InterfaceType,
1057    /// Byte information about this type in the canonical ABI.
1058    pub abi: CanonicalAbiInfo,
1059    /// Byte information about this variant type.
1060    pub info: VariantInfo,
1061}
1062
1063/// Shape of a "result" interface type.
1064#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1065pub struct TypeResult {
1066    /// The `T` in `Result<T, E>`
1067    pub ok: Option<InterfaceType>,
1068    /// The `E` in `Result<T, E>`
1069    pub err: Option<InterfaceType>,
1070    /// Byte information about this type in the canonical ABI.
1071    pub abi: CanonicalAbiInfo,
1072    /// Byte information about this variant type.
1073    pub info: VariantInfo,
1074}
1075
1076/// Shape of a "future" interface type.
1077#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1078pub struct TypeFuture {
1079    /// The `T` in `future<T>`
1080    pub payload: Option<InterfaceType>,
1081}
1082
1083/// Metadata about a future table added to a component.
1084#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1085pub struct TypeFutureTable {
1086    /// The specific future type this table is used for.
1087    pub ty: TypeFutureIndex,
1088    /// The specific component instance this table is used for.
1089    pub instance: RuntimeComponentInstanceIndex,
1090}
1091
1092/// Shape of a "stream" interface type.
1093#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1094pub struct TypeStream {
1095    /// The `T` in `stream<T>`
1096    pub payload: Option<InterfaceType>,
1097}
1098
1099/// Metadata about a stream table added to a component.
1100#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1101pub struct TypeStreamTable {
1102    /// The specific stream type this table is used for.
1103    pub ty: TypeStreamIndex,
1104    /// The specific component instance this table is used for.
1105    pub instance: RuntimeComponentInstanceIndex,
1106}
1107
1108/// Metadata about a error context table added to a component.
1109#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1110pub struct TypeErrorContextTable {
1111    /// The specific component instance this table is used for.
1112    pub instance: RuntimeComponentInstanceIndex,
1113}
1114
1115/// Metadata about a resource table added to a component.
1116#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1117pub enum TypeResourceTable {
1118    /// This resource is for an actual concrete resource which has runtime state
1119    /// associated with it.
1120    ///
1121    /// This is used for any resource which might actually enter a component.
1122    /// For example when a resource is either imported or defined in a component
1123    /// it'll get this case.
1124    Concrete {
1125        /// The original resource that this table contains.
1126        ///
1127        /// This is used when destroying resources within this table since this
1128        /// original definition will know how to execute destructors.
1129        ty: ResourceIndex,
1130
1131        /// The component instance that contains this resource table.
1132        instance: RuntimeComponentInstanceIndex,
1133    },
1134
1135    /// This table does not actually exist at runtime but instead represents
1136    /// type information for an uninstantiable resource. This tracks, for
1137    /// example, resources in component and instance types.
1138    Abstract(AbstractResourceIndex),
1139}
1140
1141impl TypeResourceTable {
1142    /// Asserts that this is `TypeResourceTable::Concrete` and returns the `ty`
1143    /// field.
1144    ///
1145    /// # Panics
1146    ///
1147    /// Panics if this is `TypeResourceTable::Abstract`.
1148    pub fn unwrap_concrete_ty(&self) -> ResourceIndex {
1149        match self {
1150            TypeResourceTable::Concrete { ty, .. } => *ty,
1151            TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1152        }
1153    }
1154
1155    /// Asserts that this is `TypeResourceTable::Concrete` and returns the
1156    /// `instance` field.
1157    ///
1158    /// # Panics
1159    ///
1160    /// Panics if this is `TypeResourceTable::Abstract`.
1161    pub fn unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex {
1162        match self {
1163            TypeResourceTable::Concrete { instance, .. } => *instance,
1164            TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1165        }
1166    }
1167}
1168
1169/// Shape of a "list" interface type.
1170#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1171pub struct TypeList {
1172    /// The element type of the list.
1173    pub element: InterfaceType,
1174}
1175
1176/// Maximum number of flat types, for either params or results.
1177pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1178    MAX_FLAT_PARAMS
1179} else {
1180    MAX_FLAT_RESULTS
1181};
1182
1183const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1184    const MAX: u8 = MAX_FLAT_TYPES as u8;
1185    let sum = match (a, b) {
1186        (Some(a), Some(b)) => match a.checked_add(b) {
1187            Some(c) => c,
1188            None => return None,
1189        },
1190        _ => return None,
1191    };
1192    if sum > MAX { None } else { Some(sum) }
1193}
1194
1195const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1196    match (a, b) {
1197        (Some(a), Some(b)) => {
1198            if a > b {
1199                Some(a)
1200            } else {
1201                Some(b)
1202            }
1203        }
1204        _ => None,
1205    }
1206}
1207
1208/// Flat representation of a type in just core wasm types.
1209pub struct FlatTypes<'a> {
1210    /// The flat representation of this type in 32-bit memories.
1211    pub memory32: &'a [FlatType],
1212    /// The flat representation of this type in 64-bit memories.
1213    pub memory64: &'a [FlatType],
1214}
1215
1216impl FlatTypes<'_> {
1217    /// Returns the number of flat types used to represent this type.
1218    ///
1219    /// Note that this length is the same regardless to the size of memory.
1220    pub fn len(&self) -> usize {
1221        assert_eq!(self.memory32.len(), self.memory64.len());
1222        self.memory32.len()
1223    }
1224}
1225
1226// Note that this is intentionally duplicated here to keep the size to 1 byte
1227// regardless to changes in the core wasm type system since this will only
1228// ever use integers/floats for the foreseeable future.
1229#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1230#[expect(missing_docs, reason = "self-describing variants")]
1231pub enum FlatType {
1232    I32,
1233    I64,
1234    F32,
1235    F64,
1236}