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