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
248pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
251
252#[derive(Debug, Clone, Copy)]
255#[expect(missing_docs, reason = "self-describing variants")]
256pub enum ComponentItem {
257 Func(ComponentFuncIndex),
258 Module(ModuleIndex),
259 Component(ComponentIndex),
260 ComponentInstance(ComponentInstanceIndex),
261 Type(ComponentAnyTypeId),
262}
263
264#[derive(Default, Serialize, Deserialize)]
270pub struct ComponentTypes {
271 pub(super) modules: PrimaryMap<TypeModuleIndex, TypeModule>,
272 pub(super) components: PrimaryMap<TypeComponentIndex, TypeComponent>,
273 pub(super) component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
274 pub(super) functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
275 pub(super) lists: PrimaryMap<TypeListIndex, TypeList>,
276 pub(super) records: PrimaryMap<TypeRecordIndex, TypeRecord>,
277 pub(super) variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
278 pub(super) tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
279 pub(super) enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
280 pub(super) flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
281 pub(super) options: PrimaryMap<TypeOptionIndex, TypeOption>,
282 pub(super) results: PrimaryMap<TypeResultIndex, TypeResult>,
283 pub(super) resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
284 pub(super) module_types: Option<ModuleTypes>,
285 pub(super) futures: PrimaryMap<TypeFutureIndex, TypeFuture>,
286 pub(super) future_tables: PrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
287 pub(super) streams: PrimaryMap<TypeStreamIndex, TypeStream>,
288 pub(super) stream_tables: PrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
289 pub(super) error_context_tables:
290 PrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
291}
292
293impl TypeTrace for ComponentTypes {
294 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
295 where
296 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
297 {
298 for (_, m) in &self.modules {
299 m.trace(func)?;
300 }
301 if let Some(m) = self.module_types.as_ref() {
302 m.trace(func)?;
303 }
304 Ok(())
305 }
306
307 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
308 where
309 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
310 {
311 for (_, m) in &mut self.modules {
312 m.trace_mut(func)?;
313 }
314 if let Some(m) = self.module_types.as_mut() {
315 m.trace_mut(func)?;
316 }
317 Ok(())
318 }
319}
320
321impl ComponentTypes {
322 pub fn module_types(&self) -> &ModuleTypes {
324 self.module_types.as_ref().unwrap()
325 }
326
327 pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
329 self.module_types.as_mut().unwrap()
330 }
331
332 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
334 match ty {
335 InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
336 &CanonicalAbiInfo::SCALAR1
337 }
338
339 InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
340
341 InterfaceType::U32
342 | InterfaceType::S32
343 | InterfaceType::Float32
344 | InterfaceType::Char
345 | InterfaceType::Own(_)
346 | InterfaceType::Borrow(_)
347 | InterfaceType::Future(_)
348 | InterfaceType::Stream(_)
349 | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
350
351 InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
352 &CanonicalAbiInfo::SCALAR8
353 }
354
355 InterfaceType::String | InterfaceType::List(_) => &CanonicalAbiInfo::POINTER_PAIR,
356
357 InterfaceType::Record(i) => &self[*i].abi,
358 InterfaceType::Variant(i) => &self[*i].abi,
359 InterfaceType::Tuple(i) => &self[*i].abi,
360 InterfaceType::Flags(i) => &self[*i].abi,
361 InterfaceType::Enum(i) => &self[*i].abi,
362 InterfaceType::Option(i) => &self[*i].abi,
363 InterfaceType::Result(i) => &self[*i].abi,
364 }
365 }
366
367 pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
369 self.resource_tables.push(table)
370 }
371}
372
373macro_rules! impl_index {
374 ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
375 impl core::ops::Index<$ty> for ComponentTypes {
376 type Output = $output;
377 #[inline]
378 fn index(&self, idx: $ty) -> &$output {
379 &self.$field[idx]
380 }
381 }
382
383 #[cfg(feature = "compile")]
384 impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
385 type Output = $output;
386 #[inline]
387 fn index(&self, idx: $ty) -> &$output {
388 &self.component_types()[idx]
389 }
390 }
391 )*)
392}
393
394impl_index! {
395 impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
396 impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
397 impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
398 impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
399 impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
400 impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
401 impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
402 impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
403 impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
404 impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
405 impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
406 impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
407 impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
408 impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
409 impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
410 impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
411 impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
412 impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
413}
414
415impl<T> Index<T> for ComponentTypes
418where
419 ModuleTypes: Index<T>,
420{
421 type Output = <ModuleTypes as Index<T>>::Output;
422 fn index(&self, idx: T) -> &Self::Output {
423 self.module_types.as_ref().unwrap().index(idx)
424 }
425}
426
427#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
433pub enum TypeDef {
434 Component(TypeComponentIndex),
436 ComponentInstance(TypeComponentInstanceIndex),
438 ComponentFunc(TypeFuncIndex),
440 Interface(InterfaceType),
442 Module(TypeModuleIndex),
444 CoreFunc(ModuleInternedTypeIndex),
446 Resource(TypeResourceTableIndex),
451}
452
453impl TypeDef {
454 pub fn desc(&self) -> &str {
456 match self {
457 TypeDef::Component(_) => "component",
458 TypeDef::ComponentInstance(_) => "instance",
459 TypeDef::ComponentFunc(_) => "function",
460 TypeDef::Interface(_) => "type",
461 TypeDef::Module(_) => "core module",
462 TypeDef::CoreFunc(_) => "core function",
463 TypeDef::Resource(_) => "resource",
464 }
465 }
466}
467
468#[derive(Serialize, Deserialize, Default)]
478pub struct TypeModule {
479 pub imports: IndexMap<(String, String), EntityType>,
487
488 pub exports: IndexMap<String, EntityType>,
493}
494
495impl TypeTrace for TypeModule {
496 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
497 where
498 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
499 {
500 for ty in self.imports.values() {
501 ty.trace(func)?;
502 }
503 for ty in self.exports.values() {
504 ty.trace(func)?;
505 }
506 Ok(())
507 }
508
509 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
510 where
511 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
512 {
513 for ty in self.imports.values_mut() {
514 ty.trace_mut(func)?;
515 }
516 for ty in self.exports.values_mut() {
517 ty.trace_mut(func)?;
518 }
519 Ok(())
520 }
521}
522
523#[derive(Serialize, Deserialize, Default)]
525pub struct TypeComponent {
526 pub imports: IndexMap<String, TypeDef>,
528 pub exports: IndexMap<String, TypeDef>,
530}
531
532#[derive(Serialize, Deserialize, Default)]
537pub struct TypeComponentInstance {
538 pub exports: IndexMap<String, TypeDef>,
540}
541
542#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
544pub struct TypeFunc {
545 pub param_names: Vec<String>,
547 pub params: TypeTupleIndex,
549 pub results: TypeTupleIndex,
551}
552
553#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
560#[expect(missing_docs, reason = "self-describing variants")]
561pub enum InterfaceType {
562 Bool,
563 S8,
564 U8,
565 S16,
566 U16,
567 S32,
568 U32,
569 S64,
570 U64,
571 Float32,
572 Float64,
573 Char,
574 String,
575 Record(TypeRecordIndex),
576 Variant(TypeVariantIndex),
577 List(TypeListIndex),
578 Tuple(TypeTupleIndex),
579 Flags(TypeFlagsIndex),
580 Enum(TypeEnumIndex),
581 Option(TypeOptionIndex),
582 Result(TypeResultIndex),
583 Own(TypeResourceTableIndex),
584 Borrow(TypeResourceTableIndex),
585 Future(TypeFutureTableIndex),
586 Stream(TypeStreamTableIndex),
587 ErrorContext(TypeComponentLocalErrorContextTableIndex),
588}
589
590#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
593pub struct CanonicalAbiInfo {
594 pub size32: u32,
596 pub align32: u32,
598 pub size64: u32,
600 pub align64: u32,
602 pub flat_count: Option<u8>,
609}
610
611impl Default for CanonicalAbiInfo {
612 fn default() -> CanonicalAbiInfo {
613 CanonicalAbiInfo {
614 size32: 0,
615 align32: 1,
616 size64: 0,
617 align64: 1,
618 flat_count: Some(0),
619 }
620 }
621}
622
623const fn align_to(a: u32, b: u32) -> u32 {
624 assert!(b.is_power_of_two());
625 (a + (b - 1)) & !(b - 1)
626}
627
628const fn max(a: u32, b: u32) -> u32 {
629 if a > b { a } else { b }
630}
631
632impl CanonicalAbiInfo {
633 pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
635 size32: 0,
636 align32: 1,
637 size64: 0,
638 align64: 1,
639 flat_count: Some(0),
640 };
641
642 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
644 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
646 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
648 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
650
651 const fn scalar(size: u32) -> CanonicalAbiInfo {
652 CanonicalAbiInfo {
653 size32: size,
654 align32: size,
655 size64: size,
656 align64: size,
657 flat_count: Some(1),
658 }
659 }
660
661 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
663 size32: 8,
664 align32: 4,
665 size64: 16,
666 align64: 8,
667 flat_count: Some(2),
668 };
669
670 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
672 let mut ret = CanonicalAbiInfo::default();
676 for field in fields {
677 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
678 ret.align32 = ret.align32.max(field.align32);
679 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
680 ret.align64 = ret.align64.max(field.align64);
681 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
682 }
683 ret.size32 = align_to(ret.size32, ret.align32);
684 ret.size64 = align_to(ret.size64, ret.align64);
685 return ret;
686 }
687
688 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
690 let mut ret = CanonicalAbiInfo::ZERO;
694 let mut i = 0;
695 while i < fields.len() {
696 let field = &fields[i];
697 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
698 ret.align32 = max(ret.align32, field.align32);
699 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
700 ret.align64 = max(ret.align64, field.align64);
701 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
702 i += 1;
703 }
704 ret.size32 = align_to(ret.size32, ret.align32);
705 ret.size64 = align_to(ret.size64, ret.align64);
706 return ret;
707 }
708
709 pub fn next_field32(&self, offset: &mut u32) -> u32 {
712 *offset = align_to(*offset, self.align32) + self.size32;
713 *offset - self.size32
714 }
715
716 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
718 let cur = u32::try_from(*offset).unwrap();
719 let cur = align_to(cur, self.align32) + self.size32;
720 *offset = usize::try_from(cur).unwrap();
721 usize::try_from(cur - self.size32).unwrap()
722 }
723
724 pub fn next_field64(&self, offset: &mut u32) -> u32 {
727 *offset = align_to(*offset, self.align64) + self.size64;
728 *offset - self.size64
729 }
730
731 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
733 let cur = u32::try_from(*offset).unwrap();
734 let cur = align_to(cur, self.align64) + self.size64;
735 *offset = usize::try_from(cur).unwrap();
736 usize::try_from(cur - self.size64).unwrap()
737 }
738
739 pub const fn flags(count: usize) -> CanonicalAbiInfo {
741 let (size, align, flat_count) = match FlagsSize::from_count(count) {
742 FlagsSize::Size0 => (0, 1, 0),
743 FlagsSize::Size1 => (1, 1, 1),
744 FlagsSize::Size2 => (2, 2, 1),
745 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
746 };
747 CanonicalAbiInfo {
748 size32: size,
749 align32: align,
750 size64: size,
751 align64: align,
752 flat_count: Some(flat_count),
753 }
754 }
755
756 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
757 where
758 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
759 I::IntoIter: ExactSizeIterator,
760 {
761 let cases = cases.into_iter();
765 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
766 let mut max_size32 = 0;
767 let mut max_align32 = discrim_size;
768 let mut max_size64 = 0;
769 let mut max_align64 = discrim_size;
770 let mut max_case_count = Some(0);
771 for case in cases {
772 if let Some(case) = case {
773 max_size32 = max_size32.max(case.size32);
774 max_align32 = max_align32.max(case.align32);
775 max_size64 = max_size64.max(case.size64);
776 max_align64 = max_align64.max(case.align64);
777 max_case_count = max_flat(max_case_count, case.flat_count);
778 }
779 }
780 CanonicalAbiInfo {
781 size32: align_to(
782 align_to(discrim_size, max_align32) + max_size32,
783 max_align32,
784 ),
785 align32: max_align32,
786 size64: align_to(
787 align_to(discrim_size, max_align64) + max_size64,
788 max_align64,
789 ),
790 align64: max_align64,
791 flat_count: add_flat(max_case_count, Some(1)),
792 }
793 }
794
795 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
797 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
801 Some(size) => size.byte_size(),
802 None => unreachable!(),
803 };
804 let mut max_size32 = 0;
805 let mut max_align32 = discrim_size;
806 let mut max_size64 = 0;
807 let mut max_align64 = discrim_size;
808 let mut max_case_count = Some(0);
809 let mut i = 0;
810 while i < cases.len() {
811 let case = &cases[i];
812 if let Some(case) = case {
813 max_size32 = max(max_size32, case.size32);
814 max_align32 = max(max_align32, case.align32);
815 max_size64 = max(max_size64, case.size64);
816 max_align64 = max(max_align64, case.align64);
817 max_case_count = max_flat(max_case_count, case.flat_count);
818 }
819 i += 1;
820 }
821 CanonicalAbiInfo {
822 size32: align_to(
823 align_to(discrim_size, max_align32) + max_size32,
824 max_align32,
825 ),
826 align32: max_align32,
827 size64: align_to(
828 align_to(discrim_size, max_align64) + max_size64,
829 max_align64,
830 ),
831 align64: max_align64,
832 flat_count: add_flat(max_case_count, Some(1)),
833 }
834 }
835
836 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
838 let discrim_size = match DiscriminantSize::from_count(cases) {
842 Some(size) => size.byte_size(),
843 None => unreachable!(),
844 };
845 CanonicalAbiInfo {
846 size32: discrim_size,
847 align32: discrim_size,
848 size64: discrim_size,
849 align64: discrim_size,
850 flat_count: Some(1),
851 }
852 }
853
854 pub fn flat_count(&self, max: usize) -> Option<usize> {
857 let flat = usize::from(self.flat_count?);
858 if flat > max { None } else { Some(flat) }
859 }
860}
861
862#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
864pub struct VariantInfo {
865 #[serde(with = "serde_discrim_size")]
867 pub size: DiscriminantSize,
868 pub payload_offset32: u32,
871 pub payload_offset64: u32,
874}
875
876impl VariantInfo {
877 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
880 where
881 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
882 I::IntoIter: ExactSizeIterator,
883 {
884 let cases = cases.into_iter();
885 let size = DiscriminantSize::from_count(cases.len()).unwrap();
886 let abi = CanonicalAbiInfo::variant(cases);
887 (
888 VariantInfo {
889 size,
890 payload_offset32: align_to(u32::from(size), abi.align32),
891 payload_offset64: align_to(u32::from(size), abi.align64),
892 },
893 abi,
894 )
895 }
896 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
898 let size = match DiscriminantSize::from_count(cases.len()) {
899 Some(size) => size,
900 None => unreachable!(),
901 };
902 let abi = CanonicalAbiInfo::variant_static(cases);
903 VariantInfo {
904 size,
905 payload_offset32: align_to(size.byte_size(), abi.align32),
906 payload_offset64: align_to(size.byte_size(), abi.align64),
907 }
908 }
909}
910
911mod serde_discrim_size {
912 use super::DiscriminantSize;
913 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
914
915 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
916 where
917 S: Serializer,
918 {
919 u32::from(*disc).serialize(ser)
920 }
921
922 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
923 where
924 D: Deserializer<'de>,
925 {
926 match u32::deserialize(deser)? {
927 1 => Ok(DiscriminantSize::Size1),
928 2 => Ok(DiscriminantSize::Size2),
929 4 => Ok(DiscriminantSize::Size4),
930 _ => Err(D::Error::custom("invalid discriminant size")),
931 }
932 }
933}
934
935#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
939pub struct TypeRecord {
940 pub fields: Box<[RecordField]>,
942 pub abi: CanonicalAbiInfo,
944}
945
946#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
948pub struct RecordField {
949 pub name: String,
951 pub ty: InterfaceType,
953}
954
955#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
961pub struct TypeVariant {
962 pub cases: IndexMap<String, Option<InterfaceType>>,
964 pub abi: CanonicalAbiInfo,
966 pub info: VariantInfo,
968}
969
970impl Hash for TypeVariant {
971 fn hash<H: Hasher>(&self, h: &mut H) {
972 let TypeVariant { cases, abi, info } = self;
973 cases.len().hash(h);
974 for pair in cases {
975 pair.hash(h);
976 }
977 abi.hash(h);
978 info.hash(h);
979 }
980}
981
982#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
987pub struct TypeTuple {
988 pub types: Box<[InterfaceType]>,
990 pub abi: CanonicalAbiInfo,
992}
993
994#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
999pub struct TypeFlags {
1000 pub names: IndexSet<String>,
1002 pub abi: CanonicalAbiInfo,
1004}
1005
1006impl Hash for TypeFlags {
1007 fn hash<H: Hasher>(&self, h: &mut H) {
1008 let TypeFlags { names, abi } = self;
1009 names.len().hash(h);
1010 for name in names {
1011 name.hash(h);
1012 }
1013 abi.hash(h);
1014 }
1015}
1016
1017#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1023pub struct TypeEnum {
1024 pub names: IndexSet<String>,
1026 pub abi: CanonicalAbiInfo,
1028 pub info: VariantInfo,
1030}
1031
1032impl Hash for TypeEnum {
1033 fn hash<H: Hasher>(&self, h: &mut H) {
1034 let TypeEnum { names, abi, info } = self;
1035 names.len().hash(h);
1036 for name in names {
1037 name.hash(h);
1038 }
1039 abi.hash(h);
1040 info.hash(h);
1041 }
1042}
1043
1044#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1046pub struct TypeOption {
1047 pub ty: InterfaceType,
1049 pub abi: CanonicalAbiInfo,
1051 pub info: VariantInfo,
1053}
1054
1055#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1057pub struct TypeResult {
1058 pub ok: Option<InterfaceType>,
1060 pub err: Option<InterfaceType>,
1062 pub abi: CanonicalAbiInfo,
1064 pub info: VariantInfo,
1066}
1067
1068#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1070pub struct TypeFuture {
1071 pub payload: Option<InterfaceType>,
1073}
1074
1075#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1077pub struct TypeFutureTable {
1078 pub ty: TypeFutureIndex,
1080 pub instance: RuntimeComponentInstanceIndex,
1082}
1083
1084#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1086pub struct TypeStream {
1087 pub payload: Option<InterfaceType>,
1089}
1090
1091#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1093pub struct TypeStreamTable {
1094 pub ty: TypeStreamIndex,
1096 pub instance: RuntimeComponentInstanceIndex,
1098}
1099
1100#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1102pub struct TypeErrorContextTable {
1103 pub instance: RuntimeComponentInstanceIndex,
1105}
1106
1107#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1109pub struct TypeResourceTable {
1110 pub ty: ResourceIndex,
1115
1116 pub instance: RuntimeComponentInstanceIndex,
1118}
1119
1120#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1122pub struct TypeList {
1123 pub element: InterfaceType,
1125}
1126
1127pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1129 MAX_FLAT_PARAMS
1130} else {
1131 MAX_FLAT_RESULTS
1132};
1133
1134const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1135 const MAX: u8 = MAX_FLAT_TYPES as u8;
1136 let sum = match (a, b) {
1137 (Some(a), Some(b)) => match a.checked_add(b) {
1138 Some(c) => c,
1139 None => return None,
1140 },
1141 _ => return None,
1142 };
1143 if sum > MAX { None } else { Some(sum) }
1144}
1145
1146const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1147 match (a, b) {
1148 (Some(a), Some(b)) => {
1149 if a > b {
1150 Some(a)
1151 } else {
1152 Some(b)
1153 }
1154 }
1155 _ => None,
1156 }
1157}
1158
1159pub struct FlatTypes<'a> {
1161 pub memory32: &'a [FlatType],
1163 pub memory64: &'a [FlatType],
1165}
1166
1167impl FlatTypes<'_> {
1168 pub fn len(&self) -> usize {
1172 assert_eq!(self.memory32.len(), self.memory64.len());
1173 self.memory32.len()
1174 }
1175}
1176
1177#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1181#[expect(missing_docs, reason = "self-describing variants")]
1182pub enum FlatType {
1183 I32,
1184 I64,
1185 F32,
1186 F64,
1187}