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, 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
1066// NB: the order of `cases` matter, so this `PartialEq` disagrees with
1067// `IndexMap`'s implementation.
1068impl PartialEq for TypeVariant {
1069    fn eq(&self, other: &TypeVariant) -> bool {
1070        let TypeVariant { cases, abi, info } = self;
1071        cases.len() == other.cases.len()
1072            && cases.iter().eq(other.cases.iter())
1073            && *abi == other.abi
1074            && *info == other.info
1075    }
1076}
1077
1078impl Eq for TypeVariant {}
1079
1080impl Hash for TypeVariant {
1081    fn hash<H: Hasher>(&self, h: &mut H) {
1082        let TypeVariant { cases, abi, info } = self;
1083        cases.len().hash(h);
1084        for pair in cases {
1085            pair.hash(h);
1086        }
1087        abi.hash(h);
1088        info.hash(h);
1089    }
1090}
1091
1092/// Shape of a "tuple" type in interface types.
1093///
1094/// This is largely the same as a tuple in Rust, basically a record with
1095/// unnamed fields.
1096#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1097pub struct TypeTuple {
1098    /// The types that are contained within this tuple.
1099    pub types: Box<[InterfaceType]>,
1100    /// Byte information about this type in the canonical ABI.
1101    pub abi: CanonicalAbiInfo,
1102}
1103
1104/// Shape of a "flags" type in interface types.
1105///
1106/// This can be thought of as a record-of-bools, although the representation is
1107/// more efficient as bitflags.
1108#[derive(Serialize, Deserialize, Clone, Debug)]
1109pub struct TypeFlags {
1110    /// The names of all flags, all of which are unique.
1111    pub names: IndexSet<String>,
1112    /// Byte information about this type in the canonical ABI.
1113    pub abi: CanonicalAbiInfo,
1114}
1115
1116// NB: the order of `names` matter, so this `PartialEq` disagrees with
1117// `IndexMap`'s implementation.
1118impl PartialEq for TypeFlags {
1119    fn eq(&self, other: &TypeFlags) -> bool {
1120        let TypeFlags { names, abi } = self;
1121        names.len() == other.names.len() && names.iter().eq(other.names.iter()) && *abi == other.abi
1122    }
1123}
1124
1125impl Eq for TypeFlags {}
1126
1127impl Hash for TypeFlags {
1128    fn hash<H: Hasher>(&self, h: &mut H) {
1129        let TypeFlags { names, abi } = self;
1130        names.len().hash(h);
1131        for name in names {
1132            name.hash(h);
1133        }
1134        abi.hash(h);
1135    }
1136}
1137
1138/// Shape of an "enum" type in interface types, not to be confused with a Rust
1139/// `enum` type.
1140///
1141/// In interface types enums are simply a bag of names, and can be seen as a
1142/// variant where all payloads are `Unit`.
1143#[derive(Serialize, Deserialize, Clone, Debug)]
1144pub struct TypeEnum {
1145    /// The names of this enum, all of which are unique.
1146    pub names: IndexSet<String>,
1147    /// Byte information about this type in the canonical ABI.
1148    pub abi: CanonicalAbiInfo,
1149    /// Byte information about this variant type.
1150    pub info: VariantInfo,
1151}
1152
1153// NB: the order of `names` matter, so this `PartialEq` disagrees with
1154// `IndexMap`'s implementation.
1155impl PartialEq for TypeEnum {
1156    fn eq(&self, other: &TypeEnum) -> bool {
1157        let TypeEnum { names, abi, info } = self;
1158        names.len() == other.names.len()
1159            && names.iter().eq(other.names.iter())
1160            && *abi == other.abi
1161            && *info == other.info
1162    }
1163}
1164
1165impl Eq for TypeEnum {}
1166
1167impl Hash for TypeEnum {
1168    fn hash<H: Hasher>(&self, h: &mut H) {
1169        let TypeEnum { names, abi, info } = self;
1170        names.len().hash(h);
1171        for name in names {
1172            name.hash(h);
1173        }
1174        abi.hash(h);
1175        info.hash(h);
1176    }
1177}
1178
1179/// Shape of an "option" interface type.
1180#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1181pub struct TypeOption {
1182    /// The `T` in `Result<T, E>`
1183    pub ty: InterfaceType,
1184    /// Byte information about this type in the canonical ABI.
1185    pub abi: CanonicalAbiInfo,
1186    /// Byte information about this variant type.
1187    pub info: VariantInfo,
1188}
1189
1190/// Shape of a "result" interface type.
1191#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1192pub struct TypeResult {
1193    /// The `T` in `Result<T, E>`
1194    pub ok: Option<InterfaceType>,
1195    /// The `E` in `Result<T, E>`
1196    pub err: Option<InterfaceType>,
1197    /// Byte information about this type in the canonical ABI.
1198    pub abi: CanonicalAbiInfo,
1199    /// Byte information about this variant type.
1200    pub info: VariantInfo,
1201}
1202
1203/// Shape of a "future" interface type.
1204#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1205pub struct TypeFuture {
1206    /// The `T` in `future<T>`
1207    pub payload: Option<InterfaceType>,
1208}
1209
1210/// Metadata about a future table added to a component.
1211#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1212pub struct TypeFutureTable {
1213    /// The specific future type this table is used for.
1214    pub ty: TypeFutureIndex,
1215    /// The specific component instance this table is used for.
1216    pub instance: RuntimeComponentInstanceIndex,
1217}
1218
1219/// Shape of a "stream" interface type.
1220#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1221pub struct TypeStream {
1222    /// The `T` in `stream<T>`
1223    pub payload: Option<InterfaceType>,
1224}
1225
1226/// Metadata about a stream table added to a component.
1227#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1228pub struct TypeStreamTable {
1229    /// The specific stream type this table is used for.
1230    pub ty: TypeStreamIndex,
1231    /// The specific component instance this table is used for.
1232    pub instance: RuntimeComponentInstanceIndex,
1233}
1234
1235/// Metadata about a error context table added to a component.
1236#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1237pub struct TypeErrorContextTable {
1238    /// The specific component instance this table is used for.
1239    pub instance: RuntimeComponentInstanceIndex,
1240}
1241
1242/// Metadata about a resource table added to a component.
1243#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1244pub enum TypeResourceTable {
1245    /// This resource is for an actual concrete resource which has runtime state
1246    /// associated with it.
1247    ///
1248    /// This is used for any resource which might actually enter a component.
1249    /// For example when a resource is either imported or defined in a component
1250    /// it'll get this case.
1251    Concrete {
1252        /// The original resource that this table contains.
1253        ///
1254        /// This is used when destroying resources within this table since this
1255        /// original definition will know how to execute destructors.
1256        ty: ResourceIndex,
1257
1258        /// The component instance that contains this resource table.
1259        instance: RuntimeComponentInstanceIndex,
1260    },
1261
1262    /// This table does not actually exist at runtime but instead represents
1263    /// type information for an uninstantiable resource. This tracks, for
1264    /// example, resources in component and instance types.
1265    Abstract(AbstractResourceIndex),
1266}
1267
1268impl TypeResourceTable {
1269    /// Asserts that this is `TypeResourceTable::Concrete` and returns the `ty`
1270    /// field.
1271    ///
1272    /// # Panics
1273    ///
1274    /// Panics if this is `TypeResourceTable::Abstract`.
1275    pub fn unwrap_concrete_ty(&self) -> ResourceIndex {
1276        match self {
1277            TypeResourceTable::Concrete { ty, .. } => *ty,
1278            TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1279        }
1280    }
1281
1282    /// Asserts that this is `TypeResourceTable::Concrete` and returns the
1283    /// `instance` field.
1284    ///
1285    /// # Panics
1286    ///
1287    /// Panics if this is `TypeResourceTable::Abstract`.
1288    pub fn unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex {
1289        match self {
1290            TypeResourceTable::Concrete { instance, .. } => *instance,
1291            TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1292        }
1293    }
1294}
1295
1296/// Shape of a "list" interface type.
1297#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1298pub struct TypeList {
1299    /// The element type of the list.
1300    pub element: InterfaceType,
1301}
1302
1303/// Shape of a "map" interface type.
1304#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1305pub struct TypeMap {
1306    /// The key type of the map.
1307    pub key: InterfaceType,
1308    /// The value type of the map.
1309    pub value: InterfaceType,
1310    /// Byte information for each map entry represented as `tuple<key, value>`.
1311    pub entry_abi: CanonicalAbiInfo,
1312    /// Offset in bytes from the start of the entry tuple to the value field in
1313    /// memory32.
1314    pub value_offset32: u32,
1315    /// Offset in bytes from the start of the entry tuple to the value field in
1316    /// memory64.
1317    pub value_offset64: u32,
1318}
1319
1320/// Shape of a "fixed size list" interface type.
1321#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1322pub struct TypeFixedLengthList {
1323    /// The element type of the list.
1324    pub element: InterfaceType,
1325    /// The fixed length of the list.
1326    pub size: u32,
1327    /// Byte information about this type in the canonical ABI.
1328    pub abi: CanonicalAbiInfo,
1329}
1330
1331/// Maximum number of flat types, for either params or results.
1332pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1333    MAX_FLAT_PARAMS
1334} else {
1335    MAX_FLAT_RESULTS
1336};
1337
1338const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1339    const MAX: u8 = MAX_FLAT_TYPES as u8;
1340    let sum = match (a, b) {
1341        (Some(a), Some(b)) => match a.checked_add(b) {
1342            Some(c) => c,
1343            None => return None,
1344        },
1345        _ => return None,
1346    };
1347    if sum > MAX { None } else { Some(sum) }
1348}
1349
1350const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1351    match (a, b) {
1352        (Some(a), Some(b)) => {
1353            if a > b {
1354                Some(a)
1355            } else {
1356                Some(b)
1357            }
1358        }
1359        _ => None,
1360    }
1361}
1362
1363/// Flat representation of a type in just core wasm types.
1364pub struct FlatTypes<'a> {
1365    /// The flat representation of this type in 32-bit memories.
1366    pub memory32: &'a [FlatType],
1367    /// The flat representation of this type in 64-bit memories.
1368    pub memory64: &'a [FlatType],
1369}
1370
1371impl FlatTypes<'_> {
1372    /// Returns the number of flat types used to represent this type.
1373    ///
1374    /// Note that this length is the same regardless to the size of memory.
1375    pub fn len(&self) -> usize {
1376        assert_eq!(self.memory32.len(), self.memory64.len());
1377        self.memory32.len()
1378    }
1379}
1380
1381// Note that this is intentionally duplicated here to keep the size to 1 byte
1382// regardless to changes in the core wasm type system since this will only
1383// ever use integers/floats for the foreseeable future.
1384#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1385#[expect(missing_docs, reason = "self-describing variants")]
1386pub enum FlatType {
1387    I32,
1388    I64,
1389    F32,
1390    F64,
1391}
1392
1393#[cfg(test)]
1394mod tests {
1395    use super::*;
1396
1397    fn variant(cases: &[(&str, InterfaceType)]) -> TypeVariant {
1398        TypeVariant {
1399            cases: cases
1400                .iter()
1401                .map(|(name, ty)| (name.to_string(), Some(*ty)))
1402                .collect(),
1403            abi: CanonicalAbiInfo::default(),
1404            info: VariantInfo {
1405                size: DiscriminantSize::Size1,
1406                payload_offset32: 4,
1407                payload_offset64: 8,
1408            },
1409        }
1410    }
1411
1412    fn flags(names: &[&str]) -> TypeFlags {
1413        TypeFlags {
1414            names: names.iter().map(|n| n.to_string()).collect(),
1415            abi: CanonicalAbiInfo::default(),
1416        }
1417    }
1418
1419    fn enum_(names: &[&str]) -> TypeEnum {
1420        TypeEnum {
1421            names: names.iter().map(|n| n.to_string()).collect(),
1422            abi: CanonicalAbiInfo::default(),
1423            info: VariantInfo {
1424                size: DiscriminantSize::Size1,
1425                payload_offset32: 4,
1426                payload_offset64: 8,
1427            },
1428        }
1429    }
1430
1431    #[test]
1432    fn variant_case_order_is_significant() {
1433        let a = variant(&[("n", InterfaceType::U32), ("s", InterfaceType::String)]);
1434        let b = variant(&[("s", InterfaceType::String), ("n", InterfaceType::U32)]);
1435        assert_ne!(a, b);
1436        assert_eq!(a, a.clone());
1437    }
1438
1439    #[test]
1440    fn flags_name_order_is_significant() {
1441        let a = flags(&["a", "b", "c"]);
1442        let b = flags(&["c", "b", "a"]);
1443
1444        assert_ne!(a, b);
1445        assert_eq!(a, a.clone());
1446    }
1447
1448    #[test]
1449    fn enum_name_order_is_significant() {
1450        let a = enum_(&["red", "green", "blue"]);
1451        let b = enum_(&["blue", "green", "red"]);
1452
1453        assert_ne!(a, b);
1454        assert_eq!(a, a.clone());
1455    }
1456}