wasmtime_environ/component/
types.rs

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