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 impl TryClone for $name {
26 #[inline]
27 fn try_clone(&self) -> Result<Self, OutOfMemory> {
28 Ok(*self)
29 }
30 }
31 )*);
32}
33
34indices! {
35 pub struct ComponentTypeIndex(u32);
43
44 pub struct ModuleIndex(u32);
46
47 pub struct ComponentIndex(u32);
49
50 pub struct ModuleInstanceIndex(u32);
52
53 pub struct ComponentInstanceIndex(u32);
55
56 pub struct ComponentFuncIndex(u32);
58
59 pub struct TypeComponentIndex(u32);
67
68 pub struct TypeComponentInstanceIndex(u32);
71
72 pub struct TypeModuleIndex(u32);
75
76 pub struct TypeFuncIndex(u32);
79
80 pub struct TypeRecordIndex(u32);
82 pub struct TypeVariantIndex(u32);
84 pub struct TypeTupleIndex(u32);
86 pub struct TypeFlagsIndex(u32);
88 pub struct TypeEnumIndex(u32);
90 pub struct TypeOptionIndex(u32);
93 pub struct TypeResultIndex(u32);
96 pub struct TypeListIndex(u32);
98 pub struct TypeMapIndex(u32);
100 pub struct TypeFixedLengthListIndex(u32);
102 pub struct TypeFutureIndex(u32);
104
105 pub struct TypeFutureTableIndex(u32);
110
111 pub struct TypeStreamIndex(u32);
113
114 pub struct TypeStreamTableIndex(u32);
119
120 pub struct TypeComponentLocalErrorContextTableIndex(u32);
125
126 pub struct TypeComponentGlobalErrorContextTableIndex(u32);
132
133 pub struct TypeResourceTableIndex(u32);
148
149 pub struct ResourceIndex(u32);
162
163 pub struct DefinedResourceIndex(u32);
169
170 pub struct ModuleUpvarIndex(u32);
177
178 pub struct ComponentUpvarIndex(u32);
180
181 pub struct StaticComponentIndex(u32);
183
184 pub struct RuntimeInstanceIndex(u32);
193
194 pub struct RuntimeComponentInstanceIndex(u32);
196
197 pub struct ImportIndex(u32);
202
203 pub struct RuntimeImportIndex(u32);
209
210 pub struct LoweredIndex(u32);
216
217 pub struct RuntimeMemoryIndex(u32);
225
226 pub struct RuntimeReallocIndex(u32);
228
229 pub struct RuntimeCallbackIndex(u32);
231
232 pub struct RuntimePostReturnIndex(u32);
234
235 pub struct RuntimeTableIndex(u32);
242
243 pub struct TrampolineIndex(u32);
250
251 pub struct ExportIndex(u32);
253
254 pub struct OptionsIndex(u32);
256
257 pub struct AbstractResourceIndex(u32);
264}
265
266pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
269
270#[derive(Debug, Clone, Copy)]
273#[expect(missing_docs, reason = "self-describing variants")]
274pub enum ComponentItem {
275 Func(ComponentFuncIndex),
276 Module(ModuleIndex),
277 Component(ComponentIndex),
278 ComponentInstance(ComponentInstanceIndex),
279 Type(ComponentAnyTypeId),
280}
281
282#[derive(Default, Serialize, Deserialize)]
288pub struct ComponentTypes {
289 pub(super) modules: PrimaryMap<TypeModuleIndex, TypeModule>,
290 pub(super) components: PrimaryMap<TypeComponentIndex, TypeComponent>,
291 pub(super) component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
292 pub(super) functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
293 pub(super) lists: PrimaryMap<TypeListIndex, TypeList>,
294 pub(super) maps: PrimaryMap<TypeMapIndex, TypeMap>,
295 pub(super) records: PrimaryMap<TypeRecordIndex, TypeRecord>,
296 pub(super) variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
297 pub(super) tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
298 pub(super) enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
299 pub(super) flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
300 pub(super) options: PrimaryMap<TypeOptionIndex, TypeOption>,
301 pub(super) results: PrimaryMap<TypeResultIndex, TypeResult>,
302 pub(super) resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
303 pub(super) module_types: Option<ModuleTypes>,
304 pub(super) futures: PrimaryMap<TypeFutureIndex, TypeFuture>,
305 pub(super) future_tables: PrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
306 pub(super) streams: PrimaryMap<TypeStreamIndex, TypeStream>,
307 pub(super) stream_tables: PrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
308 pub(super) error_context_tables:
309 PrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
310 pub(super) fixed_length_lists: PrimaryMap<TypeFixedLengthListIndex, TypeFixedLengthList>,
311}
312
313impl TypeTrace for ComponentTypes {
314 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
315 where
316 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
317 {
318 for (_, m) in &self.modules {
319 m.trace(func)?;
320 }
321 if let Some(m) = self.module_types.as_ref() {
322 m.trace(func)?;
323 }
324 Ok(())
325 }
326
327 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
328 where
329 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
330 {
331 for (_, m) in &mut self.modules {
332 m.trace_mut(func)?;
333 }
334 if let Some(m) = self.module_types.as_mut() {
335 m.trace_mut(func)?;
336 }
337 Ok(())
338 }
339}
340
341impl ComponentTypes {
342 pub fn module_types(&self) -> &ModuleTypes {
344 self.module_types.as_ref().unwrap()
345 }
346
347 pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
349 self.module_types.as_mut().unwrap()
350 }
351
352 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
354 match ty {
355 InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
356 &CanonicalAbiInfo::SCALAR1
357 }
358
359 InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
360
361 InterfaceType::U32
362 | InterfaceType::S32
363 | InterfaceType::Float32
364 | InterfaceType::Char
365 | InterfaceType::Own(_)
366 | InterfaceType::Borrow(_)
367 | InterfaceType::Future(_)
368 | InterfaceType::Stream(_)
369 | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
370
371 InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
372 &CanonicalAbiInfo::SCALAR8
373 }
374
375 InterfaceType::String | InterfaceType::List(_) | InterfaceType::Map(_) => {
376 &CanonicalAbiInfo::POINTER_PAIR
377 }
378
379 InterfaceType::Record(i) => &self[*i].abi,
380 InterfaceType::Variant(i) => &self[*i].abi,
381 InterfaceType::Tuple(i) => &self[*i].abi,
382 InterfaceType::Flags(i) => &self[*i].abi,
383 InterfaceType::Enum(i) => &self[*i].abi,
384 InterfaceType::Option(i) => &self[*i].abi,
385 InterfaceType::Result(i) => &self[*i].abi,
386 InterfaceType::FixedLengthList(i) => &self[*i].abi,
387 }
388 }
389
390 pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
392 self.resource_tables.push(table)
393 }
394}
395
396macro_rules! impl_index {
397 ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
398 impl core::ops::Index<$ty> for ComponentTypes {
399 type Output = $output;
400 #[inline]
401 fn index(&self, idx: $ty) -> &$output {
402 &self.$field[idx]
403 }
404 }
405
406 #[cfg(feature = "compile")]
407 impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
408 type Output = $output;
409 #[inline]
410 fn index(&self, idx: $ty) -> &$output {
411 &self.component_types()[idx]
412 }
413 }
414 )*)
415}
416
417impl_index! {
418 impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
419 impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
420 impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
421 impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
422 impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
423 impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
424 impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
425 impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
426 impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
427 impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
428 impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
429 impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
430 impl Index<TypeMapIndex> for ComponentTypes { TypeMap => maps }
431 impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
432 impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
433 impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
434 impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
435 impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
436 impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
437 impl Index<TypeFixedLengthListIndex> for ComponentTypes { TypeFixedLengthList => fixed_length_lists }
438}
439
440impl<T> Index<T> for ComponentTypes
443where
444 ModuleTypes: Index<T>,
445{
446 type Output = <ModuleTypes as Index<T>>::Output;
447 fn index(&self, idx: T) -> &Self::Output {
448 self.module_types.as_ref().unwrap().index(idx)
449 }
450}
451
452#[derive(Clone, Debug, Serialize, Deserialize)]
457pub struct ComponentExtern {
458 pub data: ComponentExternData,
461 pub ty: TypeDef,
463}
464
465#[derive(Clone, Debug, Serialize, Deserialize)]
467pub struct ComponentExternData {
468 pub implements: Option<String>,
472 pub external_id: Option<String>,
475}
476
477#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
483pub enum TypeDef {
484 Component(TypeComponentIndex),
486 ComponentInstance(TypeComponentInstanceIndex),
488 ComponentFunc(TypeFuncIndex),
490 Interface(InterfaceType),
492 Module(TypeModuleIndex),
494 CoreFunc(ModuleInternedTypeIndex),
496 Resource(TypeResourceTableIndex),
501}
502
503impl TypeDef {
504 pub fn desc(&self) -> &str {
506 match self {
507 TypeDef::Component(_) => "component",
508 TypeDef::ComponentInstance(_) => "instance",
509 TypeDef::ComponentFunc(_) => "function",
510 TypeDef::Interface(_) => "type",
511 TypeDef::Module(_) => "core module",
512 TypeDef::CoreFunc(_) => "core function",
513 TypeDef::Resource(_) => "resource",
514 }
515 }
516}
517
518#[derive(Serialize, Deserialize, Default)]
528pub struct TypeModule {
529 pub imports: IndexMap<(String, String), EntityType>,
537
538 pub exports: IndexMap<String, EntityType>,
543}
544
545impl TypeTrace for TypeModule {
546 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
547 where
548 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
549 {
550 for ty in self.imports.values() {
551 ty.trace(func)?;
552 }
553 for ty in self.exports.values() {
554 ty.trace(func)?;
555 }
556 Ok(())
557 }
558
559 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
560 where
561 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
562 {
563 for ty in self.imports.values_mut() {
564 ty.trace_mut(func)?;
565 }
566 for ty in self.exports.values_mut() {
567 ty.trace_mut(func)?;
568 }
569 Ok(())
570 }
571}
572
573#[derive(Serialize, Deserialize, Default)]
575pub struct TypeComponent {
576 pub imports: IndexMap<String, ComponentExtern>,
578 pub exports: IndexMap<String, ComponentExtern>,
580}
581
582#[derive(Serialize, Deserialize, Default)]
587pub struct TypeComponentInstance {
588 pub exports: IndexMap<String, ComponentExtern>,
590}
591
592#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
594pub struct TypeFunc {
595 pub async_: bool,
597 pub param_names: Vec<String>,
599 pub params: TypeTupleIndex,
601 pub results: TypeTupleIndex,
603}
604
605#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
612#[expect(missing_docs, reason = "self-describing variants")]
613pub enum InterfaceType {
614 Bool,
615 S8,
616 U8,
617 S16,
618 U16,
619 S32,
620 U32,
621 S64,
622 U64,
623 Float32,
624 Float64,
625 Char,
626 String,
627 Record(TypeRecordIndex),
628 Variant(TypeVariantIndex),
629 List(TypeListIndex),
630 Tuple(TypeTupleIndex),
631 Map(TypeMapIndex),
632 Flags(TypeFlagsIndex),
633 Enum(TypeEnumIndex),
634 Option(TypeOptionIndex),
635 Result(TypeResultIndex),
636 Own(TypeResourceTableIndex),
637 Borrow(TypeResourceTableIndex),
638 Future(TypeFutureTableIndex),
639 Stream(TypeStreamTableIndex),
640 ErrorContext(TypeComponentLocalErrorContextTableIndex),
641 FixedLengthList(TypeFixedLengthListIndex),
642}
643
644#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
647pub struct CanonicalAbiInfo {
648 pub size32: u32,
650 pub align32: u32,
652 pub size64: u32,
654 pub align64: u32,
656 pub flat_count: Option<u8>,
663}
664
665impl Default for CanonicalAbiInfo {
666 fn default() -> CanonicalAbiInfo {
667 CanonicalAbiInfo {
668 size32: 0,
669 align32: 1,
670 size64: 0,
671 align64: 1,
672 flat_count: Some(0),
673 }
674 }
675}
676
677const fn align_to(a: u32, b: u32) -> u32 {
678 assert!(b.is_power_of_two());
679 (a + (b - 1)) & !(b - 1)
680}
681
682const fn max(a: u32, b: u32) -> u32 {
683 if a > b { a } else { b }
684}
685
686impl CanonicalAbiInfo {
687 pub const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
689 size32: 0,
690 align32: 1,
691 size64: 0,
692 align64: 1,
693 flat_count: Some(0),
694 };
695
696 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
698 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
700 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
702 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
704
705 const fn scalar(size: u32) -> CanonicalAbiInfo {
706 CanonicalAbiInfo {
707 size32: size,
708 align32: size,
709 size64: size,
710 align64: size,
711 flat_count: Some(1),
712 }
713 }
714
715 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
717 size32: 8,
718 align32: 4,
719 size64: 16,
720 align64: 8,
721 flat_count: Some(2),
722 };
723
724 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
726 let mut ret = CanonicalAbiInfo::default();
730 for field in fields {
731 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
732 ret.align32 = ret.align32.max(field.align32);
733 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
734 ret.align64 = ret.align64.max(field.align64);
735 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
736 }
737 ret.size32 = align_to(ret.size32, ret.align32);
738 ret.size64 = align_to(ret.size64, ret.align64);
739 return ret;
740 }
741
742 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
744 let mut ret = CanonicalAbiInfo::ZERO;
748 let mut i = 0;
749 while i < fields.len() {
750 let field = &fields[i];
751 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
752 ret.align32 = max(ret.align32, field.align32);
753 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
754 ret.align64 = max(ret.align64, field.align64);
755 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
756 i += 1;
757 }
758 ret.size32 = align_to(ret.size32, ret.align32);
759 ret.size64 = align_to(ret.size64, ret.align64);
760 return ret;
761 }
762
763 pub const fn fixed_length_list_static(
765 element: &CanonicalAbiInfo,
766 count: usize,
767 ) -> CanonicalAbiInfo {
768 if count <= u32::MAX as usize {
769 let count = count as u32;
770 CanonicalAbiInfo {
771 size32: element.size32.saturating_mul(count),
772 align32: element.align32,
773 size64: element.size64.saturating_mul(count),
774 align64: element.align64,
775
776 flat_count: match element.flat_count {
777 None => None,
778 Some(c) =>
779 {
781 match count.checked_mul(c as u32) {
782 Some(product) => {
783 if product as usize > MAX_FLAT_TYPES || product > u8::MAX as u32 {
784 None
785 } else {
786 Some(product as u8)
787 }
788 }
789 None => None,
790 }
791 }
792 },
793 }
794 } else {
795 CanonicalAbiInfo {
796 size32: u32::MAX,
797 align32: element.align32,
798 size64: u32::MAX,
799 align64: element.align64,
800 flat_count: None,
801 }
802 }
803 }
804
805 pub fn next_field32(&self, offset: &mut u32) -> u32 {
808 *offset = align_to(*offset, self.align32) + self.size32;
809 *offset - self.size32
810 }
811
812 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
814 let cur = u32::try_from(*offset).unwrap();
815 let cur = align_to(cur, self.align32) + self.size32;
816 *offset = usize::try_from(cur).unwrap();
817 usize::try_from(cur - self.size32).unwrap()
818 }
819
820 pub fn next_field64(&self, offset: &mut u32) -> u32 {
823 *offset = align_to(*offset, self.align64) + self.size64;
824 *offset - self.size64
825 }
826
827 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
829 let cur = u32::try_from(*offset).unwrap();
830 let cur = align_to(cur, self.align64) + self.size64;
831 *offset = usize::try_from(cur).unwrap();
832 usize::try_from(cur - self.size64).unwrap()
833 }
834
835 pub const fn flags(count: usize) -> CanonicalAbiInfo {
837 let (size, align, flat_count) = match FlagsSize::from_count(count) {
838 FlagsSize::Size0 => (0, 1, 0),
839 FlagsSize::Size1 => (1, 1, 1),
840 FlagsSize::Size2 => (2, 2, 1),
841 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
842 };
843 CanonicalAbiInfo {
844 size32: size,
845 align32: align,
846 size64: size,
847 align64: align,
848 flat_count: Some(flat_count),
849 }
850 }
851
852 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
853 where
854 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
855 I::IntoIter: ExactSizeIterator,
856 {
857 let cases = cases.into_iter();
861 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
862 let mut max_size32 = 0;
863 let mut max_align32 = discrim_size;
864 let mut max_size64 = 0;
865 let mut max_align64 = discrim_size;
866 let mut max_case_count = Some(0);
867 for case in cases {
868 if let Some(case) = case {
869 max_size32 = max_size32.max(case.size32);
870 max_align32 = max_align32.max(case.align32);
871 max_size64 = max_size64.max(case.size64);
872 max_align64 = max_align64.max(case.align64);
873 max_case_count = max_flat(max_case_count, case.flat_count);
874 }
875 }
876 CanonicalAbiInfo {
877 size32: align_to(
878 align_to(discrim_size, max_align32) + max_size32,
879 max_align32,
880 ),
881 align32: max_align32,
882 size64: align_to(
883 align_to(discrim_size, max_align64) + max_size64,
884 max_align64,
885 ),
886 align64: max_align64,
887 flat_count: add_flat(max_case_count, Some(1)),
888 }
889 }
890
891 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
893 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
897 Some(size) => size.byte_size(),
898 None => unreachable!(),
899 };
900 let mut max_size32 = 0;
901 let mut max_align32 = discrim_size;
902 let mut max_size64 = 0;
903 let mut max_align64 = discrim_size;
904 let mut max_case_count = Some(0);
905 let mut i = 0;
906 while i < cases.len() {
907 let case = &cases[i];
908 if let Some(case) = case {
909 max_size32 = max(max_size32, case.size32);
910 max_align32 = max(max_align32, case.align32);
911 max_size64 = max(max_size64, case.size64);
912 max_align64 = max(max_align64, case.align64);
913 max_case_count = max_flat(max_case_count, case.flat_count);
914 }
915 i += 1;
916 }
917 CanonicalAbiInfo {
918 size32: align_to(
919 align_to(discrim_size, max_align32) + max_size32,
920 max_align32,
921 ),
922 align32: max_align32,
923 size64: align_to(
924 align_to(discrim_size, max_align64) + max_size64,
925 max_align64,
926 ),
927 align64: max_align64,
928 flat_count: add_flat(max_case_count, Some(1)),
929 }
930 }
931
932 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
934 let discrim_size = match DiscriminantSize::from_count(cases) {
938 Some(size) => size.byte_size(),
939 None => unreachable!(),
940 };
941 CanonicalAbiInfo {
942 size32: discrim_size,
943 align32: discrim_size,
944 size64: discrim_size,
945 align64: discrim_size,
946 flat_count: Some(1),
947 }
948 }
949
950 pub fn flat_count(&self, max: usize) -> Option<usize> {
953 let flat = usize::from(self.flat_count?);
954 if flat > max { None } else { Some(flat) }
955 }
956}
957
958#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
960pub struct VariantInfo {
961 #[serde(with = "serde_discrim_size")]
963 pub size: DiscriminantSize,
964 pub payload_offset32: u32,
967 pub payload_offset64: u32,
970}
971
972impl VariantInfo {
973 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
976 where
977 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
978 I::IntoIter: ExactSizeIterator,
979 {
980 let cases = cases.into_iter();
981 let size = DiscriminantSize::from_count(cases.len()).unwrap();
982 let abi = CanonicalAbiInfo::variant(cases);
983 (
984 VariantInfo {
985 size,
986 payload_offset32: align_to(u32::from(size), abi.align32),
987 payload_offset64: align_to(u32::from(size), abi.align64),
988 },
989 abi,
990 )
991 }
992 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
994 let size = match DiscriminantSize::from_count(cases.len()) {
995 Some(size) => size,
996 None => unreachable!(),
997 };
998 let abi = CanonicalAbiInfo::variant_static(cases);
999 VariantInfo {
1000 size,
1001 payload_offset32: align_to(size.byte_size(), abi.align32),
1002 payload_offset64: align_to(size.byte_size(), abi.align64),
1003 }
1004 }
1005}
1006
1007mod serde_discrim_size {
1008 use super::DiscriminantSize;
1009 use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
1010
1011 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
1012 where
1013 S: Serializer,
1014 {
1015 u32::from(*disc).serialize(ser)
1016 }
1017
1018 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
1019 where
1020 D: Deserializer<'de>,
1021 {
1022 match u32::deserialize(deser)? {
1023 1 => Ok(DiscriminantSize::Size1),
1024 2 => Ok(DiscriminantSize::Size2),
1025 4 => Ok(DiscriminantSize::Size4),
1026 _ => Err(D::Error::custom("invalid discriminant size")),
1027 }
1028 }
1029}
1030
1031#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1035pub struct TypeRecord {
1036 pub fields: Box<[RecordField]>,
1038 pub abi: CanonicalAbiInfo,
1040}
1041
1042#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1044pub struct RecordField {
1045 pub name: String,
1047 pub ty: InterfaceType,
1049}
1050
1051#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1057pub struct TypeVariant {
1058 pub cases: IndexMap<String, Option<InterfaceType>>,
1060 pub abi: CanonicalAbiInfo,
1062 pub info: VariantInfo,
1064}
1065
1066impl Hash for TypeVariant {
1067 fn hash<H: Hasher>(&self, h: &mut H) {
1068 let TypeVariant { cases, abi, info } = self;
1069 cases.len().hash(h);
1070 for pair in cases {
1071 pair.hash(h);
1072 }
1073 abi.hash(h);
1074 info.hash(h);
1075 }
1076}
1077
1078#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1083pub struct TypeTuple {
1084 pub types: Box<[InterfaceType]>,
1086 pub abi: CanonicalAbiInfo,
1088}
1089
1090#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1095pub struct TypeFlags {
1096 pub names: IndexSet<String>,
1098 pub abi: CanonicalAbiInfo,
1100}
1101
1102impl Hash for TypeFlags {
1103 fn hash<H: Hasher>(&self, h: &mut H) {
1104 let TypeFlags { names, abi } = self;
1105 names.len().hash(h);
1106 for name in names {
1107 name.hash(h);
1108 }
1109 abi.hash(h);
1110 }
1111}
1112
1113#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1119pub struct TypeEnum {
1120 pub names: IndexSet<String>,
1122 pub abi: CanonicalAbiInfo,
1124 pub info: VariantInfo,
1126}
1127
1128impl Hash for TypeEnum {
1129 fn hash<H: Hasher>(&self, h: &mut H) {
1130 let TypeEnum { names, abi, info } = self;
1131 names.len().hash(h);
1132 for name in names {
1133 name.hash(h);
1134 }
1135 abi.hash(h);
1136 info.hash(h);
1137 }
1138}
1139
1140#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1142pub struct TypeOption {
1143 pub ty: InterfaceType,
1145 pub abi: CanonicalAbiInfo,
1147 pub info: VariantInfo,
1149}
1150
1151#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1153pub struct TypeResult {
1154 pub ok: Option<InterfaceType>,
1156 pub err: Option<InterfaceType>,
1158 pub abi: CanonicalAbiInfo,
1160 pub info: VariantInfo,
1162}
1163
1164#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1166pub struct TypeFuture {
1167 pub payload: Option<InterfaceType>,
1169}
1170
1171#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1173pub struct TypeFutureTable {
1174 pub ty: TypeFutureIndex,
1176 pub instance: RuntimeComponentInstanceIndex,
1178}
1179
1180#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1182pub struct TypeStream {
1183 pub payload: Option<InterfaceType>,
1185}
1186
1187#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1189pub struct TypeStreamTable {
1190 pub ty: TypeStreamIndex,
1192 pub instance: RuntimeComponentInstanceIndex,
1194}
1195
1196#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1198pub struct TypeErrorContextTable {
1199 pub instance: RuntimeComponentInstanceIndex,
1201}
1202
1203#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1205pub enum TypeResourceTable {
1206 Concrete {
1213 ty: ResourceIndex,
1218
1219 instance: RuntimeComponentInstanceIndex,
1221 },
1222
1223 Abstract(AbstractResourceIndex),
1227}
1228
1229impl TypeResourceTable {
1230 pub fn unwrap_concrete_ty(&self) -> ResourceIndex {
1237 match self {
1238 TypeResourceTable::Concrete { ty, .. } => *ty,
1239 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1240 }
1241 }
1242
1243 pub fn unwrap_concrete_instance(&self) -> RuntimeComponentInstanceIndex {
1250 match self {
1251 TypeResourceTable::Concrete { instance, .. } => *instance,
1252 TypeResourceTable::Abstract(_) => panic!("not a concrete resource table"),
1253 }
1254 }
1255}
1256
1257#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1259pub struct TypeList {
1260 pub element: InterfaceType,
1262}
1263
1264#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1266pub struct TypeMap {
1267 pub key: InterfaceType,
1269 pub value: InterfaceType,
1271 pub entry_abi: CanonicalAbiInfo,
1273 pub value_offset32: u32,
1276 pub value_offset64: u32,
1279}
1280
1281#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1283pub struct TypeFixedLengthList {
1284 pub element: InterfaceType,
1286 pub size: u32,
1288 pub abi: CanonicalAbiInfo,
1290}
1291
1292pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1294 MAX_FLAT_PARAMS
1295} else {
1296 MAX_FLAT_RESULTS
1297};
1298
1299const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1300 const MAX: u8 = MAX_FLAT_TYPES as u8;
1301 let sum = match (a, b) {
1302 (Some(a), Some(b)) => match a.checked_add(b) {
1303 Some(c) => c,
1304 None => return None,
1305 },
1306 _ => return None,
1307 };
1308 if sum > MAX { None } else { Some(sum) }
1309}
1310
1311const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1312 match (a, b) {
1313 (Some(a), Some(b)) => {
1314 if a > b {
1315 Some(a)
1316 } else {
1317 Some(b)
1318 }
1319 }
1320 _ => None,
1321 }
1322}
1323
1324pub struct FlatTypes<'a> {
1326 pub memory32: &'a [FlatType],
1328 pub memory64: &'a [FlatType],
1330}
1331
1332impl FlatTypes<'_> {
1333 pub fn len(&self) -> usize {
1337 assert_eq!(self.memory32.len(), self.memory64.len());
1338 self.memory32.len()
1339 }
1340}
1341
1342#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1346#[expect(missing_docs, reason = "self-describing variants")]
1347pub enum FlatType {
1348 I32,
1349 I64,
1350 F32,
1351 F64,
1352}