Skip to main content

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