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 TypeFutureIndex(u32);
94
95 pub struct TypeFutureTableIndex(u32);
100
101 pub struct TypeStreamIndex(u32);
103
104 pub struct TypeStreamTableIndex(u32);
109
110 pub struct TypeComponentLocalErrorContextTableIndex(u32);
115
116 pub struct TypeComponentGlobalErrorContextTableIndex(u32);
122
123 pub struct TypeResourceTableIndex(u32);
138
139 pub struct ResourceIndex(u32);
152
153 pub struct DefinedResourceIndex(u32);
159
160 pub struct ModuleUpvarIndex(u32);
167
168 pub struct ComponentUpvarIndex(u32);
170
171 pub struct StaticComponentIndex(u32);
173
174 pub struct RuntimeInstanceIndex(u32);
183
184 pub struct RuntimeComponentInstanceIndex(u32);
186
187 pub struct ImportIndex(u32);
192
193 pub struct RuntimeImportIndex(u32);
199
200 pub struct LoweredIndex(u32);
206
207 pub struct RuntimeMemoryIndex(u32);
215
216 pub struct RuntimeReallocIndex(u32);
218
219 pub struct RuntimeCallbackIndex(u32);
221
222 pub struct RuntimePostReturnIndex(u32);
224
225 pub struct RuntimeTableIndex(u32);
232
233 pub struct TrampolineIndex(u32);
240
241 pub struct ExportIndex(u32);
243
244 pub struct OptionsIndex(u32);
246
247 pub struct AbstractResourceIndex(u32);
254}
255
256pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
259
260#[derive(Debug, Clone, Copy)]
263#[expect(missing_docs, reason = "self-describing variants")]
264pub enum ComponentItem {
265 Func(ComponentFuncIndex),
266 Module(ModuleIndex),
267 Component(ComponentIndex),
268 ComponentInstance(ComponentInstanceIndex),
269 Type(ComponentAnyTypeId),
270}
271
272#[derive(Default, Serialize, Deserialize)]
278pub struct ComponentTypes {
279 pub(super) modules: PrimaryMap<TypeModuleIndex, TypeModule>,
280 pub(super) components: PrimaryMap<TypeComponentIndex, TypeComponent>,
281 pub(super) component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
282 pub(super) functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
283 pub(super) lists: PrimaryMap<TypeListIndex, TypeList>,
284 pub(super) records: PrimaryMap<TypeRecordIndex, TypeRecord>,
285 pub(super) variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
286 pub(super) tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
287 pub(super) enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
288 pub(super) flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
289 pub(super) options: PrimaryMap<TypeOptionIndex, TypeOption>,
290 pub(super) results: PrimaryMap<TypeResultIndex, TypeResult>,
291 pub(super) resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
292 pub(super) module_types: Option<ModuleTypes>,
293 pub(super) futures: PrimaryMap<TypeFutureIndex, TypeFuture>,
294 pub(super) future_tables: PrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
295 pub(super) streams: PrimaryMap<TypeStreamIndex, TypeStream>,
296 pub(super) stream_tables: PrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
297 pub(super) error_context_tables:
298 PrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
299}
300
301impl TypeTrace for ComponentTypes {
302 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
303 where
304 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
305 {
306 for (_, m) in &self.modules {
307 m.trace(func)?;
308 }
309 if let Some(m) = self.module_types.as_ref() {
310 m.trace(func)?;
311 }
312 Ok(())
313 }
314
315 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
316 where
317 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
318 {
319 for (_, m) in &mut self.modules {
320 m.trace_mut(func)?;
321 }
322 if let Some(m) = self.module_types.as_mut() {
323 m.trace_mut(func)?;
324 }
325 Ok(())
326 }
327}
328
329impl ComponentTypes {
330 pub fn module_types(&self) -> &ModuleTypes {
332 self.module_types.as_ref().unwrap()
333 }
334
335 pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
337 self.module_types.as_mut().unwrap()
338 }
339
340 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
342 match ty {
343 InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
344 &CanonicalAbiInfo::SCALAR1
345 }
346
347 InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
348
349 InterfaceType::U32
350 | InterfaceType::S32
351 | InterfaceType::Float32
352 | InterfaceType::Char
353 | InterfaceType::Own(_)
354 | InterfaceType::Borrow(_)
355 | InterfaceType::Future(_)
356 | InterfaceType::Stream(_)
357 | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
358
359 InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
360 &CanonicalAbiInfo::SCALAR8
361 }
362
363 InterfaceType::String | InterfaceType::List(_) => &CanonicalAbiInfo::POINTER_PAIR,
364
365 InterfaceType::Record(i) => &self[*i].abi,
366 InterfaceType::Variant(i) => &self[*i].abi,
367 InterfaceType::Tuple(i) => &self[*i].abi,
368 InterfaceType::Flags(i) => &self[*i].abi,
369 InterfaceType::Enum(i) => &self[*i].abi,
370 InterfaceType::Option(i) => &self[*i].abi,
371 InterfaceType::Result(i) => &self[*i].abi,
372 }
373 }
374
375 pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
377 self.resource_tables.push(table)
378 }
379}
380
381macro_rules! impl_index {
382 ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
383 impl core::ops::Index<$ty> for ComponentTypes {
384 type Output = $output;
385 #[inline]
386 fn index(&self, idx: $ty) -> &$output {
387 &self.$field[idx]
388 }
389 }
390
391 #[cfg(feature = "compile")]
392 impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
393 type Output = $output;
394 #[inline]
395 fn index(&self, idx: $ty) -> &$output {
396 &self.component_types()[idx]
397 }
398 }
399 )*)
400}
401
402impl_index! {
403 impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
404 impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
405 impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
406 impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
407 impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
408 impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
409 impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
410 impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
411 impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
412 impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
413 impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
414 impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
415 impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
416 impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
417 impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
418 impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
419 impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
420 impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
421}
422
423impl<T> Index<T> for ComponentTypes
426where
427 ModuleTypes: Index<T>,
428{
429 type Output = <ModuleTypes as Index<T>>::Output;
430 fn index(&self, idx: T) -> &Self::Output {
431 self.module_types.as_ref().unwrap().index(idx)
432 }
433}
434
435#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
441pub enum TypeDef {
442 Component(TypeComponentIndex),
444 ComponentInstance(TypeComponentInstanceIndex),
446 ComponentFunc(TypeFuncIndex),
448 Interface(InterfaceType),
450 Module(TypeModuleIndex),
452 CoreFunc(ModuleInternedTypeIndex),
454 Resource(TypeResourceTableIndex),
459}
460
461impl TypeDef {
462 pub fn desc(&self) -> &str {
464 match self {
465 TypeDef::Component(_) => "component",
466 TypeDef::ComponentInstance(_) => "instance",
467 TypeDef::ComponentFunc(_) => "function",
468 TypeDef::Interface(_) => "type",
469 TypeDef::Module(_) => "core module",
470 TypeDef::CoreFunc(_) => "core function",
471 TypeDef::Resource(_) => "resource",
472 }
473 }
474}
475
476#[derive(Serialize, Deserialize, Default)]
486pub struct TypeModule {
487 pub imports: IndexMap<(String, String), EntityType>,
495
496 pub exports: IndexMap<String, EntityType>,
501}
502
503impl TypeTrace for TypeModule {
504 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
505 where
506 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
507 {
508 for ty in self.imports.values() {
509 ty.trace(func)?;
510 }
511 for ty in self.exports.values() {
512 ty.trace(func)?;
513 }
514 Ok(())
515 }
516
517 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
518 where
519 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
520 {
521 for ty in self.imports.values_mut() {
522 ty.trace_mut(func)?;
523 }
524 for ty in self.exports.values_mut() {
525 ty.trace_mut(func)?;
526 }
527 Ok(())
528 }
529}
530
531#[derive(Serialize, Deserialize, Default)]
533pub struct TypeComponent {
534 pub imports: IndexMap<String, TypeDef>,
536 pub exports: IndexMap<String, TypeDef>,
538}
539
540#[derive(Serialize, Deserialize, Default)]
545pub struct TypeComponentInstance {
546 pub exports: IndexMap<String, TypeDef>,
548}
549
550#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
552pub struct TypeFunc {
553 pub async_: bool,
555 pub param_names: Vec<String>,
557 pub params: TypeTupleIndex,
559 pub results: TypeTupleIndex,
561}
562
563#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
570#[expect(missing_docs, reason = "self-describing variants")]
571pub enum InterfaceType {
572 Bool,
573 S8,
574 U8,
575 S16,
576 U16,
577 S32,
578 U32,
579 S64,
580 U64,
581 Float32,
582 Float64,
583 Char,
584 String,
585 Record(TypeRecordIndex),
586 Variant(TypeVariantIndex),
587 List(TypeListIndex),
588 Tuple(TypeTupleIndex),
589 Flags(TypeFlagsIndex),
590 Enum(TypeEnumIndex),
591 Option(TypeOptionIndex),
592 Result(TypeResultIndex),
593 Own(TypeResourceTableIndex),
594 Borrow(TypeResourceTableIndex),
595 Future(TypeFutureTableIndex),
596 Stream(TypeStreamTableIndex),
597 ErrorContext(TypeComponentLocalErrorContextTableIndex),
598}
599
600#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
603pub struct CanonicalAbiInfo {
604 pub size32: u32,
606 pub align32: u32,
608 pub size64: u32,
610 pub align64: u32,
612 pub flat_count: Option<u8>,
619}
620
621impl Default for CanonicalAbiInfo {
622 fn default() -> CanonicalAbiInfo {
623 CanonicalAbiInfo {
624 size32: 0,
625 align32: 1,
626 size64: 0,
627 align64: 1,
628 flat_count: Some(0),
629 }
630 }
631}
632
633const fn align_to(a: u32, b: u32) -> u32 {
634 assert!(b.is_power_of_two());
635 (a + (b - 1)) & !(b - 1)
636}
637
638const fn max(a: u32, b: u32) -> u32 {
639 if a > b { a } else { b }
640}
641
642impl CanonicalAbiInfo {
643 pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
645 size32: 0,
646 align32: 1,
647 size64: 0,
648 align64: 1,
649 flat_count: Some(0),
650 };
651
652 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
654 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
656 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
658 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
660
661 const fn scalar(size: u32) -> CanonicalAbiInfo {
662 CanonicalAbiInfo {
663 size32: size,
664 align32: size,
665 size64: size,
666 align64: size,
667 flat_count: Some(1),
668 }
669 }
670
671 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
673 size32: 8,
674 align32: 4,
675 size64: 16,
676 align64: 8,
677 flat_count: Some(2),
678 };
679
680 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
682 let mut ret = CanonicalAbiInfo::default();
686 for field in fields {
687 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
688 ret.align32 = ret.align32.max(field.align32);
689 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
690 ret.align64 = ret.align64.max(field.align64);
691 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
692 }
693 ret.size32 = align_to(ret.size32, ret.align32);
694 ret.size64 = align_to(ret.size64, ret.align64);
695 return ret;
696 }
697
698 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
700 let mut ret = CanonicalAbiInfo::ZERO;
704 let mut i = 0;
705 while i < fields.len() {
706 let field = &fields[i];
707 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
708 ret.align32 = max(ret.align32, field.align32);
709 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
710 ret.align64 = max(ret.align64, field.align64);
711 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
712 i += 1;
713 }
714 ret.size32 = align_to(ret.size32, ret.align32);
715 ret.size64 = align_to(ret.size64, ret.align64);
716 return ret;
717 }
718
719 pub fn next_field32(&self, offset: &mut u32) -> u32 {
722 *offset = align_to(*offset, self.align32) + self.size32;
723 *offset - self.size32
724 }
725
726 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
728 let cur = u32::try_from(*offset).unwrap();
729 let cur = align_to(cur, self.align32) + self.size32;
730 *offset = usize::try_from(cur).unwrap();
731 usize::try_from(cur - self.size32).unwrap()
732 }
733
734 pub fn next_field64(&self, offset: &mut u32) -> u32 {
737 *offset = align_to(*offset, self.align64) + self.size64;
738 *offset - self.size64
739 }
740
741 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
743 let cur = u32::try_from(*offset).unwrap();
744 let cur = align_to(cur, self.align64) + self.size64;
745 *offset = usize::try_from(cur).unwrap();
746 usize::try_from(cur - self.size64).unwrap()
747 }
748
749 pub const fn flags(count: usize) -> CanonicalAbiInfo {
751 let (size, align, flat_count) = match FlagsSize::from_count(count) {
752 FlagsSize::Size0 => (0, 1, 0),
753 FlagsSize::Size1 => (1, 1, 1),
754 FlagsSize::Size2 => (2, 2, 1),
755 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
756 };
757 CanonicalAbiInfo {
758 size32: size,
759 align32: align,
760 size64: size,
761 align64: align,
762 flat_count: Some(flat_count),
763 }
764 }
765
766 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
767 where
768 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
769 I::IntoIter: ExactSizeIterator,
770 {
771 let cases = cases.into_iter();
775 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
776 let mut max_size32 = 0;
777 let mut max_align32 = discrim_size;
778 let mut max_size64 = 0;
779 let mut max_align64 = discrim_size;
780 let mut max_case_count = Some(0);
781 for case in cases {
782 if let Some(case) = case {
783 max_size32 = max_size32.max(case.size32);
784 max_align32 = max_align32.max(case.align32);
785 max_size64 = max_size64.max(case.size64);
786 max_align64 = max_align64.max(case.align64);
787 max_case_count = max_flat(max_case_count, case.flat_count);
788 }
789 }
790 CanonicalAbiInfo {
791 size32: align_to(
792 align_to(discrim_size, max_align32) + max_size32,
793 max_align32,
794 ),
795 align32: max_align32,
796 size64: align_to(
797 align_to(discrim_size, max_align64) + max_size64,
798 max_align64,
799 ),
800 align64: max_align64,
801 flat_count: add_flat(max_case_count, Some(1)),
802 }
803 }
804
805 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
807 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
811 Some(size) => size.byte_size(),
812 None => unreachable!(),
813 };
814 let mut max_size32 = 0;
815 let mut max_align32 = discrim_size;
816 let mut max_size64 = 0;
817 let mut max_align64 = discrim_size;
818 let mut max_case_count = Some(0);
819 let mut i = 0;
820 while i < cases.len() {
821 let case = &cases[i];
822 if let Some(case) = case {
823 max_size32 = max(max_size32, case.size32);
824 max_align32 = max(max_align32, case.align32);
825 max_size64 = max(max_size64, case.size64);
826 max_align64 = max(max_align64, case.align64);
827 max_case_count = max_flat(max_case_count, case.flat_count);
828 }
829 i += 1;
830 }
831 CanonicalAbiInfo {
832 size32: align_to(
833 align_to(discrim_size, max_align32) + max_size32,
834 max_align32,
835 ),
836 align32: max_align32,
837 size64: align_to(
838 align_to(discrim_size, max_align64) + max_size64,
839 max_align64,
840 ),
841 align64: max_align64,
842 flat_count: add_flat(max_case_count, Some(1)),
843 }
844 }
845
846 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
848 let discrim_size = match DiscriminantSize::from_count(cases) {
852 Some(size) => size.byte_size(),
853 None => unreachable!(),
854 };
855 CanonicalAbiInfo {
856 size32: discrim_size,
857 align32: discrim_size,
858 size64: discrim_size,
859 align64: discrim_size,
860 flat_count: Some(1),
861 }
862 }
863
864 pub fn flat_count(&self, max: usize) -> Option<usize> {
867 let flat = usize::from(self.flat_count?);
868 if flat > max { None } else { Some(flat) }
869 }
870}
871
872#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
874pub struct VariantInfo {
875 #[serde(with = "serde_discrim_size")]
877 pub size: DiscriminantSize,
878 pub payload_offset32: u32,
881 pub payload_offset64: u32,
884}
885
886impl VariantInfo {
887 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
890 where
891 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
892 I::IntoIter: ExactSizeIterator,
893 {
894 let cases = cases.into_iter();
895 let size = DiscriminantSize::from_count(cases.len()).unwrap();
896 let abi = CanonicalAbiInfo::variant(cases);
897 (
898 VariantInfo {
899 size,
900 payload_offset32: align_to(u32::from(size), abi.align32),
901 payload_offset64: align_to(u32::from(size), abi.align64),
902 },
903 abi,
904 )
905 }
906 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
908 let size = match DiscriminantSize::from_count(cases.len()) {
909 Some(size) => size,
910 None => unreachable!(),
911 };
912 let abi = CanonicalAbiInfo::variant_static(cases);
913 VariantInfo {
914 size,
915 payload_offset32: align_to(size.byte_size(), abi.align32),
916 payload_offset64: align_to(size.byte_size(), abi.align64),
917 }
918 }
919}
920
921mod serde_discrim_size {
922 use super::DiscriminantSize;
923 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
924
925 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
926 where
927 S: Serializer,
928 {
929 u32::from(*disc).serialize(ser)
930 }
931
932 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
933 where
934 D: Deserializer<'de>,
935 {
936 match u32::deserialize(deser)? {
937 1 => Ok(DiscriminantSize::Size1),
938 2 => Ok(DiscriminantSize::Size2),
939 4 => Ok(DiscriminantSize::Size4),
940 _ => Err(D::Error::custom("invalid discriminant size")),
941 }
942 }
943}
944
945#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
949pub struct TypeRecord {
950 pub fields: Box<[RecordField]>,
952 pub abi: CanonicalAbiInfo,
954}
955
956#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
958pub struct RecordField {
959 pub name: String,
961 pub ty: InterfaceType,
963}
964
965#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
971pub struct TypeVariant {
972 pub cases: IndexMap<String, Option<InterfaceType>>,
974 pub abi: CanonicalAbiInfo,
976 pub info: VariantInfo,
978}
979
980impl Hash for TypeVariant {
981 fn hash<H: Hasher>(&self, h: &mut H) {
982 let TypeVariant { cases, abi, info } = self;
983 cases.len().hash(h);
984 for pair in cases {
985 pair.hash(h);
986 }
987 abi.hash(h);
988 info.hash(h);
989 }
990}
991
992#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
997pub struct TypeTuple {
998 pub types: Box<[InterfaceType]>,
1000 pub abi: CanonicalAbiInfo,
1002}
1003
1004#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1009pub struct TypeFlags {
1010 pub names: IndexSet<String>,
1012 pub abi: CanonicalAbiInfo,
1014}
1015
1016impl Hash for TypeFlags {
1017 fn hash<H: Hasher>(&self, h: &mut H) {
1018 let TypeFlags { names, abi } = self;
1019 names.len().hash(h);
1020 for name in names {
1021 name.hash(h);
1022 }
1023 abi.hash(h);
1024 }
1025}
1026
1027#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1033pub struct TypeEnum {
1034 pub names: IndexSet<String>,
1036 pub abi: CanonicalAbiInfo,
1038 pub info: VariantInfo,
1040}
1041
1042impl Hash for TypeEnum {
1043 fn hash<H: Hasher>(&self, h: &mut H) {
1044 let TypeEnum { names, abi, info } = self;
1045 names.len().hash(h);
1046 for name in names {
1047 name.hash(h);
1048 }
1049 abi.hash(h);
1050 info.hash(h);
1051 }
1052}
1053
1054#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1056pub struct TypeOption {
1057 pub ty: InterfaceType,
1059 pub abi: CanonicalAbiInfo,
1061 pub info: VariantInfo,
1063}
1064
1065#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1067pub struct TypeResult {
1068 pub ok: Option<InterfaceType>,
1070 pub err: Option<InterfaceType>,
1072 pub abi: CanonicalAbiInfo,
1074 pub info: VariantInfo,
1076}
1077
1078#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1080pub struct TypeFuture {
1081 pub payload: Option<InterfaceType>,
1083}
1084
1085#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1087pub struct TypeFutureTable {
1088 pub ty: TypeFutureIndex,
1090 pub instance: RuntimeComponentInstanceIndex,
1092}
1093
1094#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1096pub struct TypeStream {
1097 pub payload: Option<InterfaceType>,
1099}
1100
1101#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1103pub struct TypeStreamTable {
1104 pub ty: TypeStreamIndex,
1106 pub instance: RuntimeComponentInstanceIndex,
1108}
1109
1110#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1112pub struct TypeErrorContextTable {
1113 pub instance: RuntimeComponentInstanceIndex,
1115}
1116
1117#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1119pub enum TypeResourceTable {
1120 Concrete {
1127 ty: ResourceIndex,
1132
1133 instance: RuntimeComponentInstanceIndex,
1135 },
1136
1137 Abstract(AbstractResourceIndex),
1141}
1142
1143impl TypeResourceTable {
1144 pub fn unwrap_concrete_ty(&self) -> ResourceIndex {
1151 match self {
1152 TypeResourceTable::Concrete { ty, .. } => *ty,
1153 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1154 }
1155 }
1156
1157 pub fn unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex {
1164 match self {
1165 TypeResourceTable::Concrete { instance, .. } => *instance,
1166 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1167 }
1168 }
1169}
1170
1171#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1173pub struct TypeList {
1174 pub element: InterfaceType,
1176}
1177
1178pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1180 MAX_FLAT_PARAMS
1181} else {
1182 MAX_FLAT_RESULTS
1183};
1184
1185const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1186 const MAX: u8 = MAX_FLAT_TYPES as u8;
1187 let sum = match (a, b) {
1188 (Some(a), Some(b)) => match a.checked_add(b) {
1189 Some(c) => c,
1190 None => return None,
1191 },
1192 _ => return None,
1193 };
1194 if sum > MAX { None } else { Some(sum) }
1195}
1196
1197const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1198 match (a, b) {
1199 (Some(a), Some(b)) => {
1200 if a > b {
1201 Some(a)
1202 } else {
1203 Some(b)
1204 }
1205 }
1206 _ => None,
1207 }
1208}
1209
1210pub struct FlatTypes<'a> {
1212 pub memory32: &'a [FlatType],
1214 pub memory64: &'a [FlatType],
1216}
1217
1218impl FlatTypes<'_> {
1219 pub fn len(&self) -> usize {
1223 assert_eq!(self.memory32.len(), self.memory64.len());
1224 self.memory32.len()
1225 }
1226}
1227
1228#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1232#[expect(missing_docs, reason = "self-describing variants")]
1233pub enum FlatType {
1234 I32,
1235 I64,
1236 F32,
1237 F64,
1238}