Skip to main content

wasmtime_environ/component/
types.rs

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