1 use crate::component::{MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
2 use crate::{EntityType, ModuleInternedTypeIndex, ModuleTypes, PrimaryMap};
3 use crate::{TypeTrace, prelude::*};
4 use core::hash::{Hash, Hasher};
5 use core::ops::Index;
6 use serde_derive::{Deserialize, Serialize};
7 use wasmparser::component_types::ComponentAnyTypeId;
8 use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9 
10 pub use crate::StaticModuleIndex;
11 
12 macro_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 
28 indices! {
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.
262 pub 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")]
268 pub 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)]
282 pub 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 
307 impl TypeTrace for ComponentTypes {
trace<F, E>(&self, func: &mut F) -> Result<(), E> where F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,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 
trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E> where F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,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 
335 impl ComponentTypes {
336     /// Returns the core wasm module types known within this component.
module_types(&self) -> &ModuleTypes337     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.
module_types_mut(&mut self) -> &mut ModuleTypes342     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.
canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo347     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.
push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex385     pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
386         self.resource_tables.push(table)
387     }
388 }
389 
390 macro_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 
411 impl_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`)
436 impl<T> Index<T> for ComponentTypes
437 where
438     ModuleTypes: Index<T>,
439 {
440     type Output = <ModuleTypes as Index<T>>::Output;
index(&self, idx: T) -> &Self::Output441     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)]
452 pub 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 
472 impl TypeDef {
473     /// A human readable description of what kind of type definition this is.
desc(&self) -> &str474     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)]
497 pub 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 
514 impl TypeTrace for TypeModule {
trace<F, E>(&self, func: &mut F) -> Result<(), E> where F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,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 
trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E> where F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,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)]
544 pub 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)]
556 pub 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)]
563 pub 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")]
582 pub 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)]
616 pub 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 
634 impl Default for CanonicalAbiInfo {
default() -> CanonicalAbiInfo635     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 
align_to(a: u32, b: u32) -> u32646 const fn align_to(a: u32, b: u32) -> u32 {
647     assert!(b.is_power_of_two());
648     (a + (b - 1)) & !(b - 1)
649 }
650 
max(a: u32, b: u32) -> u32651 const fn max(a: u32, b: u32) -> u32 {
652     if a > b { a } else { b }
653 }
654 
655 impl 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 
scalar(size: u32) -> CanonicalAbiInfo674     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.
record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo694     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.
record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo712     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.
next_field32(&self, offset: &mut u32) -> u32734     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
next_field32_size(&self, offset: &mut usize) -> usize740     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.
next_field64(&self, offset: &mut u32) -> u32749     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
next_field64_size(&self, offset: &mut usize) -> usize755     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.
flags(count: usize) -> CanonicalAbiInfo763     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 
variant<'a, I>(cases: I) -> CanonicalAbiInfo where I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>, I::IntoIter: ExactSizeIterator,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
variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo819     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.
enum_(cases: usize) -> CanonicalAbiInfo860     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.
flat_count(&self, max: usize) -> Option<usize>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)]
887 pub 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 
899 impl VariantInfo {
900     /// Returns the abi information for a variant represented by the specified
901     /// cases.
new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo) where I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>, I::IntoIter: ExactSizeIterator,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
new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo920     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 
934 mod serde_discrim_size {
935     use super::DiscriminantSize;
936     use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
937 
serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error> where S: Serializer,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 
deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error> where D: Deserializer<'de>,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)]
962 pub 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)]
971 pub 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)]
984 pub 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 
993 impl Hash for TypeVariant {
hash<H: Hasher>(&self, h: &mut H)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)]
1010 pub 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)]
1022 pub 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 
1029 impl Hash for TypeFlags {
hash<H: Hasher>(&self, h: &mut H)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)]
1046 pub 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 
1055 impl Hash for TypeEnum {
hash<H: Hasher>(&self, h: &mut H)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)]
1069 pub 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)]
1080 pub 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)]
1093 pub 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)]
1100 pub 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)]
1109 pub 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)]
1116 pub 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)]
1125 pub 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)]
1132 pub 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 
1156 impl 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`.
unwrap_concrete_ty(&self) -> ResourceIndex1163     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`.
unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex1176     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)]
1186 pub 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)]
1193 pub 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)]
1210 pub 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.
1220 pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1221     MAX_FLAT_PARAMS
1222 } else {
1223     MAX_FLAT_RESULTS
1224 };
1225 
add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8>1226 const 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 
max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8>1238 const 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.
1252 pub 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 
1259 impl 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.
len(&self) -> usize1263     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")]
1274 pub enum FlatType {
1275     I32,
1276     I64,
1277     F32,
1278     F64,
1279 }
1280