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 impl TryClone for $name {
26 #[inline]
27 fn try_clone(&self) -> Result<Self, OutOfMemory> {
28 Ok(*self)
29 }
30 }
31 )*);
32}
33
34indices! {
35 pub struct ComponentTypeIndex(u32);
43
44 pub struct ModuleIndex(u32);
46
47 pub struct ComponentIndex(u32);
49
50 pub struct ModuleInstanceIndex(u32);
52
53 pub struct ComponentInstanceIndex(u32);
55
56 pub struct ComponentFuncIndex(u32);
58
59 pub struct TypeComponentIndex(u32);
67
68 pub struct TypeComponentInstanceIndex(u32);
71
72 pub struct TypeModuleIndex(u32);
75
76 pub struct TypeFuncIndex(u32);
79
80 pub struct TypeRecordIndex(u32);
82 pub struct TypeVariantIndex(u32);
84 pub struct TypeTupleIndex(u32);
86 pub struct TypeFlagsIndex(u32);
88 pub struct TypeEnumIndex(u32);
90 pub struct TypeOptionIndex(u32);
93 pub struct TypeResultIndex(u32);
96 pub struct TypeListIndex(u32);
98 pub struct TypeMapIndex(u32);
100 pub struct TypeFixedLengthListIndex(u32);
102 pub struct TypeFutureIndex(u32);
104
105 pub struct TypeFutureTableIndex(u32);
110
111 pub struct TypeStreamIndex(u32);
113
114 pub struct TypeStreamTableIndex(u32);
119
120 pub struct TypeComponentLocalErrorContextTableIndex(u32);
125
126 pub struct TypeComponentGlobalErrorContextTableIndex(u32);
132
133 pub struct TypeResourceTableIndex(u32);
148
149 pub struct ResourceIndex(u32);
162
163 pub struct DefinedResourceIndex(u32);
169
170 pub struct ModuleUpvarIndex(u32);
177
178 pub struct ComponentUpvarIndex(u32);
180
181 pub struct StaticComponentIndex(u32);
183
184 pub struct RuntimeInstanceIndex(u32);
193
194 pub struct RuntimeComponentInstanceIndex(u32);
196
197 pub struct ImportIndex(u32);
202
203 pub struct RuntimeImportIndex(u32);
209
210 pub struct LoweredIndex(u32);
216
217 pub struct RuntimeMemoryIndex(u32);
225
226 pub struct RuntimeReallocIndex(u32);
228
229 pub struct RuntimeCallbackIndex(u32);
231
232 pub struct RuntimePostReturnIndex(u32);
234
235 pub struct RuntimeTableIndex(u32);
242
243 pub struct TrampolineIndex(u32);
250
251 pub struct ExportIndex(u32);
253
254 pub struct OptionsIndex(u32);
256
257 pub struct AbstractResourceIndex(u32);
264}
265
266pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
269
270#[derive(Debug, Clone, Copy)]
273#[expect(missing_docs, reason = "self-describing variants")]
274pub enum ComponentItem {
275 Func(ComponentFuncIndex),
276 Module(ModuleIndex),
277 Component(ComponentIndex),
278 ComponentInstance(ComponentInstanceIndex),
279 Type(ComponentAnyTypeId),
280}
281
282#[derive(Default, Serialize, Deserialize)]
288pub struct ComponentTypes {
289 pub(super) modules: PrimaryMap<TypeModuleIndex, TypeModule>,
290 pub(super) components: PrimaryMap<TypeComponentIndex, TypeComponent>,
291 pub(super) component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
292 pub(super) functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
293 pub(super) lists: PrimaryMap<TypeListIndex, TypeList>,
294 pub(super) maps: PrimaryMap<TypeMapIndex, TypeMap>,
295 pub(super) records: PrimaryMap<TypeRecordIndex, TypeRecord>,
296 pub(super) variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
297 pub(super) tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
298 pub(super) enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
299 pub(super) flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
300 pub(super) options: PrimaryMap<TypeOptionIndex, TypeOption>,
301 pub(super) results: PrimaryMap<TypeResultIndex, TypeResult>,
302 pub(super) resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
303 pub(super) module_types: Option<ModuleTypes>,
304 pub(super) futures: PrimaryMap<TypeFutureIndex, TypeFuture>,
305 pub(super) future_tables: PrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
306 pub(super) streams: PrimaryMap<TypeStreamIndex, TypeStream>,
307 pub(super) stream_tables: PrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
308 pub(super) error_context_tables:
309 PrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
310 pub(super) fixed_length_lists: PrimaryMap<TypeFixedLengthListIndex, TypeFixedLengthList>,
311}
312
313impl TypeTrace for ComponentTypes {
314 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
315 where
316 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
317 {
318 for (_, m) in &self.modules {
319 m.trace(func)?;
320 }
321 if let Some(m) = self.module_types.as_ref() {
322 m.trace(func)?;
323 }
324 Ok(())
325 }
326
327 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
328 where
329 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
330 {
331 for (_, m) in &mut self.modules {
332 m.trace_mut(func)?;
333 }
334 if let Some(m) = self.module_types.as_mut() {
335 m.trace_mut(func)?;
336 }
337 Ok(())
338 }
339}
340
341impl ComponentTypes {
342 pub fn module_types(&self) -> &ModuleTypes {
344 self.module_types.as_ref().unwrap()
345 }
346
347 pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
349 self.module_types.as_mut().unwrap()
350 }
351
352 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
354 match ty {
355 InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
356 &CanonicalAbiInfo::SCALAR1
357 }
358
359 InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
360
361 InterfaceType::U32
362 | InterfaceType::S32
363 | InterfaceType::Float32
364 | InterfaceType::Char
365 | InterfaceType::Own(_)
366 | InterfaceType::Borrow(_)
367 | InterfaceType::Future(_)
368 | InterfaceType::Stream(_)
369 | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
370
371 InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
372 &CanonicalAbiInfo::SCALAR8
373 }
374
375 InterfaceType::String | InterfaceType::List(_) | InterfaceType::Map(_) => {
376 &CanonicalAbiInfo::POINTER_PAIR
377 }
378
379 InterfaceType::Record(i) => &self[*i].abi,
380 InterfaceType::Variant(i) => &self[*i].abi,
381 InterfaceType::Tuple(i) => &self[*i].abi,
382 InterfaceType::Flags(i) => &self[*i].abi,
383 InterfaceType::Enum(i) => &self[*i].abi,
384 InterfaceType::Option(i) => &self[*i].abi,
385 InterfaceType::Result(i) => &self[*i].abi,
386 InterfaceType::FixedLengthList(i) => &self[*i].abi,
387 }
388 }
389
390 pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
392 self.resource_tables.push(table)
393 }
394}
395
396macro_rules! impl_index {
397 ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
398 impl core::ops::Index<$ty> for ComponentTypes {
399 type Output = $output;
400 #[inline]
401 fn index(&self, idx: $ty) -> &$output {
402 &self.$field[idx]
403 }
404 }
405
406 #[cfg(feature = "compile")]
407 impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
408 type Output = $output;
409 #[inline]
410 fn index(&self, idx: $ty) -> &$output {
411 &self.component_types()[idx]
412 }
413 }
414 )*)
415}
416
417impl_index! {
418 impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
419 impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
420 impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
421 impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
422 impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
423 impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
424 impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
425 impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
426 impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
427 impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
428 impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
429 impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
430 impl Index<TypeMapIndex> for ComponentTypes { TypeMap => maps }
431 impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
432 impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
433 impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
434 impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
435 impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
436 impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
437 impl Index<TypeFixedLengthListIndex> for ComponentTypes { TypeFixedLengthList => fixed_length_lists }
438}
439
440impl<T> Index<T> for ComponentTypes
443where
444 ModuleTypes: Index<T>,
445{
446 type Output = <ModuleTypes as Index<T>>::Output;
447 fn index(&self, idx: T) -> &Self::Output {
448 self.module_types.as_ref().unwrap().index(idx)
449 }
450}
451
452#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
458pub enum TypeDef {
459 Component(TypeComponentIndex),
461 ComponentInstance(TypeComponentInstanceIndex),
463 ComponentFunc(TypeFuncIndex),
465 Interface(InterfaceType),
467 Module(TypeModuleIndex),
469 CoreFunc(ModuleInternedTypeIndex),
471 Resource(TypeResourceTableIndex),
476}
477
478impl TypeDef {
479 pub fn desc(&self) -> &str {
481 match self {
482 TypeDef::Component(_) => "component",
483 TypeDef::ComponentInstance(_) => "instance",
484 TypeDef::ComponentFunc(_) => "function",
485 TypeDef::Interface(_) => "type",
486 TypeDef::Module(_) => "core module",
487 TypeDef::CoreFunc(_) => "core function",
488 TypeDef::Resource(_) => "resource",
489 }
490 }
491}
492
493#[derive(Serialize, Deserialize, Default)]
503pub struct TypeModule {
504 pub imports: IndexMap<(String, String), EntityType>,
512
513 pub exports: IndexMap<String, EntityType>,
518}
519
520impl TypeTrace for TypeModule {
521 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
522 where
523 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
524 {
525 for ty in self.imports.values() {
526 ty.trace(func)?;
527 }
528 for ty in self.exports.values() {
529 ty.trace(func)?;
530 }
531 Ok(())
532 }
533
534 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
535 where
536 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
537 {
538 for ty in self.imports.values_mut() {
539 ty.trace_mut(func)?;
540 }
541 for ty in self.exports.values_mut() {
542 ty.trace_mut(func)?;
543 }
544 Ok(())
545 }
546}
547
548#[derive(Serialize, Deserialize, Default)]
550pub struct TypeComponent {
551 pub imports: IndexMap<String, TypeDef>,
553 pub exports: IndexMap<String, TypeDef>,
555}
556
557#[derive(Serialize, Deserialize, Default)]
562pub struct TypeComponentInstance {
563 pub exports: IndexMap<String, TypeDef>,
565}
566
567#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
569pub struct TypeFunc {
570 pub async_: bool,
572 pub param_names: Vec<String>,
574 pub params: TypeTupleIndex,
576 pub results: TypeTupleIndex,
578}
579
580#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
587#[expect(missing_docs, reason = "self-describing variants")]
588pub enum InterfaceType {
589 Bool,
590 S8,
591 U8,
592 S16,
593 U16,
594 S32,
595 U32,
596 S64,
597 U64,
598 Float32,
599 Float64,
600 Char,
601 String,
602 Record(TypeRecordIndex),
603 Variant(TypeVariantIndex),
604 List(TypeListIndex),
605 Tuple(TypeTupleIndex),
606 Map(TypeMapIndex),
607 Flags(TypeFlagsIndex),
608 Enum(TypeEnumIndex),
609 Option(TypeOptionIndex),
610 Result(TypeResultIndex),
611 Own(TypeResourceTableIndex),
612 Borrow(TypeResourceTableIndex),
613 Future(TypeFutureTableIndex),
614 Stream(TypeStreamTableIndex),
615 ErrorContext(TypeComponentLocalErrorContextTableIndex),
616 FixedLengthList(TypeFixedLengthListIndex),
617}
618
619#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
622pub struct CanonicalAbiInfo {
623 pub size32: u32,
625 pub align32: u32,
627 pub size64: u32,
629 pub align64: u32,
631 pub flat_count: Option<u8>,
638}
639
640impl Default for CanonicalAbiInfo {
641 fn default() -> CanonicalAbiInfo {
642 CanonicalAbiInfo {
643 size32: 0,
644 align32: 1,
645 size64: 0,
646 align64: 1,
647 flat_count: Some(0),
648 }
649 }
650}
651
652const fn align_to(a: u32, b: u32) -> u32 {
653 assert!(b.is_power_of_two());
654 (a + (b - 1)) & !(b - 1)
655}
656
657const fn max(a: u32, b: u32) -> u32 {
658 if a > b { a } else { b }
659}
660
661impl CanonicalAbiInfo {
662 pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
664 size32: 0,
665 align32: 1,
666 size64: 0,
667 align64: 1,
668 flat_count: Some(0),
669 };
670
671 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
673 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
675 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
677 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
679
680 const fn scalar(size: u32) -> CanonicalAbiInfo {
681 CanonicalAbiInfo {
682 size32: size,
683 align32: size,
684 size64: size,
685 align64: size,
686 flat_count: Some(1),
687 }
688 }
689
690 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
692 size32: 8,
693 align32: 4,
694 size64: 16,
695 align64: 8,
696 flat_count: Some(2),
697 };
698
699 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
701 let mut ret = CanonicalAbiInfo::default();
705 for field in fields {
706 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
707 ret.align32 = ret.align32.max(field.align32);
708 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
709 ret.align64 = ret.align64.max(field.align64);
710 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
711 }
712 ret.size32 = align_to(ret.size32, ret.align32);
713 ret.size64 = align_to(ret.size64, ret.align64);
714 return ret;
715 }
716
717 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
719 let mut ret = CanonicalAbiInfo::ZERO;
723 let mut i = 0;
724 while i < fields.len() {
725 let field = &fields[i];
726 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
727 ret.align32 = max(ret.align32, field.align32);
728 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
729 ret.align64 = max(ret.align64, field.align64);
730 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
731 i += 1;
732 }
733 ret.size32 = align_to(ret.size32, ret.align32);
734 ret.size64 = align_to(ret.size64, ret.align64);
735 return ret;
736 }
737
738 pub fn next_field32(&self, offset: &mut u32) -> u32 {
741 *offset = align_to(*offset, self.align32) + self.size32;
742 *offset - self.size32
743 }
744
745 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
747 let cur = u32::try_from(*offset).unwrap();
748 let cur = align_to(cur, self.align32) + self.size32;
749 *offset = usize::try_from(cur).unwrap();
750 usize::try_from(cur - self.size32).unwrap()
751 }
752
753 pub fn next_field64(&self, offset: &mut u32) -> u32 {
756 *offset = align_to(*offset, self.align64) + self.size64;
757 *offset - self.size64
758 }
759
760 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
762 let cur = u32::try_from(*offset).unwrap();
763 let cur = align_to(cur, self.align64) + self.size64;
764 *offset = usize::try_from(cur).unwrap();
765 usize::try_from(cur - self.size64).unwrap()
766 }
767
768 pub const fn flags(count: usize) -> CanonicalAbiInfo {
770 let (size, align, flat_count) = match FlagsSize::from_count(count) {
771 FlagsSize::Size0 => (0, 1, 0),
772 FlagsSize::Size1 => (1, 1, 1),
773 FlagsSize::Size2 => (2, 2, 1),
774 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
775 };
776 CanonicalAbiInfo {
777 size32: size,
778 align32: align,
779 size64: size,
780 align64: align,
781 flat_count: Some(flat_count),
782 }
783 }
784
785 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
786 where
787 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
788 I::IntoIter: ExactSizeIterator,
789 {
790 let cases = cases.into_iter();
794 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
795 let mut max_size32 = 0;
796 let mut max_align32 = discrim_size;
797 let mut max_size64 = 0;
798 let mut max_align64 = discrim_size;
799 let mut max_case_count = Some(0);
800 for case in cases {
801 if let Some(case) = case {
802 max_size32 = max_size32.max(case.size32);
803 max_align32 = max_align32.max(case.align32);
804 max_size64 = max_size64.max(case.size64);
805 max_align64 = max_align64.max(case.align64);
806 max_case_count = max_flat(max_case_count, case.flat_count);
807 }
808 }
809 CanonicalAbiInfo {
810 size32: align_to(
811 align_to(discrim_size, max_align32) + max_size32,
812 max_align32,
813 ),
814 align32: max_align32,
815 size64: align_to(
816 align_to(discrim_size, max_align64) + max_size64,
817 max_align64,
818 ),
819 align64: max_align64,
820 flat_count: add_flat(max_case_count, Some(1)),
821 }
822 }
823
824 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
826 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
830 Some(size) => size.byte_size(),
831 None => unreachable!(),
832 };
833 let mut max_size32 = 0;
834 let mut max_align32 = discrim_size;
835 let mut max_size64 = 0;
836 let mut max_align64 = discrim_size;
837 let mut max_case_count = Some(0);
838 let mut i = 0;
839 while i < cases.len() {
840 let case = &cases[i];
841 if let Some(case) = case {
842 max_size32 = max(max_size32, case.size32);
843 max_align32 = max(max_align32, case.align32);
844 max_size64 = max(max_size64, case.size64);
845 max_align64 = max(max_align64, case.align64);
846 max_case_count = max_flat(max_case_count, case.flat_count);
847 }
848 i += 1;
849 }
850 CanonicalAbiInfo {
851 size32: align_to(
852 align_to(discrim_size, max_align32) + max_size32,
853 max_align32,
854 ),
855 align32: max_align32,
856 size64: align_to(
857 align_to(discrim_size, max_align64) + max_size64,
858 max_align64,
859 ),
860 align64: max_align64,
861 flat_count: add_flat(max_case_count, Some(1)),
862 }
863 }
864
865 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
867 let discrim_size = match DiscriminantSize::from_count(cases) {
871 Some(size) => size.byte_size(),
872 None => unreachable!(),
873 };
874 CanonicalAbiInfo {
875 size32: discrim_size,
876 align32: discrim_size,
877 size64: discrim_size,
878 align64: discrim_size,
879 flat_count: Some(1),
880 }
881 }
882
883 pub fn flat_count(&self, max: usize) -> Option<usize> {
886 let flat = usize::from(self.flat_count?);
887 if flat > max { None } else { Some(flat) }
888 }
889}
890
891#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
893pub struct VariantInfo {
894 #[serde(with = "serde_discrim_size")]
896 pub size: DiscriminantSize,
897 pub payload_offset32: u32,
900 pub payload_offset64: u32,
903}
904
905impl VariantInfo {
906 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
909 where
910 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
911 I::IntoIter: ExactSizeIterator,
912 {
913 let cases = cases.into_iter();
914 let size = DiscriminantSize::from_count(cases.len()).unwrap();
915 let abi = CanonicalAbiInfo::variant(cases);
916 (
917 VariantInfo {
918 size,
919 payload_offset32: align_to(u32::from(size), abi.align32),
920 payload_offset64: align_to(u32::from(size), abi.align64),
921 },
922 abi,
923 )
924 }
925 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
927 let size = match DiscriminantSize::from_count(cases.len()) {
928 Some(size) => size,
929 None => unreachable!(),
930 };
931 let abi = CanonicalAbiInfo::variant_static(cases);
932 VariantInfo {
933 size,
934 payload_offset32: align_to(size.byte_size(), abi.align32),
935 payload_offset64: align_to(size.byte_size(), abi.align64),
936 }
937 }
938}
939
940mod serde_discrim_size {
941 use super::DiscriminantSize;
942 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
943
944 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
945 where
946 S: Serializer,
947 {
948 u32::from(*disc).serialize(ser)
949 }
950
951 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
952 where
953 D: Deserializer<'de>,
954 {
955 match u32::deserialize(deser)? {
956 1 => Ok(DiscriminantSize::Size1),
957 2 => Ok(DiscriminantSize::Size2),
958 4 => Ok(DiscriminantSize::Size4),
959 _ => Err(D::Error::custom("invalid discriminant size")),
960 }
961 }
962}
963
964#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
968pub struct TypeRecord {
969 pub fields: Box<[RecordField]>,
971 pub abi: CanonicalAbiInfo,
973}
974
975#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
977pub struct RecordField {
978 pub name: String,
980 pub ty: InterfaceType,
982}
983
984#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
990pub struct TypeVariant {
991 pub cases: IndexMap<String, Option<InterfaceType>>,
993 pub abi: CanonicalAbiInfo,
995 pub info: VariantInfo,
997}
998
999impl Hash for TypeVariant {
1000 fn hash<H: Hasher>(&self, h: &mut H) {
1001 let TypeVariant { cases, abi, info } = self;
1002 cases.len().hash(h);
1003 for pair in cases {
1004 pair.hash(h);
1005 }
1006 abi.hash(h);
1007 info.hash(h);
1008 }
1009}
1010
1011#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1016pub struct TypeTuple {
1017 pub types: Box<[InterfaceType]>,
1019 pub abi: CanonicalAbiInfo,
1021}
1022
1023#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1028pub struct TypeFlags {
1029 pub names: IndexSet<String>,
1031 pub abi: CanonicalAbiInfo,
1033}
1034
1035impl Hash for TypeFlags {
1036 fn hash<H: Hasher>(&self, h: &mut H) {
1037 let TypeFlags { names, abi } = self;
1038 names.len().hash(h);
1039 for name in names {
1040 name.hash(h);
1041 }
1042 abi.hash(h);
1043 }
1044}
1045
1046#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1052pub struct TypeEnum {
1053 pub names: IndexSet<String>,
1055 pub abi: CanonicalAbiInfo,
1057 pub info: VariantInfo,
1059}
1060
1061impl Hash for TypeEnum {
1062 fn hash<H: Hasher>(&self, h: &mut H) {
1063 let TypeEnum { names, abi, info } = self;
1064 names.len().hash(h);
1065 for name in names {
1066 name.hash(h);
1067 }
1068 abi.hash(h);
1069 info.hash(h);
1070 }
1071}
1072
1073#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1075pub struct TypeOption {
1076 pub ty: InterfaceType,
1078 pub abi: CanonicalAbiInfo,
1080 pub info: VariantInfo,
1082}
1083
1084#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1086pub struct TypeResult {
1087 pub ok: Option<InterfaceType>,
1089 pub err: Option<InterfaceType>,
1091 pub abi: CanonicalAbiInfo,
1093 pub info: VariantInfo,
1095}
1096
1097#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1099pub struct TypeFuture {
1100 pub payload: Option<InterfaceType>,
1102}
1103
1104#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1106pub struct TypeFutureTable {
1107 pub ty: TypeFutureIndex,
1109 pub instance: RuntimeComponentInstanceIndex,
1111}
1112
1113#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1115pub struct TypeStream {
1116 pub payload: Option<InterfaceType>,
1118}
1119
1120#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1122pub struct TypeStreamTable {
1123 pub ty: TypeStreamIndex,
1125 pub instance: RuntimeComponentInstanceIndex,
1127}
1128
1129#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1131pub struct TypeErrorContextTable {
1132 pub instance: RuntimeComponentInstanceIndex,
1134}
1135
1136#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1138pub enum TypeResourceTable {
1139 Concrete {
1146 ty: ResourceIndex,
1151
1152 instance: RuntimeComponentInstanceIndex,
1154 },
1155
1156 Abstract(AbstractResourceIndex),
1160}
1161
1162impl TypeResourceTable {
1163 pub fn unwrap_concrete_ty(&self) -> ResourceIndex {
1170 match self {
1171 TypeResourceTable::Concrete { ty, .. } => *ty,
1172 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1173 }
1174 }
1175
1176 pub fn unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex {
1183 match self {
1184 TypeResourceTable::Concrete { instance, .. } => *instance,
1185 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1186 }
1187 }
1188}
1189
1190#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1192pub struct TypeList {
1193 pub element: InterfaceType,
1195}
1196
1197#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1199pub struct TypeMap {
1200 pub key: InterfaceType,
1202 pub value: InterfaceType,
1204 pub entry_abi: CanonicalAbiInfo,
1206 pub value_offset32: u32,
1209 pub value_offset64: u32,
1212}
1213
1214#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1216pub struct TypeFixedLengthList {
1217 pub element: InterfaceType,
1219 pub size: u32,
1221 pub abi: CanonicalAbiInfo,
1223}
1224
1225pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1227 MAX_FLAT_PARAMS
1228} else {
1229 MAX_FLAT_RESULTS
1230};
1231
1232const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1233 const MAX: u8 = MAX_FLAT_TYPES as u8;
1234 let sum = match (a, b) {
1235 (Some(a), Some(b)) => match a.checked_add(b) {
1236 Some(c) => c,
1237 None => return None,
1238 },
1239 _ => return None,
1240 };
1241 if sum > MAX { None } else { Some(sum) }
1242}
1243
1244const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1245 match (a, b) {
1246 (Some(a), Some(b)) => {
1247 if a > b {
1248 Some(a)
1249 } else {
1250 Some(b)
1251 }
1252 }
1253 _ => None,
1254 }
1255}
1256
1257pub struct FlatTypes<'a> {
1259 pub memory32: &'a [FlatType],
1261 pub memory64: &'a [FlatType],
1263}
1264
1265impl FlatTypes<'_> {
1266 pub fn len(&self) -> usize {
1270 assert_eq!(self.memory32.len(), self.memory64.len());
1271 self.memory32.len()
1272 }
1273}
1274
1275#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1279#[expect(missing_docs, reason = "self-describing variants")]
1280pub enum FlatType {
1281 I32,
1282 I64,
1283 F32,
1284 F64,
1285}