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
245pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
248
249#[derive(Debug, Clone, Copy)]
252#[expect(missing_docs, reason = "self-describing variants")]
253pub enum ComponentItem {
254 Func(ComponentFuncIndex),
255 Module(ModuleIndex),
256 Component(ComponentIndex),
257 ComponentInstance(ComponentInstanceIndex),
258 Type(ComponentAnyTypeId),
259}
260
261#[derive(Default, Serialize, Deserialize)]
267pub struct ComponentTypes {
268 pub(super) modules: PrimaryMap<TypeModuleIndex, TypeModule>,
269 pub(super) components: PrimaryMap<TypeComponentIndex, TypeComponent>,
270 pub(super) component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
271 pub(super) functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
272 pub(super) lists: PrimaryMap<TypeListIndex, TypeList>,
273 pub(super) records: PrimaryMap<TypeRecordIndex, TypeRecord>,
274 pub(super) variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
275 pub(super) tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
276 pub(super) enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
277 pub(super) flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
278 pub(super) options: PrimaryMap<TypeOptionIndex, TypeOption>,
279 pub(super) results: PrimaryMap<TypeResultIndex, TypeResult>,
280 pub(super) resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
281 pub(super) module_types: Option<ModuleTypes>,
282 pub(super) futures: PrimaryMap<TypeFutureIndex, TypeFuture>,
283 pub(super) future_tables: PrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
284 pub(super) streams: PrimaryMap<TypeStreamIndex, TypeStream>,
285 pub(super) stream_tables: PrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
286 pub(super) error_context_tables:
287 PrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
288}
289
290impl TypeTrace for ComponentTypes {
291 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
292 where
293 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
294 {
295 for (_, m) in &self.modules {
296 m.trace(func)?;
297 }
298 if let Some(m) = self.module_types.as_ref() {
299 m.trace(func)?;
300 }
301 Ok(())
302 }
303
304 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
305 where
306 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
307 {
308 for (_, m) in &mut self.modules {
309 m.trace_mut(func)?;
310 }
311 if let Some(m) = self.module_types.as_mut() {
312 m.trace_mut(func)?;
313 }
314 Ok(())
315 }
316}
317
318impl ComponentTypes {
319 pub fn module_types(&self) -> &ModuleTypes {
321 self.module_types.as_ref().unwrap()
322 }
323
324 pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
326 self.module_types.as_mut().unwrap()
327 }
328
329 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
331 match ty {
332 InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
333 &CanonicalAbiInfo::SCALAR1
334 }
335
336 InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
337
338 InterfaceType::U32
339 | InterfaceType::S32
340 | InterfaceType::Float32
341 | InterfaceType::Char
342 | InterfaceType::Own(_)
343 | InterfaceType::Borrow(_)
344 | InterfaceType::Future(_)
345 | InterfaceType::Stream(_)
346 | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
347
348 InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
349 &CanonicalAbiInfo::SCALAR8
350 }
351
352 InterfaceType::String | InterfaceType::List(_) => &CanonicalAbiInfo::POINTER_PAIR,
353
354 InterfaceType::Record(i) => &self[*i].abi,
355 InterfaceType::Variant(i) => &self[*i].abi,
356 InterfaceType::Tuple(i) => &self[*i].abi,
357 InterfaceType::Flags(i) => &self[*i].abi,
358 InterfaceType::Enum(i) => &self[*i].abi,
359 InterfaceType::Option(i) => &self[*i].abi,
360 InterfaceType::Result(i) => &self[*i].abi,
361 }
362 }
363
364 pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
366 self.resource_tables.push(table)
367 }
368}
369
370macro_rules! impl_index {
371 ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
372 impl core::ops::Index<$ty> for ComponentTypes {
373 type Output = $output;
374 #[inline]
375 fn index(&self, idx: $ty) -> &$output {
376 &self.$field[idx]
377 }
378 }
379
380 #[cfg(feature = "compile")]
381 impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
382 type Output = $output;
383 #[inline]
384 fn index(&self, idx: $ty) -> &$output {
385 &self.component_types()[idx]
386 }
387 }
388 )*)
389}
390
391impl_index! {
392 impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
393 impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
394 impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
395 impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
396 impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
397 impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
398 impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
399 impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
400 impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
401 impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
402 impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
403 impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
404 impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
405 impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
406 impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
407 impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
408 impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
409 impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
410}
411
412impl<T> Index<T> for ComponentTypes
415where
416 ModuleTypes: Index<T>,
417{
418 type Output = <ModuleTypes as Index<T>>::Output;
419 fn index(&self, idx: T) -> &Self::Output {
420 self.module_types.as_ref().unwrap().index(idx)
421 }
422}
423
424#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
430pub enum TypeDef {
431 Component(TypeComponentIndex),
433 ComponentInstance(TypeComponentInstanceIndex),
435 ComponentFunc(TypeFuncIndex),
437 Interface(InterfaceType),
439 Module(TypeModuleIndex),
441 CoreFunc(ModuleInternedTypeIndex),
443 Resource(TypeResourceTableIndex),
448}
449
450impl TypeDef {
451 pub fn desc(&self) -> &str {
453 match self {
454 TypeDef::Component(_) => "component",
455 TypeDef::ComponentInstance(_) => "instance",
456 TypeDef::ComponentFunc(_) => "function",
457 TypeDef::Interface(_) => "type",
458 TypeDef::Module(_) => "core module",
459 TypeDef::CoreFunc(_) => "core function",
460 TypeDef::Resource(_) => "resource",
461 }
462 }
463}
464
465#[derive(Serialize, Deserialize, Default)]
475pub struct TypeModule {
476 pub imports: IndexMap<(String, String), EntityType>,
484
485 pub exports: IndexMap<String, EntityType>,
490}
491
492impl TypeTrace for TypeModule {
493 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
494 where
495 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
496 {
497 for ty in self.imports.values() {
498 ty.trace(func)?;
499 }
500 for ty in self.exports.values() {
501 ty.trace(func)?;
502 }
503 Ok(())
504 }
505
506 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
507 where
508 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
509 {
510 for ty in self.imports.values_mut() {
511 ty.trace_mut(func)?;
512 }
513 for ty in self.exports.values_mut() {
514 ty.trace_mut(func)?;
515 }
516 Ok(())
517 }
518}
519
520#[derive(Serialize, Deserialize, Default)]
522pub struct TypeComponent {
523 pub imports: IndexMap<String, TypeDef>,
525 pub exports: IndexMap<String, TypeDef>,
527}
528
529#[derive(Serialize, Deserialize, Default)]
534pub struct TypeComponentInstance {
535 pub exports: IndexMap<String, TypeDef>,
537}
538
539#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
541pub struct TypeFunc {
542 pub param_names: Vec<String>,
544 pub params: TypeTupleIndex,
546 pub results: TypeTupleIndex,
548}
549
550#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
557#[expect(missing_docs, reason = "self-describing variants")]
558pub enum InterfaceType {
559 Bool,
560 S8,
561 U8,
562 S16,
563 U16,
564 S32,
565 U32,
566 S64,
567 U64,
568 Float32,
569 Float64,
570 Char,
571 String,
572 Record(TypeRecordIndex),
573 Variant(TypeVariantIndex),
574 List(TypeListIndex),
575 Tuple(TypeTupleIndex),
576 Flags(TypeFlagsIndex),
577 Enum(TypeEnumIndex),
578 Option(TypeOptionIndex),
579 Result(TypeResultIndex),
580 Own(TypeResourceTableIndex),
581 Borrow(TypeResourceTableIndex),
582 Future(TypeFutureTableIndex),
583 Stream(TypeStreamTableIndex),
584 ErrorContext(TypeComponentLocalErrorContextTableIndex),
585}
586
587#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
590pub struct CanonicalAbiInfo {
591 pub size32: u32,
593 pub align32: u32,
595 pub size64: u32,
597 pub align64: u32,
599 pub flat_count: Option<u8>,
606}
607
608impl Default for CanonicalAbiInfo {
609 fn default() -> CanonicalAbiInfo {
610 CanonicalAbiInfo {
611 size32: 0,
612 align32: 1,
613 size64: 0,
614 align64: 1,
615 flat_count: Some(0),
616 }
617 }
618}
619
620const fn align_to(a: u32, b: u32) -> u32 {
621 assert!(b.is_power_of_two());
622 (a + (b - 1)) & !(b - 1)
623}
624
625const fn max(a: u32, b: u32) -> u32 {
626 if a > b { a } else { b }
627}
628
629impl CanonicalAbiInfo {
630 pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
632 size32: 0,
633 align32: 1,
634 size64: 0,
635 align64: 1,
636 flat_count: Some(0),
637 };
638
639 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
641 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
643 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
645 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
647
648 const fn scalar(size: u32) -> CanonicalAbiInfo {
649 CanonicalAbiInfo {
650 size32: size,
651 align32: size,
652 size64: size,
653 align64: size,
654 flat_count: Some(1),
655 }
656 }
657
658 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
660 size32: 8,
661 align32: 4,
662 size64: 16,
663 align64: 8,
664 flat_count: Some(2),
665 };
666
667 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
669 let mut ret = CanonicalAbiInfo::default();
673 for field in fields {
674 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
675 ret.align32 = ret.align32.max(field.align32);
676 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
677 ret.align64 = ret.align64.max(field.align64);
678 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
679 }
680 ret.size32 = align_to(ret.size32, ret.align32);
681 ret.size64 = align_to(ret.size64, ret.align64);
682 return ret;
683 }
684
685 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
687 let mut ret = CanonicalAbiInfo::ZERO;
691 let mut i = 0;
692 while i < fields.len() {
693 let field = &fields[i];
694 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
695 ret.align32 = max(ret.align32, field.align32);
696 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
697 ret.align64 = max(ret.align64, field.align64);
698 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
699 i += 1;
700 }
701 ret.size32 = align_to(ret.size32, ret.align32);
702 ret.size64 = align_to(ret.size64, ret.align64);
703 return ret;
704 }
705
706 pub fn next_field32(&self, offset: &mut u32) -> u32 {
709 *offset = align_to(*offset, self.align32) + self.size32;
710 *offset - self.size32
711 }
712
713 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
715 let cur = u32::try_from(*offset).unwrap();
716 let cur = align_to(cur, self.align32) + self.size32;
717 *offset = usize::try_from(cur).unwrap();
718 usize::try_from(cur - self.size32).unwrap()
719 }
720
721 pub fn next_field64(&self, offset: &mut u32) -> u32 {
724 *offset = align_to(*offset, self.align64) + self.size64;
725 *offset - self.size64
726 }
727
728 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
730 let cur = u32::try_from(*offset).unwrap();
731 let cur = align_to(cur, self.align64) + self.size64;
732 *offset = usize::try_from(cur).unwrap();
733 usize::try_from(cur - self.size64).unwrap()
734 }
735
736 pub const fn flags(count: usize) -> CanonicalAbiInfo {
738 let (size, align, flat_count) = match FlagsSize::from_count(count) {
739 FlagsSize::Size0 => (0, 1, 0),
740 FlagsSize::Size1 => (1, 1, 1),
741 FlagsSize::Size2 => (2, 2, 1),
742 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
743 };
744 CanonicalAbiInfo {
745 size32: size,
746 align32: align,
747 size64: size,
748 align64: align,
749 flat_count: Some(flat_count),
750 }
751 }
752
753 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
754 where
755 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
756 I::IntoIter: ExactSizeIterator,
757 {
758 let cases = cases.into_iter();
762 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
763 let mut max_size32 = 0;
764 let mut max_align32 = discrim_size;
765 let mut max_size64 = 0;
766 let mut max_align64 = discrim_size;
767 let mut max_case_count = Some(0);
768 for case in cases {
769 if let Some(case) = case {
770 max_size32 = max_size32.max(case.size32);
771 max_align32 = max_align32.max(case.align32);
772 max_size64 = max_size64.max(case.size64);
773 max_align64 = max_align64.max(case.align64);
774 max_case_count = max_flat(max_case_count, case.flat_count);
775 }
776 }
777 CanonicalAbiInfo {
778 size32: align_to(
779 align_to(discrim_size, max_align32) + max_size32,
780 max_align32,
781 ),
782 align32: max_align32,
783 size64: align_to(
784 align_to(discrim_size, max_align64) + max_size64,
785 max_align64,
786 ),
787 align64: max_align64,
788 flat_count: add_flat(max_case_count, Some(1)),
789 }
790 }
791
792 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
794 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
798 Some(size) => size.byte_size(),
799 None => unreachable!(),
800 };
801 let mut max_size32 = 0;
802 let mut max_align32 = discrim_size;
803 let mut max_size64 = 0;
804 let mut max_align64 = discrim_size;
805 let mut max_case_count = Some(0);
806 let mut i = 0;
807 while i < cases.len() {
808 let case = &cases[i];
809 if let Some(case) = case {
810 max_size32 = max(max_size32, case.size32);
811 max_align32 = max(max_align32, case.align32);
812 max_size64 = max(max_size64, case.size64);
813 max_align64 = max(max_align64, case.align64);
814 max_case_count = max_flat(max_case_count, case.flat_count);
815 }
816 i += 1;
817 }
818 CanonicalAbiInfo {
819 size32: align_to(
820 align_to(discrim_size, max_align32) + max_size32,
821 max_align32,
822 ),
823 align32: max_align32,
824 size64: align_to(
825 align_to(discrim_size, max_align64) + max_size64,
826 max_align64,
827 ),
828 align64: max_align64,
829 flat_count: add_flat(max_case_count, Some(1)),
830 }
831 }
832
833 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
835 let discrim_size = match DiscriminantSize::from_count(cases) {
839 Some(size) => size.byte_size(),
840 None => unreachable!(),
841 };
842 CanonicalAbiInfo {
843 size32: discrim_size,
844 align32: discrim_size,
845 size64: discrim_size,
846 align64: discrim_size,
847 flat_count: Some(1),
848 }
849 }
850
851 pub fn flat_count(&self, max: usize) -> Option<usize> {
854 let flat = usize::from(self.flat_count?);
855 if flat > max { None } else { Some(flat) }
856 }
857}
858
859#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
861pub struct VariantInfo {
862 #[serde(with = "serde_discrim_size")]
864 pub size: DiscriminantSize,
865 pub payload_offset32: u32,
868 pub payload_offset64: u32,
871}
872
873impl VariantInfo {
874 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
877 where
878 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
879 I::IntoIter: ExactSizeIterator,
880 {
881 let cases = cases.into_iter();
882 let size = DiscriminantSize::from_count(cases.len()).unwrap();
883 let abi = CanonicalAbiInfo::variant(cases);
884 (
885 VariantInfo {
886 size,
887 payload_offset32: align_to(u32::from(size), abi.align32),
888 payload_offset64: align_to(u32::from(size), abi.align64),
889 },
890 abi,
891 )
892 }
893 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
895 let size = match DiscriminantSize::from_count(cases.len()) {
896 Some(size) => size,
897 None => unreachable!(),
898 };
899 let abi = CanonicalAbiInfo::variant_static(cases);
900 VariantInfo {
901 size,
902 payload_offset32: align_to(size.byte_size(), abi.align32),
903 payload_offset64: align_to(size.byte_size(), abi.align64),
904 }
905 }
906}
907
908mod serde_discrim_size {
909 use super::DiscriminantSize;
910 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
911
912 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
913 where
914 S: Serializer,
915 {
916 u32::from(*disc).serialize(ser)
917 }
918
919 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
920 where
921 D: Deserializer<'de>,
922 {
923 match u32::deserialize(deser)? {
924 1 => Ok(DiscriminantSize::Size1),
925 2 => Ok(DiscriminantSize::Size2),
926 4 => Ok(DiscriminantSize::Size4),
927 _ => Err(D::Error::custom("invalid discriminant size")),
928 }
929 }
930}
931
932#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
936pub struct TypeRecord {
937 pub fields: Box<[RecordField]>,
939 pub abi: CanonicalAbiInfo,
941}
942
943#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
945pub struct RecordField {
946 pub name: String,
948 pub ty: InterfaceType,
950}
951
952#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
958pub struct TypeVariant {
959 pub cases: IndexMap<String, Option<InterfaceType>>,
961 pub abi: CanonicalAbiInfo,
963 pub info: VariantInfo,
965}
966
967impl Hash for TypeVariant {
968 fn hash<H: Hasher>(&self, h: &mut H) {
969 let TypeVariant { cases, abi, info } = self;
970 cases.len().hash(h);
971 for pair in cases {
972 pair.hash(h);
973 }
974 abi.hash(h);
975 info.hash(h);
976 }
977}
978
979#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
984pub struct TypeTuple {
985 pub types: Box<[InterfaceType]>,
987 pub abi: CanonicalAbiInfo,
989}
990
991#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
996pub struct TypeFlags {
997 pub names: IndexSet<String>,
999 pub abi: CanonicalAbiInfo,
1001}
1002
1003impl Hash for TypeFlags {
1004 fn hash<H: Hasher>(&self, h: &mut H) {
1005 let TypeFlags { names, abi } = self;
1006 names.len().hash(h);
1007 for name in names {
1008 name.hash(h);
1009 }
1010 abi.hash(h);
1011 }
1012}
1013
1014#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1020pub struct TypeEnum {
1021 pub names: IndexSet<String>,
1023 pub abi: CanonicalAbiInfo,
1025 pub info: VariantInfo,
1027}
1028
1029impl Hash for TypeEnum {
1030 fn hash<H: Hasher>(&self, h: &mut H) {
1031 let TypeEnum { names, abi, info } = self;
1032 names.len().hash(h);
1033 for name in names {
1034 name.hash(h);
1035 }
1036 abi.hash(h);
1037 info.hash(h);
1038 }
1039}
1040
1041#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1043pub struct TypeOption {
1044 pub ty: InterfaceType,
1046 pub abi: CanonicalAbiInfo,
1048 pub info: VariantInfo,
1050}
1051
1052#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1054pub struct TypeResult {
1055 pub ok: Option<InterfaceType>,
1057 pub err: Option<InterfaceType>,
1059 pub abi: CanonicalAbiInfo,
1061 pub info: VariantInfo,
1063}
1064
1065#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1067pub struct TypeFuture {
1068 pub payload: Option<InterfaceType>,
1070}
1071
1072#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1074pub struct TypeFutureTable {
1075 pub ty: TypeFutureIndex,
1077 pub instance: RuntimeComponentInstanceIndex,
1079}
1080
1081#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1083pub struct TypeStream {
1084 pub payload: Option<InterfaceType>,
1086}
1087
1088#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1090pub struct TypeStreamTable {
1091 pub ty: TypeStreamIndex,
1093 pub instance: RuntimeComponentInstanceIndex,
1095}
1096
1097#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1099pub struct TypeErrorContextTable {
1100 pub instance: RuntimeComponentInstanceIndex,
1102}
1103
1104#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1106pub struct TypeResourceTable {
1107 pub ty: ResourceIndex,
1112
1113 pub instance: RuntimeComponentInstanceIndex,
1115}
1116
1117#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1119pub struct TypeList {
1120 pub element: InterfaceType,
1122}
1123
1124pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1126 MAX_FLAT_PARAMS
1127} else {
1128 MAX_FLAT_RESULTS
1129};
1130
1131const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1132 const MAX: u8 = MAX_FLAT_TYPES as u8;
1133 let sum = match (a, b) {
1134 (Some(a), Some(b)) => match a.checked_add(b) {
1135 Some(c) => c,
1136 None => return None,
1137 },
1138 _ => return None,
1139 };
1140 if sum > MAX { None } else { Some(sum) }
1141}
1142
1143const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1144 match (a, b) {
1145 (Some(a), Some(b)) => {
1146 if a > b {
1147 Some(a)
1148 } else {
1149 Some(b)
1150 }
1151 }
1152 _ => None,
1153 }
1154}
1155
1156pub struct FlatTypes<'a> {
1158 pub memory32: &'a [FlatType],
1160 pub memory64: &'a [FlatType],
1162}
1163
1164impl FlatTypes<'_> {
1165 pub fn len(&self) -> usize {
1169 assert_eq!(self.memory32.len(), self.memory64.len());
1170 self.memory32.len()
1171 }
1172}
1173
1174#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1178#[expect(missing_docs, reason = "self-describing variants")]
1179pub enum FlatType {
1180 I32,
1181 I64,
1182 F32,
1183 F64,
1184}