wasmtime_environ/component/
types.rs

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