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(Clone, Debug, Serialize, Deserialize)]
454pub struct ComponentExtern {
455 pub data: ComponentExternData,
457 pub ty: TypeDef,
459}
460
461#[derive(Clone, Debug, Serialize, Deserialize)]
463pub struct ComponentExternData {
464 pub implements: Option<String>,
466}
467
468#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
474pub enum TypeDef {
475 Component(TypeComponentIndex),
477 ComponentInstance(TypeComponentInstanceIndex),
479 ComponentFunc(TypeFuncIndex),
481 Interface(InterfaceType),
483 Module(TypeModuleIndex),
485 CoreFunc(ModuleInternedTypeIndex),
487 Resource(TypeResourceTableIndex),
492}
493
494impl TypeDef {
495 pub fn desc(&self) -> &str {
497 match self {
498 TypeDef::Component(_) => "component",
499 TypeDef::ComponentInstance(_) => "instance",
500 TypeDef::ComponentFunc(_) => "function",
501 TypeDef::Interface(_) => "type",
502 TypeDef::Module(_) => "core module",
503 TypeDef::CoreFunc(_) => "core function",
504 TypeDef::Resource(_) => "resource",
505 }
506 }
507}
508
509#[derive(Serialize, Deserialize, Default)]
519pub struct TypeModule {
520 pub imports: IndexMap<(String, String), EntityType>,
528
529 pub exports: IndexMap<String, EntityType>,
534}
535
536impl TypeTrace for TypeModule {
537 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
538 where
539 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
540 {
541 for ty in self.imports.values() {
542 ty.trace(func)?;
543 }
544 for ty in self.exports.values() {
545 ty.trace(func)?;
546 }
547 Ok(())
548 }
549
550 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
551 where
552 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
553 {
554 for ty in self.imports.values_mut() {
555 ty.trace_mut(func)?;
556 }
557 for ty in self.exports.values_mut() {
558 ty.trace_mut(func)?;
559 }
560 Ok(())
561 }
562}
563
564#[derive(Serialize, Deserialize, Default)]
566pub struct TypeComponent {
567 pub imports: IndexMap<String, ComponentExtern>,
569 pub exports: IndexMap<String, ComponentExtern>,
571}
572
573#[derive(Serialize, Deserialize, Default)]
578pub struct TypeComponentInstance {
579 pub exports: IndexMap<String, ComponentExtern>,
581}
582
583#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
585pub struct TypeFunc {
586 pub async_: bool,
588 pub param_names: Vec<String>,
590 pub params: TypeTupleIndex,
592 pub results: TypeTupleIndex,
594}
595
596#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
603#[expect(missing_docs, reason = "self-describing variants")]
604pub enum InterfaceType {
605 Bool,
606 S8,
607 U8,
608 S16,
609 U16,
610 S32,
611 U32,
612 S64,
613 U64,
614 Float32,
615 Float64,
616 Char,
617 String,
618 Record(TypeRecordIndex),
619 Variant(TypeVariantIndex),
620 List(TypeListIndex),
621 Tuple(TypeTupleIndex),
622 Map(TypeMapIndex),
623 Flags(TypeFlagsIndex),
624 Enum(TypeEnumIndex),
625 Option(TypeOptionIndex),
626 Result(TypeResultIndex),
627 Own(TypeResourceTableIndex),
628 Borrow(TypeResourceTableIndex),
629 Future(TypeFutureTableIndex),
630 Stream(TypeStreamTableIndex),
631 ErrorContext(TypeComponentLocalErrorContextTableIndex),
632 FixedLengthList(TypeFixedLengthListIndex),
633}
634
635#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
638pub struct CanonicalAbiInfo {
639 pub size32: u32,
641 pub align32: u32,
643 pub size64: u32,
645 pub align64: u32,
647 pub flat_count: Option<u8>,
654}
655
656impl Default for CanonicalAbiInfo {
657 fn default() -> CanonicalAbiInfo {
658 CanonicalAbiInfo {
659 size32: 0,
660 align32: 1,
661 size64: 0,
662 align64: 1,
663 flat_count: Some(0),
664 }
665 }
666}
667
668const fn align_to(a: u32, b: u32) -> u32 {
669 assert!(b.is_power_of_two());
670 (a + (b - 1)) & !(b - 1)
671}
672
673const fn max(a: u32, b: u32) -> u32 {
674 if a > b { a } else { b }
675}
676
677impl CanonicalAbiInfo {
678 pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
680 size32: 0,
681 align32: 1,
682 size64: 0,
683 align64: 1,
684 flat_count: Some(0),
685 };
686
687 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
689 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
691 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
693 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
695
696 const fn scalar(size: u32) -> CanonicalAbiInfo {
697 CanonicalAbiInfo {
698 size32: size,
699 align32: size,
700 size64: size,
701 align64: size,
702 flat_count: Some(1),
703 }
704 }
705
706 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
708 size32: 8,
709 align32: 4,
710 size64: 16,
711 align64: 8,
712 flat_count: Some(2),
713 };
714
715 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
717 let mut ret = CanonicalAbiInfo::default();
721 for field in fields {
722 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
723 ret.align32 = ret.align32.max(field.align32);
724 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
725 ret.align64 = ret.align64.max(field.align64);
726 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
727 }
728 ret.size32 = align_to(ret.size32, ret.align32);
729 ret.size64 = align_to(ret.size64, ret.align64);
730 return ret;
731 }
732
733 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
735 let mut ret = CanonicalAbiInfo::ZERO;
739 let mut i = 0;
740 while i < fields.len() {
741 let field = &fields[i];
742 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
743 ret.align32 = max(ret.align32, field.align32);
744 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
745 ret.align64 = max(ret.align64, field.align64);
746 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
747 i += 1;
748 }
749 ret.size32 = align_to(ret.size32, ret.align32);
750 ret.size64 = align_to(ret.size64, ret.align64);
751 return ret;
752 }
753
754 pub fn next_field32(&self, offset: &mut u32) -> u32 {
757 *offset = align_to(*offset, self.align32) + self.size32;
758 *offset - self.size32
759 }
760
761 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
763 let cur = u32::try_from(*offset).unwrap();
764 let cur = align_to(cur, self.align32) + self.size32;
765 *offset = usize::try_from(cur).unwrap();
766 usize::try_from(cur - self.size32).unwrap()
767 }
768
769 pub fn next_field64(&self, offset: &mut u32) -> u32 {
772 *offset = align_to(*offset, self.align64) + self.size64;
773 *offset - self.size64
774 }
775
776 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
778 let cur = u32::try_from(*offset).unwrap();
779 let cur = align_to(cur, self.align64) + self.size64;
780 *offset = usize::try_from(cur).unwrap();
781 usize::try_from(cur - self.size64).unwrap()
782 }
783
784 pub const fn flags(count: usize) -> CanonicalAbiInfo {
786 let (size, align, flat_count) = match FlagsSize::from_count(count) {
787 FlagsSize::Size0 => (0, 1, 0),
788 FlagsSize::Size1 => (1, 1, 1),
789 FlagsSize::Size2 => (2, 2, 1),
790 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
791 };
792 CanonicalAbiInfo {
793 size32: size,
794 align32: align,
795 size64: size,
796 align64: align,
797 flat_count: Some(flat_count),
798 }
799 }
800
801 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
802 where
803 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
804 I::IntoIter: ExactSizeIterator,
805 {
806 let cases = cases.into_iter();
810 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
811 let mut max_size32 = 0;
812 let mut max_align32 = discrim_size;
813 let mut max_size64 = 0;
814 let mut max_align64 = discrim_size;
815 let mut max_case_count = Some(0);
816 for case in cases {
817 if let Some(case) = case {
818 max_size32 = max_size32.max(case.size32);
819 max_align32 = max_align32.max(case.align32);
820 max_size64 = max_size64.max(case.size64);
821 max_align64 = max_align64.max(case.align64);
822 max_case_count = max_flat(max_case_count, case.flat_count);
823 }
824 }
825 CanonicalAbiInfo {
826 size32: align_to(
827 align_to(discrim_size, max_align32) + max_size32,
828 max_align32,
829 ),
830 align32: max_align32,
831 size64: align_to(
832 align_to(discrim_size, max_align64) + max_size64,
833 max_align64,
834 ),
835 align64: max_align64,
836 flat_count: add_flat(max_case_count, Some(1)),
837 }
838 }
839
840 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
842 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
846 Some(size) => size.byte_size(),
847 None => unreachable!(),
848 };
849 let mut max_size32 = 0;
850 let mut max_align32 = discrim_size;
851 let mut max_size64 = 0;
852 let mut max_align64 = discrim_size;
853 let mut max_case_count = Some(0);
854 let mut i = 0;
855 while i < cases.len() {
856 let case = &cases[i];
857 if let Some(case) = case {
858 max_size32 = max(max_size32, case.size32);
859 max_align32 = max(max_align32, case.align32);
860 max_size64 = max(max_size64, case.size64);
861 max_align64 = max(max_align64, case.align64);
862 max_case_count = max_flat(max_case_count, case.flat_count);
863 }
864 i += 1;
865 }
866 CanonicalAbiInfo {
867 size32: align_to(
868 align_to(discrim_size, max_align32) + max_size32,
869 max_align32,
870 ),
871 align32: max_align32,
872 size64: align_to(
873 align_to(discrim_size, max_align64) + max_size64,
874 max_align64,
875 ),
876 align64: max_align64,
877 flat_count: add_flat(max_case_count, Some(1)),
878 }
879 }
880
881 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
883 let discrim_size = match DiscriminantSize::from_count(cases) {
887 Some(size) => size.byte_size(),
888 None => unreachable!(),
889 };
890 CanonicalAbiInfo {
891 size32: discrim_size,
892 align32: discrim_size,
893 size64: discrim_size,
894 align64: discrim_size,
895 flat_count: Some(1),
896 }
897 }
898
899 pub fn flat_count(&self, max: usize) -> Option<usize> {
902 let flat = usize::from(self.flat_count?);
903 if flat > max { None } else { Some(flat) }
904 }
905}
906
907#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
909pub struct VariantInfo {
910 #[serde(with = "serde_discrim_size")]
912 pub size: DiscriminantSize,
913 pub payload_offset32: u32,
916 pub payload_offset64: u32,
919}
920
921impl VariantInfo {
922 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
925 where
926 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
927 I::IntoIter: ExactSizeIterator,
928 {
929 let cases = cases.into_iter();
930 let size = DiscriminantSize::from_count(cases.len()).unwrap();
931 let abi = CanonicalAbiInfo::variant(cases);
932 (
933 VariantInfo {
934 size,
935 payload_offset32: align_to(u32::from(size), abi.align32),
936 payload_offset64: align_to(u32::from(size), abi.align64),
937 },
938 abi,
939 )
940 }
941 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
943 let size = match DiscriminantSize::from_count(cases.len()) {
944 Some(size) => size,
945 None => unreachable!(),
946 };
947 let abi = CanonicalAbiInfo::variant_static(cases);
948 VariantInfo {
949 size,
950 payload_offset32: align_to(size.byte_size(), abi.align32),
951 payload_offset64: align_to(size.byte_size(), abi.align64),
952 }
953 }
954}
955
956mod serde_discrim_size {
957 use super::DiscriminantSize;
958 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
959
960 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
961 where
962 S: Serializer,
963 {
964 u32::from(*disc).serialize(ser)
965 }
966
967 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
968 where
969 D: Deserializer<'de>,
970 {
971 match u32::deserialize(deser)? {
972 1 => Ok(DiscriminantSize::Size1),
973 2 => Ok(DiscriminantSize::Size2),
974 4 => Ok(DiscriminantSize::Size4),
975 _ => Err(D::Error::custom("invalid discriminant size")),
976 }
977 }
978}
979
980#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
984pub struct TypeRecord {
985 pub fields: Box<[RecordField]>,
987 pub abi: CanonicalAbiInfo,
989}
990
991#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
993pub struct RecordField {
994 pub name: String,
996 pub ty: InterfaceType,
998}
999
1000#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1006pub struct TypeVariant {
1007 pub cases: IndexMap<String, Option<InterfaceType>>,
1009 pub abi: CanonicalAbiInfo,
1011 pub info: VariantInfo,
1013}
1014
1015impl Hash for TypeVariant {
1016 fn hash<H: Hasher>(&self, h: &mut H) {
1017 let TypeVariant { cases, abi, info } = self;
1018 cases.len().hash(h);
1019 for pair in cases {
1020 pair.hash(h);
1021 }
1022 abi.hash(h);
1023 info.hash(h);
1024 }
1025}
1026
1027#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1032pub struct TypeTuple {
1033 pub types: Box<[InterfaceType]>,
1035 pub abi: CanonicalAbiInfo,
1037}
1038
1039#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1044pub struct TypeFlags {
1045 pub names: IndexSet<String>,
1047 pub abi: CanonicalAbiInfo,
1049}
1050
1051impl Hash for TypeFlags {
1052 fn hash<H: Hasher>(&self, h: &mut H) {
1053 let TypeFlags { names, abi } = self;
1054 names.len().hash(h);
1055 for name in names {
1056 name.hash(h);
1057 }
1058 abi.hash(h);
1059 }
1060}
1061
1062#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1068pub struct TypeEnum {
1069 pub names: IndexSet<String>,
1071 pub abi: CanonicalAbiInfo,
1073 pub info: VariantInfo,
1075}
1076
1077impl Hash for TypeEnum {
1078 fn hash<H: Hasher>(&self, h: &mut H) {
1079 let TypeEnum { names, abi, info } = self;
1080 names.len().hash(h);
1081 for name in names {
1082 name.hash(h);
1083 }
1084 abi.hash(h);
1085 info.hash(h);
1086 }
1087}
1088
1089#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1091pub struct TypeOption {
1092 pub ty: InterfaceType,
1094 pub abi: CanonicalAbiInfo,
1096 pub info: VariantInfo,
1098}
1099
1100#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1102pub struct TypeResult {
1103 pub ok: Option<InterfaceType>,
1105 pub err: Option<InterfaceType>,
1107 pub abi: CanonicalAbiInfo,
1109 pub info: VariantInfo,
1111}
1112
1113#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1115pub struct TypeFuture {
1116 pub payload: Option<InterfaceType>,
1118}
1119
1120#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1122pub struct TypeFutureTable {
1123 pub ty: TypeFutureIndex,
1125 pub instance: RuntimeComponentInstanceIndex,
1127}
1128
1129#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1131pub struct TypeStream {
1132 pub payload: Option<InterfaceType>,
1134}
1135
1136#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1138pub struct TypeStreamTable {
1139 pub ty: TypeStreamIndex,
1141 pub instance: RuntimeComponentInstanceIndex,
1143}
1144
1145#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1147pub struct TypeErrorContextTable {
1148 pub instance: RuntimeComponentInstanceIndex,
1150}
1151
1152#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1154pub enum TypeResourceTable {
1155 Concrete {
1162 ty: ResourceIndex,
1167
1168 instance: RuntimeComponentInstanceIndex,
1170 },
1171
1172 Abstract(AbstractResourceIndex),
1176}
1177
1178impl TypeResourceTable {
1179 pub fn unwrap_concrete_ty(&self) -> ResourceIndex {
1186 match self {
1187 TypeResourceTable::Concrete { ty, .. } => *ty,
1188 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1189 }
1190 }
1191
1192 pub fn unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex {
1199 match self {
1200 TypeResourceTable::Concrete { instance, .. } => *instance,
1201 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1202 }
1203 }
1204}
1205
1206#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1208pub struct TypeList {
1209 pub element: InterfaceType,
1211}
1212
1213#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1215pub struct TypeMap {
1216 pub key: InterfaceType,
1218 pub value: InterfaceType,
1220 pub entry_abi: CanonicalAbiInfo,
1222 pub value_offset32: u32,
1225 pub value_offset64: u32,
1228}
1229
1230#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1232pub struct TypeFixedLengthList {
1233 pub element: InterfaceType,
1235 pub size: u32,
1237 pub abi: CanonicalAbiInfo,
1239}
1240
1241pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1243 MAX_FLAT_PARAMS
1244} else {
1245 MAX_FLAT_RESULTS
1246};
1247
1248const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1249 const MAX: u8 = MAX_FLAT_TYPES as u8;
1250 let sum = match (a, b) {
1251 (Some(a), Some(b)) => match a.checked_add(b) {
1252 Some(c) => c,
1253 None => return None,
1254 },
1255 _ => return None,
1256 };
1257 if sum > MAX { None } else { Some(sum) }
1258}
1259
1260const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1261 match (a, b) {
1262 (Some(a), Some(b)) => {
1263 if a > b {
1264 Some(a)
1265 } else {
1266 Some(b)
1267 }
1268 }
1269 _ => None,
1270 }
1271}
1272
1273pub struct FlatTypes<'a> {
1275 pub memory32: &'a [FlatType],
1277 pub memory64: &'a [FlatType],
1279}
1280
1281impl FlatTypes<'_> {
1282 pub fn len(&self) -> usize {
1286 assert_eq!(self.memory32.len(), self.memory64.len());
1287 self.memory32.len()
1288 }
1289}
1290
1291#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1295#[expect(missing_docs, reason = "self-describing variants")]
1296pub enum FlatType {
1297 I32,
1298 I64,
1299 F32,
1300 F64,
1301}