1use crate::component::{MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
2use crate::{EntityType, ModuleInternedTypeIndex, ModuleTypes, PrimaryMap};
3use crate::{TypeTrace, prelude::*};
4use core::hash::{Hash, Hasher};
5use core::ops::Index;
6use serde_derive::{Deserialize, Serialize};
7use wasmparser::component_types::ComponentAnyTypeId;
8use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9
10pub use crate::StaticModuleIndex;
11
12macro_rules! indices {
13 ($(
14 $(#[$a:meta])*
15 pub struct $name:ident(u32);
16 )*) => ($(
17 $(#[$a])*
18 #[derive(
19 Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
20 Serialize, Deserialize,
21 )]
22 #[repr(transparent)]
23 pub struct $name(u32);
24 cranelift_entity::entity_impl!($name);
25 )*);
26}
27
28indices! {
29 pub struct ComponentTypeIndex(u32);
37
38 pub struct ModuleIndex(u32);
40
41 pub struct ComponentIndex(u32);
43
44 pub struct ModuleInstanceIndex(u32);
46
47 pub struct ComponentInstanceIndex(u32);
49
50 pub struct ComponentFuncIndex(u32);
52
53 pub struct TypeComponentIndex(u32);
61
62 pub struct TypeComponentInstanceIndex(u32);
65
66 pub struct TypeModuleIndex(u32);
69
70 pub struct TypeFuncIndex(u32);
73
74 pub struct TypeRecordIndex(u32);
76 pub struct TypeVariantIndex(u32);
78 pub struct TypeTupleIndex(u32);
80 pub struct TypeFlagsIndex(u32);
82 pub struct TypeEnumIndex(u32);
84 pub struct TypeOptionIndex(u32);
87 pub struct TypeResultIndex(u32);
90 pub struct TypeListIndex(u32);
92 pub struct TypeFixedLengthListIndex(u32);
94 pub struct TypeFutureIndex(u32);
96
97 pub struct TypeFutureTableIndex(u32);
102
103 pub struct TypeStreamIndex(u32);
105
106 pub struct TypeStreamTableIndex(u32);
111
112 pub struct TypeComponentLocalErrorContextTableIndex(u32);
117
118 pub struct TypeComponentGlobalErrorContextTableIndex(u32);
124
125 pub struct TypeResourceTableIndex(u32);
140
141 pub struct ResourceIndex(u32);
154
155 pub struct DefinedResourceIndex(u32);
161
162 pub struct ModuleUpvarIndex(u32);
169
170 pub struct ComponentUpvarIndex(u32);
172
173 pub struct StaticComponentIndex(u32);
175
176 pub struct RuntimeInstanceIndex(u32);
185
186 pub struct RuntimeComponentInstanceIndex(u32);
188
189 pub struct ImportIndex(u32);
194
195 pub struct RuntimeImportIndex(u32);
201
202 pub struct LoweredIndex(u32);
208
209 pub struct RuntimeMemoryIndex(u32);
217
218 pub struct RuntimeReallocIndex(u32);
220
221 pub struct RuntimeCallbackIndex(u32);
223
224 pub struct RuntimePostReturnIndex(u32);
226
227 pub struct RuntimeTableIndex(u32);
234
235 pub struct TrampolineIndex(u32);
242
243 pub struct ExportIndex(u32);
245
246 pub struct OptionsIndex(u32);
248
249 pub struct AbstractResourceIndex(u32);
256}
257
258pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
261
262#[derive(Debug, Clone, Copy)]
265#[expect(missing_docs, reason = "self-describing variants")]
266pub enum ComponentItem {
267 Func(ComponentFuncIndex),
268 Module(ModuleIndex),
269 Component(ComponentIndex),
270 ComponentInstance(ComponentInstanceIndex),
271 Type(ComponentAnyTypeId),
272}
273
274#[derive(Default, Serialize, Deserialize)]
280pub struct ComponentTypes {
281 pub(super) modules: PrimaryMap<TypeModuleIndex, TypeModule>,
282 pub(super) components: PrimaryMap<TypeComponentIndex, TypeComponent>,
283 pub(super) component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
284 pub(super) functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
285 pub(super) lists: PrimaryMap<TypeListIndex, TypeList>,
286 pub(super) records: PrimaryMap<TypeRecordIndex, TypeRecord>,
287 pub(super) variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
288 pub(super) tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
289 pub(super) enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
290 pub(super) flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
291 pub(super) options: PrimaryMap<TypeOptionIndex, TypeOption>,
292 pub(super) results: PrimaryMap<TypeResultIndex, TypeResult>,
293 pub(super) resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
294 pub(super) module_types: Option<ModuleTypes>,
295 pub(super) futures: PrimaryMap<TypeFutureIndex, TypeFuture>,
296 pub(super) future_tables: PrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
297 pub(super) streams: PrimaryMap<TypeStreamIndex, TypeStream>,
298 pub(super) stream_tables: PrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
299 pub(super) error_context_tables:
300 PrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
301 pub(super) fixed_length_lists: PrimaryMap<TypeFixedLengthListIndex, TypeFixedLengthList>,
302}
303
304impl TypeTrace for ComponentTypes {
305 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
306 where
307 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
308 {
309 for (_, m) in &self.modules {
310 m.trace(func)?;
311 }
312 if let Some(m) = self.module_types.as_ref() {
313 m.trace(func)?;
314 }
315 Ok(())
316 }
317
318 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
319 where
320 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
321 {
322 for (_, m) in &mut self.modules {
323 m.trace_mut(func)?;
324 }
325 if let Some(m) = self.module_types.as_mut() {
326 m.trace_mut(func)?;
327 }
328 Ok(())
329 }
330}
331
332impl ComponentTypes {
333 pub fn module_types(&self) -> &ModuleTypes {
335 self.module_types.as_ref().unwrap()
336 }
337
338 pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
340 self.module_types.as_mut().unwrap()
341 }
342
343 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
345 match ty {
346 InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
347 &CanonicalAbiInfo::SCALAR1
348 }
349
350 InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
351
352 InterfaceType::U32
353 | InterfaceType::S32
354 | InterfaceType::Float32
355 | InterfaceType::Char
356 | InterfaceType::Own(_)
357 | InterfaceType::Borrow(_)
358 | InterfaceType::Future(_)
359 | InterfaceType::Stream(_)
360 | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
361
362 InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
363 &CanonicalAbiInfo::SCALAR8
364 }
365
366 InterfaceType::String | InterfaceType::List(_) => &CanonicalAbiInfo::POINTER_PAIR,
367
368 InterfaceType::Record(i) => &self[*i].abi,
369 InterfaceType::Variant(i) => &self[*i].abi,
370 InterfaceType::Tuple(i) => &self[*i].abi,
371 InterfaceType::Flags(i) => &self[*i].abi,
372 InterfaceType::Enum(i) => &self[*i].abi,
373 InterfaceType::Option(i) => &self[*i].abi,
374 InterfaceType::Result(i) => &self[*i].abi,
375 InterfaceType::FixedLengthList(i) => &self[*i].abi,
376 }
377 }
378
379 pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
381 self.resource_tables.push(table)
382 }
383}
384
385macro_rules! impl_index {
386 ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
387 impl core::ops::Index<$ty> for ComponentTypes {
388 type Output = $output;
389 #[inline]
390 fn index(&self, idx: $ty) -> &$output {
391 &self.$field[idx]
392 }
393 }
394
395 #[cfg(feature = "compile")]
396 impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
397 type Output = $output;
398 #[inline]
399 fn index(&self, idx: $ty) -> &$output {
400 &self.component_types()[idx]
401 }
402 }
403 )*)
404}
405
406impl_index! {
407 impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
408 impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
409 impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
410 impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
411 impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
412 impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
413 impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
414 impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
415 impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
416 impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
417 impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
418 impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
419 impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
420 impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
421 impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
422 impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
423 impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
424 impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
425 impl Index<TypeFixedLengthListIndex> for ComponentTypes { TypeFixedLengthList => fixed_length_lists }
426}
427
428impl<T> Index<T> for ComponentTypes
431where
432 ModuleTypes: Index<T>,
433{
434 type Output = <ModuleTypes as Index<T>>::Output;
435 fn index(&self, idx: T) -> &Self::Output {
436 self.module_types.as_ref().unwrap().index(idx)
437 }
438}
439
440#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
446pub enum TypeDef {
447 Component(TypeComponentIndex),
449 ComponentInstance(TypeComponentInstanceIndex),
451 ComponentFunc(TypeFuncIndex),
453 Interface(InterfaceType),
455 Module(TypeModuleIndex),
457 CoreFunc(ModuleInternedTypeIndex),
459 Resource(TypeResourceTableIndex),
464}
465
466impl TypeDef {
467 pub fn desc(&self) -> &str {
469 match self {
470 TypeDef::Component(_) => "component",
471 TypeDef::ComponentInstance(_) => "instance",
472 TypeDef::ComponentFunc(_) => "function",
473 TypeDef::Interface(_) => "type",
474 TypeDef::Module(_) => "core module",
475 TypeDef::CoreFunc(_) => "core function",
476 TypeDef::Resource(_) => "resource",
477 }
478 }
479}
480
481#[derive(Serialize, Deserialize, Default)]
491pub struct TypeModule {
492 pub imports: IndexMap<(String, String), EntityType>,
500
501 pub exports: IndexMap<String, EntityType>,
506}
507
508impl TypeTrace for TypeModule {
509 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
510 where
511 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
512 {
513 for ty in self.imports.values() {
514 ty.trace(func)?;
515 }
516 for ty in self.exports.values() {
517 ty.trace(func)?;
518 }
519 Ok(())
520 }
521
522 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
523 where
524 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
525 {
526 for ty in self.imports.values_mut() {
527 ty.trace_mut(func)?;
528 }
529 for ty in self.exports.values_mut() {
530 ty.trace_mut(func)?;
531 }
532 Ok(())
533 }
534}
535
536#[derive(Serialize, Deserialize, Default)]
538pub struct TypeComponent {
539 pub imports: IndexMap<String, TypeDef>,
541 pub exports: IndexMap<String, TypeDef>,
543}
544
545#[derive(Serialize, Deserialize, Default)]
550pub struct TypeComponentInstance {
551 pub exports: IndexMap<String, TypeDef>,
553}
554
555#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
557pub struct TypeFunc {
558 pub async_: bool,
560 pub param_names: Vec<String>,
562 pub params: TypeTupleIndex,
564 pub results: TypeTupleIndex,
566}
567
568#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
575#[expect(missing_docs, reason = "self-describing variants")]
576pub enum InterfaceType {
577 Bool,
578 S8,
579 U8,
580 S16,
581 U16,
582 S32,
583 U32,
584 S64,
585 U64,
586 Float32,
587 Float64,
588 Char,
589 String,
590 Record(TypeRecordIndex),
591 Variant(TypeVariantIndex),
592 List(TypeListIndex),
593 Tuple(TypeTupleIndex),
594 Flags(TypeFlagsIndex),
595 Enum(TypeEnumIndex),
596 Option(TypeOptionIndex),
597 Result(TypeResultIndex),
598 Own(TypeResourceTableIndex),
599 Borrow(TypeResourceTableIndex),
600 Future(TypeFutureTableIndex),
601 Stream(TypeStreamTableIndex),
602 ErrorContext(TypeComponentLocalErrorContextTableIndex),
603 FixedLengthList(TypeFixedLengthListIndex),
604}
605
606#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
609pub struct CanonicalAbiInfo {
610 pub size32: u32,
612 pub align32: u32,
614 pub size64: u32,
616 pub align64: u32,
618 pub flat_count: Option<u8>,
625}
626
627impl Default for CanonicalAbiInfo {
628 fn default() -> CanonicalAbiInfo {
629 CanonicalAbiInfo {
630 size32: 0,
631 align32: 1,
632 size64: 0,
633 align64: 1,
634 flat_count: Some(0),
635 }
636 }
637}
638
639const fn align_to(a: u32, b: u32) -> u32 {
640 assert!(b.is_power_of_two());
641 (a + (b - 1)) & !(b - 1)
642}
643
644const fn max(a: u32, b: u32) -> u32 {
645 if a > b { a } else { b }
646}
647
648impl CanonicalAbiInfo {
649 pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
651 size32: 0,
652 align32: 1,
653 size64: 0,
654 align64: 1,
655 flat_count: Some(0),
656 };
657
658 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
660 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
662 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
664 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
666
667 const fn scalar(size: u32) -> CanonicalAbiInfo {
668 CanonicalAbiInfo {
669 size32: size,
670 align32: size,
671 size64: size,
672 align64: size,
673 flat_count: Some(1),
674 }
675 }
676
677 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
679 size32: 8,
680 align32: 4,
681 size64: 16,
682 align64: 8,
683 flat_count: Some(2),
684 };
685
686 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
688 let mut ret = CanonicalAbiInfo::default();
692 for field in fields {
693 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
694 ret.align32 = ret.align32.max(field.align32);
695 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
696 ret.align64 = ret.align64.max(field.align64);
697 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
698 }
699 ret.size32 = align_to(ret.size32, ret.align32);
700 ret.size64 = align_to(ret.size64, ret.align64);
701 return ret;
702 }
703
704 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
706 let mut ret = CanonicalAbiInfo::ZERO;
710 let mut i = 0;
711 while i < fields.len() {
712 let field = &fields[i];
713 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
714 ret.align32 = max(ret.align32, field.align32);
715 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
716 ret.align64 = max(ret.align64, field.align64);
717 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
718 i += 1;
719 }
720 ret.size32 = align_to(ret.size32, ret.align32);
721 ret.size64 = align_to(ret.size64, ret.align64);
722 return ret;
723 }
724
725 pub fn next_field32(&self, offset: &mut u32) -> u32 {
728 *offset = align_to(*offset, self.align32) + self.size32;
729 *offset - self.size32
730 }
731
732 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
734 let cur = u32::try_from(*offset).unwrap();
735 let cur = align_to(cur, self.align32) + self.size32;
736 *offset = usize::try_from(cur).unwrap();
737 usize::try_from(cur - self.size32).unwrap()
738 }
739
740 pub fn next_field64(&self, offset: &mut u32) -> u32 {
743 *offset = align_to(*offset, self.align64) + self.size64;
744 *offset - self.size64
745 }
746
747 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
749 let cur = u32::try_from(*offset).unwrap();
750 let cur = align_to(cur, self.align64) + self.size64;
751 *offset = usize::try_from(cur).unwrap();
752 usize::try_from(cur - self.size64).unwrap()
753 }
754
755 pub const fn flags(count: usize) -> CanonicalAbiInfo {
757 let (size, align, flat_count) = match FlagsSize::from_count(count) {
758 FlagsSize::Size0 => (0, 1, 0),
759 FlagsSize::Size1 => (1, 1, 1),
760 FlagsSize::Size2 => (2, 2, 1),
761 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
762 };
763 CanonicalAbiInfo {
764 size32: size,
765 align32: align,
766 size64: size,
767 align64: align,
768 flat_count: Some(flat_count),
769 }
770 }
771
772 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
773 where
774 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
775 I::IntoIter: ExactSizeIterator,
776 {
777 let cases = cases.into_iter();
781 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
782 let mut max_size32 = 0;
783 let mut max_align32 = discrim_size;
784 let mut max_size64 = 0;
785 let mut max_align64 = discrim_size;
786 let mut max_case_count = Some(0);
787 for case in cases {
788 if let Some(case) = case {
789 max_size32 = max_size32.max(case.size32);
790 max_align32 = max_align32.max(case.align32);
791 max_size64 = max_size64.max(case.size64);
792 max_align64 = max_align64.max(case.align64);
793 max_case_count = max_flat(max_case_count, case.flat_count);
794 }
795 }
796 CanonicalAbiInfo {
797 size32: align_to(
798 align_to(discrim_size, max_align32) + max_size32,
799 max_align32,
800 ),
801 align32: max_align32,
802 size64: align_to(
803 align_to(discrim_size, max_align64) + max_size64,
804 max_align64,
805 ),
806 align64: max_align64,
807 flat_count: add_flat(max_case_count, Some(1)),
808 }
809 }
810
811 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
813 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
817 Some(size) => size.byte_size(),
818 None => unreachable!(),
819 };
820 let mut max_size32 = 0;
821 let mut max_align32 = discrim_size;
822 let mut max_size64 = 0;
823 let mut max_align64 = discrim_size;
824 let mut max_case_count = Some(0);
825 let mut i = 0;
826 while i < cases.len() {
827 let case = &cases[i];
828 if let Some(case) = case {
829 max_size32 = max(max_size32, case.size32);
830 max_align32 = max(max_align32, case.align32);
831 max_size64 = max(max_size64, case.size64);
832 max_align64 = max(max_align64, case.align64);
833 max_case_count = max_flat(max_case_count, case.flat_count);
834 }
835 i += 1;
836 }
837 CanonicalAbiInfo {
838 size32: align_to(
839 align_to(discrim_size, max_align32) + max_size32,
840 max_align32,
841 ),
842 align32: max_align32,
843 size64: align_to(
844 align_to(discrim_size, max_align64) + max_size64,
845 max_align64,
846 ),
847 align64: max_align64,
848 flat_count: add_flat(max_case_count, Some(1)),
849 }
850 }
851
852 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
854 let discrim_size = match DiscriminantSize::from_count(cases) {
858 Some(size) => size.byte_size(),
859 None => unreachable!(),
860 };
861 CanonicalAbiInfo {
862 size32: discrim_size,
863 align32: discrim_size,
864 size64: discrim_size,
865 align64: discrim_size,
866 flat_count: Some(1),
867 }
868 }
869
870 pub fn flat_count(&self, max: usize) -> Option<usize> {
873 let flat = usize::from(self.flat_count?);
874 if flat > max { None } else { Some(flat) }
875 }
876}
877
878#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
880pub struct VariantInfo {
881 #[serde(with = "serde_discrim_size")]
883 pub size: DiscriminantSize,
884 pub payload_offset32: u32,
887 pub payload_offset64: u32,
890}
891
892impl VariantInfo {
893 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
896 where
897 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
898 I::IntoIter: ExactSizeIterator,
899 {
900 let cases = cases.into_iter();
901 let size = DiscriminantSize::from_count(cases.len()).unwrap();
902 let abi = CanonicalAbiInfo::variant(cases);
903 (
904 VariantInfo {
905 size,
906 payload_offset32: align_to(u32::from(size), abi.align32),
907 payload_offset64: align_to(u32::from(size), abi.align64),
908 },
909 abi,
910 )
911 }
912 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
914 let size = match DiscriminantSize::from_count(cases.len()) {
915 Some(size) => size,
916 None => unreachable!(),
917 };
918 let abi = CanonicalAbiInfo::variant_static(cases);
919 VariantInfo {
920 size,
921 payload_offset32: align_to(size.byte_size(), abi.align32),
922 payload_offset64: align_to(size.byte_size(), abi.align64),
923 }
924 }
925}
926
927mod serde_discrim_size {
928 use super::DiscriminantSize;
929 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
930
931 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
932 where
933 S: Serializer,
934 {
935 u32::from(*disc).serialize(ser)
936 }
937
938 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
939 where
940 D: Deserializer<'de>,
941 {
942 match u32::deserialize(deser)? {
943 1 => Ok(DiscriminantSize::Size1),
944 2 => Ok(DiscriminantSize::Size2),
945 4 => Ok(DiscriminantSize::Size4),
946 _ => Err(D::Error::custom("invalid discriminant size")),
947 }
948 }
949}
950
951#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
955pub struct TypeRecord {
956 pub fields: Box<[RecordField]>,
958 pub abi: CanonicalAbiInfo,
960}
961
962#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
964pub struct RecordField {
965 pub name: String,
967 pub ty: InterfaceType,
969}
970
971#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
977pub struct TypeVariant {
978 pub cases: IndexMap<String, Option<InterfaceType>>,
980 pub abi: CanonicalAbiInfo,
982 pub info: VariantInfo,
984}
985
986impl Hash for TypeVariant {
987 fn hash<H: Hasher>(&self, h: &mut H) {
988 let TypeVariant { cases, abi, info } = self;
989 cases.len().hash(h);
990 for pair in cases {
991 pair.hash(h);
992 }
993 abi.hash(h);
994 info.hash(h);
995 }
996}
997
998#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1003pub struct TypeTuple {
1004 pub types: Box<[InterfaceType]>,
1006 pub abi: CanonicalAbiInfo,
1008}
1009
1010#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1015pub struct TypeFlags {
1016 pub names: IndexSet<String>,
1018 pub abi: CanonicalAbiInfo,
1020}
1021
1022impl Hash for TypeFlags {
1023 fn hash<H: Hasher>(&self, h: &mut H) {
1024 let TypeFlags { names, abi } = self;
1025 names.len().hash(h);
1026 for name in names {
1027 name.hash(h);
1028 }
1029 abi.hash(h);
1030 }
1031}
1032
1033#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1039pub struct TypeEnum {
1040 pub names: IndexSet<String>,
1042 pub abi: CanonicalAbiInfo,
1044 pub info: VariantInfo,
1046}
1047
1048impl Hash for TypeEnum {
1049 fn hash<H: Hasher>(&self, h: &mut H) {
1050 let TypeEnum { names, abi, info } = self;
1051 names.len().hash(h);
1052 for name in names {
1053 name.hash(h);
1054 }
1055 abi.hash(h);
1056 info.hash(h);
1057 }
1058}
1059
1060#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1062pub struct TypeOption {
1063 pub ty: InterfaceType,
1065 pub abi: CanonicalAbiInfo,
1067 pub info: VariantInfo,
1069}
1070
1071#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1073pub struct TypeResult {
1074 pub ok: Option<InterfaceType>,
1076 pub err: Option<InterfaceType>,
1078 pub abi: CanonicalAbiInfo,
1080 pub info: VariantInfo,
1082}
1083
1084#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1086pub struct TypeFuture {
1087 pub payload: Option<InterfaceType>,
1089}
1090
1091#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1093pub struct TypeFutureTable {
1094 pub ty: TypeFutureIndex,
1096 pub instance: RuntimeComponentInstanceIndex,
1098}
1099
1100#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1102pub struct TypeStream {
1103 pub payload: Option<InterfaceType>,
1105}
1106
1107#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1109pub struct TypeStreamTable {
1110 pub ty: TypeStreamIndex,
1112 pub instance: RuntimeComponentInstanceIndex,
1114}
1115
1116#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1118pub struct TypeErrorContextTable {
1119 pub instance: RuntimeComponentInstanceIndex,
1121}
1122
1123#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1125pub enum TypeResourceTable {
1126 Concrete {
1133 ty: ResourceIndex,
1138
1139 instance: RuntimeComponentInstanceIndex,
1141 },
1142
1143 Abstract(AbstractResourceIndex),
1147}
1148
1149impl TypeResourceTable {
1150 pub fn unwrap_concrete_ty(&self) -> ResourceIndex {
1157 match self {
1158 TypeResourceTable::Concrete { ty, .. } => *ty,
1159 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1160 }
1161 }
1162
1163 pub fn unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex {
1170 match self {
1171 TypeResourceTable::Concrete { instance, .. } => *instance,
1172 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1173 }
1174 }
1175}
1176
1177#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1179pub struct TypeList {
1180 pub element: InterfaceType,
1182}
1183
1184#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1186pub struct TypeFixedLengthList {
1187 pub element: InterfaceType,
1189 pub size: u32,
1191 pub abi: CanonicalAbiInfo,
1193}
1194
1195pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1197 MAX_FLAT_PARAMS
1198} else {
1199 MAX_FLAT_RESULTS
1200};
1201
1202const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1203 const MAX: u8 = MAX_FLAT_TYPES as u8;
1204 let sum = match (a, b) {
1205 (Some(a), Some(b)) => match a.checked_add(b) {
1206 Some(c) => c,
1207 None => return None,
1208 },
1209 _ => return None,
1210 };
1211 if sum > MAX { None } else { Some(sum) }
1212}
1213
1214const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1215 match (a, b) {
1216 (Some(a), Some(b)) => {
1217 if a > b {
1218 Some(a)
1219 } else {
1220 Some(b)
1221 }
1222 }
1223 _ => None,
1224 }
1225}
1226
1227pub struct FlatTypes<'a> {
1229 pub memory32: &'a [FlatType],
1231 pub memory64: &'a [FlatType],
1233}
1234
1235impl FlatTypes<'_> {
1236 pub fn len(&self) -> usize {
1240 assert_eq!(self.memory32.len(), self.memory64.len());
1241 self.memory32.len()
1242 }
1243}
1244
1245#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1249#[expect(missing_docs, reason = "self-describing variants")]
1250pub enum FlatType {
1251 I32,
1252 I64,
1253 F32,
1254 F64,
1255}