wasmtime_environ/component/
types.rs

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