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 param_names: Vec<String>,
555 pub params: TypeTupleIndex,
557 pub results: TypeTupleIndex,
559}
560
561#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
568#[expect(missing_docs, reason = "self-describing variants")]
569pub enum InterfaceType {
570 Bool,
571 S8,
572 U8,
573 S16,
574 U16,
575 S32,
576 U32,
577 S64,
578 U64,
579 Float32,
580 Float64,
581 Char,
582 String,
583 Record(TypeRecordIndex),
584 Variant(TypeVariantIndex),
585 List(TypeListIndex),
586 Tuple(TypeTupleIndex),
587 Flags(TypeFlagsIndex),
588 Enum(TypeEnumIndex),
589 Option(TypeOptionIndex),
590 Result(TypeResultIndex),
591 Own(TypeResourceTableIndex),
592 Borrow(TypeResourceTableIndex),
593 Future(TypeFutureTableIndex),
594 Stream(TypeStreamTableIndex),
595 ErrorContext(TypeComponentLocalErrorContextTableIndex),
596}
597
598#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
601pub struct CanonicalAbiInfo {
602 pub size32: u32,
604 pub align32: u32,
606 pub size64: u32,
608 pub align64: u32,
610 pub flat_count: Option<u8>,
617}
618
619impl Default for CanonicalAbiInfo {
620 fn default() -> CanonicalAbiInfo {
621 CanonicalAbiInfo {
622 size32: 0,
623 align32: 1,
624 size64: 0,
625 align64: 1,
626 flat_count: Some(0),
627 }
628 }
629}
630
631const fn align_to(a: u32, b: u32) -> u32 {
632 assert!(b.is_power_of_two());
633 (a + (b - 1)) & !(b - 1)
634}
635
636const fn max(a: u32, b: u32) -> u32 {
637 if a > b { a } else { b }
638}
639
640impl CanonicalAbiInfo {
641 pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
643 size32: 0,
644 align32: 1,
645 size64: 0,
646 align64: 1,
647 flat_count: Some(0),
648 };
649
650 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
652 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
654 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
656 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
658
659 const fn scalar(size: u32) -> CanonicalAbiInfo {
660 CanonicalAbiInfo {
661 size32: size,
662 align32: size,
663 size64: size,
664 align64: size,
665 flat_count: Some(1),
666 }
667 }
668
669 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
671 size32: 8,
672 align32: 4,
673 size64: 16,
674 align64: 8,
675 flat_count: Some(2),
676 };
677
678 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
680 let mut ret = CanonicalAbiInfo::default();
684 for field in fields {
685 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
686 ret.align32 = ret.align32.max(field.align32);
687 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
688 ret.align64 = ret.align64.max(field.align64);
689 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
690 }
691 ret.size32 = align_to(ret.size32, ret.align32);
692 ret.size64 = align_to(ret.size64, ret.align64);
693 return ret;
694 }
695
696 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
698 let mut ret = CanonicalAbiInfo::ZERO;
702 let mut i = 0;
703 while i < fields.len() {
704 let field = &fields[i];
705 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
706 ret.align32 = max(ret.align32, field.align32);
707 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
708 ret.align64 = max(ret.align64, field.align64);
709 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
710 i += 1;
711 }
712 ret.size32 = align_to(ret.size32, ret.align32);
713 ret.size64 = align_to(ret.size64, ret.align64);
714 return ret;
715 }
716
717 pub fn next_field32(&self, offset: &mut u32) -> u32 {
720 *offset = align_to(*offset, self.align32) + self.size32;
721 *offset - self.size32
722 }
723
724 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
726 let cur = u32::try_from(*offset).unwrap();
727 let cur = align_to(cur, self.align32) + self.size32;
728 *offset = usize::try_from(cur).unwrap();
729 usize::try_from(cur - self.size32).unwrap()
730 }
731
732 pub fn next_field64(&self, offset: &mut u32) -> u32 {
735 *offset = align_to(*offset, self.align64) + self.size64;
736 *offset - self.size64
737 }
738
739 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
741 let cur = u32::try_from(*offset).unwrap();
742 let cur = align_to(cur, self.align64) + self.size64;
743 *offset = usize::try_from(cur).unwrap();
744 usize::try_from(cur - self.size64).unwrap()
745 }
746
747 pub const fn flags(count: usize) -> CanonicalAbiInfo {
749 let (size, align, flat_count) = match FlagsSize::from_count(count) {
750 FlagsSize::Size0 => (0, 1, 0),
751 FlagsSize::Size1 => (1, 1, 1),
752 FlagsSize::Size2 => (2, 2, 1),
753 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
754 };
755 CanonicalAbiInfo {
756 size32: size,
757 align32: align,
758 size64: size,
759 align64: align,
760 flat_count: Some(flat_count),
761 }
762 }
763
764 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
765 where
766 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
767 I::IntoIter: ExactSizeIterator,
768 {
769 let cases = cases.into_iter();
773 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
774 let mut max_size32 = 0;
775 let mut max_align32 = discrim_size;
776 let mut max_size64 = 0;
777 let mut max_align64 = discrim_size;
778 let mut max_case_count = Some(0);
779 for case in cases {
780 if let Some(case) = case {
781 max_size32 = max_size32.max(case.size32);
782 max_align32 = max_align32.max(case.align32);
783 max_size64 = max_size64.max(case.size64);
784 max_align64 = max_align64.max(case.align64);
785 max_case_count = max_flat(max_case_count, case.flat_count);
786 }
787 }
788 CanonicalAbiInfo {
789 size32: align_to(
790 align_to(discrim_size, max_align32) + max_size32,
791 max_align32,
792 ),
793 align32: max_align32,
794 size64: align_to(
795 align_to(discrim_size, max_align64) + max_size64,
796 max_align64,
797 ),
798 align64: max_align64,
799 flat_count: add_flat(max_case_count, Some(1)),
800 }
801 }
802
803 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
805 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
809 Some(size) => size.byte_size(),
810 None => unreachable!(),
811 };
812 let mut max_size32 = 0;
813 let mut max_align32 = discrim_size;
814 let mut max_size64 = 0;
815 let mut max_align64 = discrim_size;
816 let mut max_case_count = Some(0);
817 let mut i = 0;
818 while i < cases.len() {
819 let case = &cases[i];
820 if let Some(case) = case {
821 max_size32 = max(max_size32, case.size32);
822 max_align32 = max(max_align32, case.align32);
823 max_size64 = max(max_size64, case.size64);
824 max_align64 = max(max_align64, case.align64);
825 max_case_count = max_flat(max_case_count, case.flat_count);
826 }
827 i += 1;
828 }
829 CanonicalAbiInfo {
830 size32: align_to(
831 align_to(discrim_size, max_align32) + max_size32,
832 max_align32,
833 ),
834 align32: max_align32,
835 size64: align_to(
836 align_to(discrim_size, max_align64) + max_size64,
837 max_align64,
838 ),
839 align64: max_align64,
840 flat_count: add_flat(max_case_count, Some(1)),
841 }
842 }
843
844 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
846 let discrim_size = match DiscriminantSize::from_count(cases) {
850 Some(size) => size.byte_size(),
851 None => unreachable!(),
852 };
853 CanonicalAbiInfo {
854 size32: discrim_size,
855 align32: discrim_size,
856 size64: discrim_size,
857 align64: discrim_size,
858 flat_count: Some(1),
859 }
860 }
861
862 pub fn flat_count(&self, max: usize) -> Option<usize> {
865 let flat = usize::from(self.flat_count?);
866 if flat > max { None } else { Some(flat) }
867 }
868}
869
870#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
872pub struct VariantInfo {
873 #[serde(with = "serde_discrim_size")]
875 pub size: DiscriminantSize,
876 pub payload_offset32: u32,
879 pub payload_offset64: u32,
882}
883
884impl VariantInfo {
885 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
888 where
889 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
890 I::IntoIter: ExactSizeIterator,
891 {
892 let cases = cases.into_iter();
893 let size = DiscriminantSize::from_count(cases.len()).unwrap();
894 let abi = CanonicalAbiInfo::variant(cases);
895 (
896 VariantInfo {
897 size,
898 payload_offset32: align_to(u32::from(size), abi.align32),
899 payload_offset64: align_to(u32::from(size), abi.align64),
900 },
901 abi,
902 )
903 }
904 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
906 let size = match DiscriminantSize::from_count(cases.len()) {
907 Some(size) => size,
908 None => unreachable!(),
909 };
910 let abi = CanonicalAbiInfo::variant_static(cases);
911 VariantInfo {
912 size,
913 payload_offset32: align_to(size.byte_size(), abi.align32),
914 payload_offset64: align_to(size.byte_size(), abi.align64),
915 }
916 }
917}
918
919mod serde_discrim_size {
920 use super::DiscriminantSize;
921 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
922
923 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
924 where
925 S: Serializer,
926 {
927 u32::from(*disc).serialize(ser)
928 }
929
930 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
931 where
932 D: Deserializer<'de>,
933 {
934 match u32::deserialize(deser)? {
935 1 => Ok(DiscriminantSize::Size1),
936 2 => Ok(DiscriminantSize::Size2),
937 4 => Ok(DiscriminantSize::Size4),
938 _ => Err(D::Error::custom("invalid discriminant size")),
939 }
940 }
941}
942
943#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
947pub struct TypeRecord {
948 pub fields: Box<[RecordField]>,
950 pub abi: CanonicalAbiInfo,
952}
953
954#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
956pub struct RecordField {
957 pub name: String,
959 pub ty: InterfaceType,
961}
962
963#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
969pub struct TypeVariant {
970 pub cases: IndexMap<String, Option<InterfaceType>>,
972 pub abi: CanonicalAbiInfo,
974 pub info: VariantInfo,
976}
977
978impl Hash for TypeVariant {
979 fn hash<H: Hasher>(&self, h: &mut H) {
980 let TypeVariant { cases, abi, info } = self;
981 cases.len().hash(h);
982 for pair in cases {
983 pair.hash(h);
984 }
985 abi.hash(h);
986 info.hash(h);
987 }
988}
989
990#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
995pub struct TypeTuple {
996 pub types: Box<[InterfaceType]>,
998 pub abi: CanonicalAbiInfo,
1000}
1001
1002#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1007pub struct TypeFlags {
1008 pub names: IndexSet<String>,
1010 pub abi: CanonicalAbiInfo,
1012}
1013
1014impl Hash for TypeFlags {
1015 fn hash<H: Hasher>(&self, h: &mut H) {
1016 let TypeFlags { names, abi } = self;
1017 names.len().hash(h);
1018 for name in names {
1019 name.hash(h);
1020 }
1021 abi.hash(h);
1022 }
1023}
1024
1025#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1031pub struct TypeEnum {
1032 pub names: IndexSet<String>,
1034 pub abi: CanonicalAbiInfo,
1036 pub info: VariantInfo,
1038}
1039
1040impl Hash for TypeEnum {
1041 fn hash<H: Hasher>(&self, h: &mut H) {
1042 let TypeEnum { names, abi, info } = self;
1043 names.len().hash(h);
1044 for name in names {
1045 name.hash(h);
1046 }
1047 abi.hash(h);
1048 info.hash(h);
1049 }
1050}
1051
1052#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1054pub struct TypeOption {
1055 pub ty: InterfaceType,
1057 pub abi: CanonicalAbiInfo,
1059 pub info: VariantInfo,
1061}
1062
1063#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1065pub struct TypeResult {
1066 pub ok: Option<InterfaceType>,
1068 pub err: Option<InterfaceType>,
1070 pub abi: CanonicalAbiInfo,
1072 pub info: VariantInfo,
1074}
1075
1076#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1078pub struct TypeFuture {
1079 pub payload: Option<InterfaceType>,
1081}
1082
1083#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1085pub struct TypeFutureTable {
1086 pub ty: TypeFutureIndex,
1088 pub instance: RuntimeComponentInstanceIndex,
1090}
1091
1092#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1094pub struct TypeStream {
1095 pub payload: Option<InterfaceType>,
1097}
1098
1099#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1101pub struct TypeStreamTable {
1102 pub ty: TypeStreamIndex,
1104 pub instance: RuntimeComponentInstanceIndex,
1106}
1107
1108#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1110pub struct TypeErrorContextTable {
1111 pub instance: RuntimeComponentInstanceIndex,
1113}
1114
1115#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1117pub enum TypeResourceTable {
1118 Concrete {
1125 ty: ResourceIndex,
1130
1131 instance: RuntimeComponentInstanceIndex,
1133 },
1134
1135 Abstract(AbstractResourceIndex),
1139}
1140
1141impl TypeResourceTable {
1142 pub fn unwrap_concrete_ty(&self) -> ResourceIndex {
1149 match self {
1150 TypeResourceTable::Concrete { ty, .. } => *ty,
1151 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1152 }
1153 }
1154
1155 pub fn unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex {
1162 match self {
1163 TypeResourceTable::Concrete { instance, .. } => *instance,
1164 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1165 }
1166 }
1167}
1168
1169#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1171pub struct TypeList {
1172 pub element: InterfaceType,
1174}
1175
1176pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1178 MAX_FLAT_PARAMS
1179} else {
1180 MAX_FLAT_RESULTS
1181};
1182
1183const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1184 const MAX: u8 = MAX_FLAT_TYPES as u8;
1185 let sum = match (a, b) {
1186 (Some(a), Some(b)) => match a.checked_add(b) {
1187 Some(c) => c,
1188 None => return None,
1189 },
1190 _ => return None,
1191 };
1192 if sum > MAX { None } else { Some(sum) }
1193}
1194
1195const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1196 match (a, b) {
1197 (Some(a), Some(b)) => {
1198 if a > b {
1199 Some(a)
1200 } else {
1201 Some(b)
1202 }
1203 }
1204 _ => None,
1205 }
1206}
1207
1208pub struct FlatTypes<'a> {
1210 pub memory32: &'a [FlatType],
1212 pub memory64: &'a [FlatType],
1214}
1215
1216impl FlatTypes<'_> {
1217 pub fn len(&self) -> usize {
1221 assert_eq!(self.memory32.len(), self.memory64.len());
1222 self.memory32.len()
1223 }
1224}
1225
1226#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1230#[expect(missing_docs, reason = "self-describing variants")]
1231pub enum FlatType {
1232 I32,
1233 I64,
1234 F32,
1235 F64,
1236}