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