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 TypeMapIndex(u32);
94 pub struct TypeFixedLengthListIndex(u32);
96 pub struct TypeFutureIndex(u32);
98
99 pub struct TypeFutureTableIndex(u32);
104
105 pub struct TypeStreamIndex(u32);
107
108 pub struct TypeStreamTableIndex(u32);
113
114 pub struct TypeComponentLocalErrorContextTableIndex(u32);
119
120 pub struct TypeComponentGlobalErrorContextTableIndex(u32);
126
127 pub struct TypeResourceTableIndex(u32);
142
143 pub struct ResourceIndex(u32);
156
157 pub struct DefinedResourceIndex(u32);
163
164 pub struct ModuleUpvarIndex(u32);
171
172 pub struct ComponentUpvarIndex(u32);
174
175 pub struct StaticComponentIndex(u32);
177
178 pub struct RuntimeInstanceIndex(u32);
187
188 pub struct RuntimeComponentInstanceIndex(u32);
190
191 pub struct ImportIndex(u32);
196
197 pub struct RuntimeImportIndex(u32);
203
204 pub struct LoweredIndex(u32);
210
211 pub struct RuntimeMemoryIndex(u32);
219
220 pub struct RuntimeReallocIndex(u32);
222
223 pub struct RuntimeCallbackIndex(u32);
225
226 pub struct RuntimePostReturnIndex(u32);
228
229 pub struct RuntimeTableIndex(u32);
236
237 pub struct TrampolineIndex(u32);
244
245 pub struct ExportIndex(u32);
247
248 pub struct OptionsIndex(u32);
250
251 pub struct AbstractResourceIndex(u32);
258}
259
260pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
263
264#[derive(Debug, Clone, Copy)]
267#[expect(missing_docs, reason = "self-describing variants")]
268pub enum ComponentItem {
269 Func(ComponentFuncIndex),
270 Module(ModuleIndex),
271 Component(ComponentIndex),
272 ComponentInstance(ComponentInstanceIndex),
273 Type(ComponentAnyTypeId),
274}
275
276#[derive(Default, Serialize, Deserialize)]
282pub 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
307impl TypeTrace for ComponentTypes {
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
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
335impl ComponentTypes {
336 pub fn module_types(&self) -> &ModuleTypes {
338 self.module_types.as_ref().unwrap()
339 }
340
341 pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
343 self.module_types.as_mut().unwrap()
344 }
345
346 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 pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
386 self.resource_tables.push(table)
387 }
388}
389
390macro_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
411impl_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
434impl<T> Index<T> for ComponentTypes
437where
438 ModuleTypes: Index<T>,
439{
440 type Output = <ModuleTypes as Index<T>>::Output;
441 fn index(&self, idx: T) -> &Self::Output {
442 self.module_types.as_ref().unwrap().index(idx)
443 }
444}
445
446#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
452pub enum TypeDef {
453 Component(TypeComponentIndex),
455 ComponentInstance(TypeComponentInstanceIndex),
457 ComponentFunc(TypeFuncIndex),
459 Interface(InterfaceType),
461 Module(TypeModuleIndex),
463 CoreFunc(ModuleInternedTypeIndex),
465 Resource(TypeResourceTableIndex),
470}
471
472impl TypeDef {
473 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#[derive(Serialize, Deserialize, Default)]
497pub struct TypeModule {
498 pub imports: IndexMap<(String, String), EntityType>,
506
507 pub exports: IndexMap<String, EntityType>,
512}
513
514impl TypeTrace for TypeModule {
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
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#[derive(Serialize, Deserialize, Default)]
544pub struct TypeComponent {
545 pub imports: IndexMap<String, TypeDef>,
547 pub exports: IndexMap<String, TypeDef>,
549}
550
551#[derive(Serialize, Deserialize, Default)]
556pub struct TypeComponentInstance {
557 pub exports: IndexMap<String, TypeDef>,
559}
560
561#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
563pub struct TypeFunc {
564 pub async_: bool,
566 pub param_names: Vec<String>,
568 pub params: TypeTupleIndex,
570 pub results: TypeTupleIndex,
572}
573
574#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
581#[expect(missing_docs, reason = "self-describing variants")]
582pub 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#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
616pub struct CanonicalAbiInfo {
617 pub size32: u32,
619 pub align32: u32,
621 pub size64: u32,
623 pub align64: u32,
625 pub flat_count: Option<u8>,
632}
633
634impl Default for CanonicalAbiInfo {
635 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
646const fn align_to(a: u32, b: u32) -> u32 {
647 assert!(b.is_power_of_two());
648 (a + (b - 1)) & !(b - 1)
649}
650
651const fn max(a: u32, b: u32) -> u32 {
652 if a > b { a } else { b }
653}
654
655impl CanonicalAbiInfo {
656 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 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
667 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
669 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
671 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
673
674 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 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 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
695 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 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
713 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 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 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 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 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 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
779 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
780 where
781 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
782 I::IntoIter: ExactSizeIterator,
783 {
784 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 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
820 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 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
861 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 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#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
887pub struct VariantInfo {
888 #[serde(with = "serde_discrim_size")]
890 pub size: DiscriminantSize,
891 pub payload_offset32: u32,
894 pub payload_offset64: u32,
897}
898
899impl VariantInfo {
900 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 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
934mod serde_discrim_size {
935 use super::DiscriminantSize;
936 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
937
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
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#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
962pub struct TypeRecord {
963 pub fields: Box<[RecordField]>,
965 pub abi: CanonicalAbiInfo,
967}
968
969#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
971pub struct RecordField {
972 pub name: String,
974 pub ty: InterfaceType,
976}
977
978#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
984pub struct TypeVariant {
985 pub cases: IndexMap<String, Option<InterfaceType>>,
987 pub abi: CanonicalAbiInfo,
989 pub info: VariantInfo,
991}
992
993impl Hash for TypeVariant {
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#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1010pub struct TypeTuple {
1011 pub types: Box<[InterfaceType]>,
1013 pub abi: CanonicalAbiInfo,
1015}
1016
1017#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1022pub struct TypeFlags {
1023 pub names: IndexSet<String>,
1025 pub abi: CanonicalAbiInfo,
1027}
1028
1029impl Hash for TypeFlags {
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#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1046pub struct TypeEnum {
1047 pub names: IndexSet<String>,
1049 pub abi: CanonicalAbiInfo,
1051 pub info: VariantInfo,
1053}
1054
1055impl Hash for TypeEnum {
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#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1069pub struct TypeOption {
1070 pub ty: InterfaceType,
1072 pub abi: CanonicalAbiInfo,
1074 pub info: VariantInfo,
1076}
1077
1078#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1080pub struct TypeResult {
1081 pub ok: Option<InterfaceType>,
1083 pub err: Option<InterfaceType>,
1085 pub abi: CanonicalAbiInfo,
1087 pub info: VariantInfo,
1089}
1090
1091#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1093pub struct TypeFuture {
1094 pub payload: Option<InterfaceType>,
1096}
1097
1098#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1100pub struct TypeFutureTable {
1101 pub ty: TypeFutureIndex,
1103 pub instance: RuntimeComponentInstanceIndex,
1105}
1106
1107#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1109pub struct TypeStream {
1110 pub payload: Option<InterfaceType>,
1112}
1113
1114#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1116pub struct TypeStreamTable {
1117 pub ty: TypeStreamIndex,
1119 pub instance: RuntimeComponentInstanceIndex,
1121}
1122
1123#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1125pub struct TypeErrorContextTable {
1126 pub instance: RuntimeComponentInstanceIndex,
1128}
1129
1130#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1132pub enum TypeResourceTable {
1133 Concrete {
1140 ty: ResourceIndex,
1145
1146 instance: RuntimeComponentInstanceIndex,
1148 },
1149
1150 Abstract(AbstractResourceIndex),
1154}
1155
1156impl TypeResourceTable {
1157 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 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#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1186pub struct TypeList {
1187 pub element: InterfaceType,
1189}
1190
1191#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1193pub struct TypeMap {
1194 pub key: InterfaceType,
1196 pub value: InterfaceType,
1198 pub entry_abi: CanonicalAbiInfo,
1200 pub value_offset32: u32,
1203 pub value_offset64: u32,
1206}
1207
1208#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1210pub struct TypeFixedLengthList {
1211 pub element: InterfaceType,
1213 pub size: u32,
1215 pub abi: CanonicalAbiInfo,
1217}
1218
1219pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1221 MAX_FLAT_PARAMS
1222} else {
1223 MAX_FLAT_RESULTS
1224};
1225
1226const 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
1238const 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
1251pub struct FlatTypes<'a> {
1253 pub memory32: &'a [FlatType],
1255 pub memory64: &'a [FlatType],
1257}
1258
1259impl FlatTypes<'_> {
1260 pub fn len(&self) -> usize {
1264 assert_eq!(self.memory32.len(), self.memory64.len());
1265 self.memory32.len()
1266 }
1267}
1268
1269#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1273#[expect(missing_docs, reason = "self-describing variants")]
1274pub enum FlatType {
1275 I32,
1276 I64,
1277 F32,
1278 F64,
1279}