1use crate::component::{MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
2use crate::{prelude::*, TypeTrace};
3use crate::{EntityType, ModuleInternedTypeIndex, ModuleTypes, PrimaryMap};
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 pub struct TypeFutureTableIndex(u32);
99 pub struct TypeStreamIndex(u32);
101 pub struct TypeStreamTableIndex(u32);
106
107 pub struct TypeComponentLocalErrorContextTableIndex(u32);
112
113 pub struct TypeComponentGlobalErrorContextTableIndex(u32);
119
120 pub struct TypeTaskReturnIndex(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 TrampolineIndex(u32);
232
233 pub struct ExportIndex(u32);
235}
236
237pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
240
241#[derive(Debug, Clone, Copy)]
244#[allow(missing_docs, reason = "self-describing variants")]
245pub enum ComponentItem {
246 Func(ComponentFuncIndex),
247 Module(ModuleIndex),
248 Component(ComponentIndex),
249 ComponentInstance(ComponentInstanceIndex),
250 Type(ComponentAnyTypeId),
251}
252
253#[derive(Default, Serialize, Deserialize)]
259pub struct ComponentTypes {
260 pub(super) modules: PrimaryMap<TypeModuleIndex, TypeModule>,
261 pub(super) components: PrimaryMap<TypeComponentIndex, TypeComponent>,
262 pub(super) component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
263 pub(super) functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
264 pub(super) lists: PrimaryMap<TypeListIndex, TypeList>,
265 pub(super) records: PrimaryMap<TypeRecordIndex, TypeRecord>,
266 pub(super) variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
267 pub(super) tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
268 pub(super) enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
269 pub(super) flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
270 pub(super) options: PrimaryMap<TypeOptionIndex, TypeOption>,
271 pub(super) results: PrimaryMap<TypeResultIndex, TypeResult>,
272 pub(super) resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
273 pub(super) module_types: Option<ModuleTypes>,
274 pub(super) futures: PrimaryMap<TypeFutureIndex, TypeFuture>,
275 pub(super) future_tables: PrimaryMap<TypeFutureTableIndex, TypeFutureTable>,
276 pub(super) streams: PrimaryMap<TypeStreamIndex, TypeStream>,
277 pub(super) stream_tables: PrimaryMap<TypeStreamTableIndex, TypeStreamTable>,
278 pub(super) error_context_tables:
279 PrimaryMap<TypeComponentLocalErrorContextTableIndex, TypeErrorContextTable>,
280 pub(super) task_returns: PrimaryMap<TypeTaskReturnIndex, TypeTaskReturn>,
281}
282
283impl TypeTrace for ComponentTypes {
284 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
285 where
286 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
287 {
288 for (_, m) in &self.modules {
289 m.trace(func)?;
290 }
291 if let Some(m) = self.module_types.as_ref() {
292 m.trace(func)?;
293 }
294 Ok(())
295 }
296
297 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
298 where
299 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
300 {
301 for (_, m) in &mut self.modules {
302 m.trace_mut(func)?;
303 }
304 if let Some(m) = self.module_types.as_mut() {
305 m.trace_mut(func)?;
306 }
307 Ok(())
308 }
309}
310
311impl ComponentTypes {
312 pub fn module_types(&self) -> &ModuleTypes {
314 self.module_types.as_ref().unwrap()
315 }
316
317 pub fn module_types_mut(&mut self) -> &mut ModuleTypes {
319 self.module_types.as_mut().unwrap()
320 }
321
322 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
324 match ty {
325 InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
326 &CanonicalAbiInfo::SCALAR1
327 }
328
329 InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
330
331 InterfaceType::U32
332 | InterfaceType::S32
333 | InterfaceType::Float32
334 | InterfaceType::Char
335 | InterfaceType::Own(_)
336 | InterfaceType::Borrow(_)
337 | InterfaceType::Future(_)
338 | InterfaceType::Stream(_)
339 | InterfaceType::ErrorContext(_) => &CanonicalAbiInfo::SCALAR4,
340
341 InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
342 &CanonicalAbiInfo::SCALAR8
343 }
344
345 InterfaceType::String | InterfaceType::List(_) => &CanonicalAbiInfo::POINTER_PAIR,
346
347 InterfaceType::Record(i) => &self[*i].abi,
348 InterfaceType::Variant(i) => &self[*i].abi,
349 InterfaceType::Tuple(i) => &self[*i].abi,
350 InterfaceType::Flags(i) => &self[*i].abi,
351 InterfaceType::Enum(i) => &self[*i].abi,
352 InterfaceType::Option(i) => &self[*i].abi,
353 InterfaceType::Result(i) => &self[*i].abi,
354 }
355 }
356
357 pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
359 self.resource_tables.push(table)
360 }
361}
362
363macro_rules! impl_index {
364 ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
365 impl core::ops::Index<$ty> for ComponentTypes {
366 type Output = $output;
367 #[inline]
368 fn index(&self, idx: $ty) -> &$output {
369 &self.$field[idx]
370 }
371 }
372
373 #[cfg(feature = "compile")]
374 impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
375 type Output = $output;
376 #[inline]
377 fn index(&self, idx: $ty) -> &$output {
378 &self.component_types()[idx]
379 }
380 }
381 )*)
382}
383
384impl_index! {
385 impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
386 impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
387 impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
388 impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
389 impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
390 impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
391 impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
392 impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
393 impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
394 impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
395 impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
396 impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
397 impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
398 impl Index<TypeFutureIndex> for ComponentTypes { TypeFuture => futures }
399 impl Index<TypeStreamIndex> for ComponentTypes { TypeStream => streams }
400 impl Index<TypeFutureTableIndex> for ComponentTypes { TypeFutureTable => future_tables }
401 impl Index<TypeStreamTableIndex> for ComponentTypes { TypeStreamTable => stream_tables }
402 impl Index<TypeComponentLocalErrorContextTableIndex> for ComponentTypes { TypeErrorContextTable => error_context_tables }
403}
404
405impl<T> Index<T> for ComponentTypes
408where
409 ModuleTypes: Index<T>,
410{
411 type Output = <ModuleTypes as Index<T>>::Output;
412 fn index(&self, idx: T) -> &Self::Output {
413 self.module_types.as_ref().unwrap().index(idx)
414 }
415}
416
417#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
423pub enum TypeDef {
424 Component(TypeComponentIndex),
426 ComponentInstance(TypeComponentInstanceIndex),
428 ComponentFunc(TypeFuncIndex),
430 Interface(InterfaceType),
432 Module(TypeModuleIndex),
434 CoreFunc(ModuleInternedTypeIndex),
436 Resource(TypeResourceTableIndex),
441}
442
443impl TypeDef {
444 pub fn desc(&self) -> &str {
446 match self {
447 TypeDef::Component(_) => "component",
448 TypeDef::ComponentInstance(_) => "instance",
449 TypeDef::ComponentFunc(_) => "function",
450 TypeDef::Interface(_) => "type",
451 TypeDef::Module(_) => "core module",
452 TypeDef::CoreFunc(_) => "core function",
453 TypeDef::Resource(_) => "resource",
454 }
455 }
456}
457
458#[derive(Serialize, Deserialize, Default)]
468pub struct TypeModule {
469 pub imports: IndexMap<(String, String), EntityType>,
477
478 pub exports: IndexMap<String, EntityType>,
483}
484
485impl TypeTrace for TypeModule {
486 fn trace<F, E>(&self, func: &mut F) -> Result<(), E>
487 where
488 F: FnMut(crate::EngineOrModuleTypeIndex) -> Result<(), E>,
489 {
490 for ty in self.imports.values() {
491 ty.trace(func)?;
492 }
493 for ty in self.exports.values() {
494 ty.trace(func)?;
495 }
496 Ok(())
497 }
498
499 fn trace_mut<F, E>(&mut self, func: &mut F) -> Result<(), E>
500 where
501 F: FnMut(&mut crate::EngineOrModuleTypeIndex) -> Result<(), E>,
502 {
503 for ty in self.imports.values_mut() {
504 ty.trace_mut(func)?;
505 }
506 for ty in self.exports.values_mut() {
507 ty.trace_mut(func)?;
508 }
509 Ok(())
510 }
511}
512
513#[derive(Serialize, Deserialize, Default)]
515pub struct TypeComponent {
516 pub imports: IndexMap<String, TypeDef>,
518 pub exports: IndexMap<String, TypeDef>,
520}
521
522#[derive(Serialize, Deserialize, Default)]
527pub struct TypeComponentInstance {
528 pub exports: IndexMap<String, TypeDef>,
530}
531
532#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
534pub struct TypeFunc {
535 pub param_names: Vec<String>,
537 pub params: TypeTupleIndex,
539 pub results: TypeTupleIndex,
541 pub task_return_type32: TypeTaskReturnIndex,
543 pub task_return_type64: TypeTaskReturnIndex,
545}
546
547#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
550pub struct TypeTaskReturn {
551 pub params: Vec<FlatType>,
555}
556
557#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
564#[allow(missing_docs, reason = "self-describing variants")]
565pub enum InterfaceType {
566 Bool,
567 S8,
568 U8,
569 S16,
570 U16,
571 S32,
572 U32,
573 S64,
574 U64,
575 Float32,
576 Float64,
577 Char,
578 String,
579 Record(TypeRecordIndex),
580 Variant(TypeVariantIndex),
581 List(TypeListIndex),
582 Tuple(TypeTupleIndex),
583 Flags(TypeFlagsIndex),
584 Enum(TypeEnumIndex),
585 Option(TypeOptionIndex),
586 Result(TypeResultIndex),
587 Own(TypeResourceTableIndex),
588 Borrow(TypeResourceTableIndex),
589 Future(TypeFutureTableIndex),
590 Stream(TypeStreamTableIndex),
591 ErrorContext(TypeComponentLocalErrorContextTableIndex),
592}
593
594impl From<&wasmparser::PrimitiveValType> for InterfaceType {
595 fn from(ty: &wasmparser::PrimitiveValType) -> InterfaceType {
596 match ty {
597 wasmparser::PrimitiveValType::Bool => InterfaceType::Bool,
598 wasmparser::PrimitiveValType::S8 => InterfaceType::S8,
599 wasmparser::PrimitiveValType::U8 => InterfaceType::U8,
600 wasmparser::PrimitiveValType::S16 => InterfaceType::S16,
601 wasmparser::PrimitiveValType::U16 => InterfaceType::U16,
602 wasmparser::PrimitiveValType::S32 => InterfaceType::S32,
603 wasmparser::PrimitiveValType::U32 => InterfaceType::U32,
604 wasmparser::PrimitiveValType::S64 => InterfaceType::S64,
605 wasmparser::PrimitiveValType::U64 => InterfaceType::U64,
606 wasmparser::PrimitiveValType::F32 => InterfaceType::Float32,
607 wasmparser::PrimitiveValType::F64 => InterfaceType::Float64,
608 wasmparser::PrimitiveValType::Char => InterfaceType::Char,
609 wasmparser::PrimitiveValType::String => InterfaceType::String,
610 }
611 }
612}
613
614#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
617pub struct CanonicalAbiInfo {
618 pub size32: u32,
620 pub align32: u32,
622 pub size64: u32,
624 pub align64: u32,
626 pub flat_count: Option<u8>,
633}
634
635impl Default for CanonicalAbiInfo {
636 fn default() -> CanonicalAbiInfo {
637 CanonicalAbiInfo {
638 size32: 0,
639 align32: 1,
640 size64: 0,
641 align64: 1,
642 flat_count: Some(0),
643 }
644 }
645}
646
647const fn align_to(a: u32, b: u32) -> u32 {
648 assert!(b.is_power_of_two());
649 (a + (b - 1)) & !(b - 1)
650}
651
652const fn max(a: u32, b: u32) -> u32 {
653 if a > b {
654 a
655 } else {
656 b
657 }
658}
659
660impl CanonicalAbiInfo {
661 const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
663 size32: 0,
664 align32: 1,
665 size64: 0,
666 align64: 1,
667 flat_count: Some(0),
668 };
669
670 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
672 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
674 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
676 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
678
679 const fn scalar(size: u32) -> CanonicalAbiInfo {
680 CanonicalAbiInfo {
681 size32: size,
682 align32: size,
683 size64: size,
684 align64: size,
685 flat_count: Some(1),
686 }
687 }
688
689 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
691 size32: 8,
692 align32: 4,
693 size64: 16,
694 align64: 8,
695 flat_count: Some(2),
696 };
697
698 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
700 let mut ret = CanonicalAbiInfo::default();
704 for field in fields {
705 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
706 ret.align32 = ret.align32.max(field.align32);
707 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
708 ret.align64 = ret.align64.max(field.align64);
709 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
710 }
711 ret.size32 = align_to(ret.size32, ret.align32);
712 ret.size64 = align_to(ret.size64, ret.align64);
713 return ret;
714 }
715
716 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
718 let mut ret = CanonicalAbiInfo::ZERO;
722 let mut i = 0;
723 while i < fields.len() {
724 let field = &fields[i];
725 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
726 ret.align32 = max(ret.align32, field.align32);
727 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
728 ret.align64 = max(ret.align64, field.align64);
729 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
730 i += 1;
731 }
732 ret.size32 = align_to(ret.size32, ret.align32);
733 ret.size64 = align_to(ret.size64, ret.align64);
734 return ret;
735 }
736
737 pub fn next_field32(&self, offset: &mut u32) -> u32 {
740 *offset = align_to(*offset, self.align32) + self.size32;
741 *offset - self.size32
742 }
743
744 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
746 let cur = u32::try_from(*offset).unwrap();
747 let cur = align_to(cur, self.align32) + self.size32;
748 *offset = usize::try_from(cur).unwrap();
749 usize::try_from(cur - self.size32).unwrap()
750 }
751
752 pub fn next_field64(&self, offset: &mut u32) -> u32 {
755 *offset = align_to(*offset, self.align64) + self.size64;
756 *offset - self.size64
757 }
758
759 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
761 let cur = u32::try_from(*offset).unwrap();
762 let cur = align_to(cur, self.align64) + self.size64;
763 *offset = usize::try_from(cur).unwrap();
764 usize::try_from(cur - self.size64).unwrap()
765 }
766
767 pub const fn flags(count: usize) -> CanonicalAbiInfo {
769 let (size, align, flat_count) = match FlagsSize::from_count(count) {
770 FlagsSize::Size0 => (0, 1, 0),
771 FlagsSize::Size1 => (1, 1, 1),
772 FlagsSize::Size2 => (2, 2, 1),
773 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
774 };
775 CanonicalAbiInfo {
776 size32: size,
777 align32: align,
778 size64: size,
779 align64: align,
780 flat_count: Some(flat_count),
781 }
782 }
783
784 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
785 where
786 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
787 I::IntoIter: ExactSizeIterator,
788 {
789 let cases = cases.into_iter();
793 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
794 let mut max_size32 = 0;
795 let mut max_align32 = discrim_size;
796 let mut max_size64 = 0;
797 let mut max_align64 = discrim_size;
798 let mut max_case_count = Some(0);
799 for case in cases {
800 if let Some(case) = case {
801 max_size32 = max_size32.max(case.size32);
802 max_align32 = max_align32.max(case.align32);
803 max_size64 = max_size64.max(case.size64);
804 max_align64 = max_align64.max(case.align64);
805 max_case_count = max_flat(max_case_count, case.flat_count);
806 }
807 }
808 CanonicalAbiInfo {
809 size32: align_to(
810 align_to(discrim_size, max_align32) + max_size32,
811 max_align32,
812 ),
813 align32: max_align32,
814 size64: align_to(
815 align_to(discrim_size, max_align64) + max_size64,
816 max_align64,
817 ),
818 align64: max_align64,
819 flat_count: add_flat(max_case_count, Some(1)),
820 }
821 }
822
823 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
825 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
829 Some(size) => size.byte_size(),
830 None => unreachable!(),
831 };
832 let mut max_size32 = 0;
833 let mut max_align32 = discrim_size;
834 let mut max_size64 = 0;
835 let mut max_align64 = discrim_size;
836 let mut max_case_count = Some(0);
837 let mut i = 0;
838 while i < cases.len() {
839 let case = &cases[i];
840 if let Some(case) = case {
841 max_size32 = max(max_size32, case.size32);
842 max_align32 = max(max_align32, case.align32);
843 max_size64 = max(max_size64, case.size64);
844 max_align64 = max(max_align64, case.align64);
845 max_case_count = max_flat(max_case_count, case.flat_count);
846 }
847 i += 1;
848 }
849 CanonicalAbiInfo {
850 size32: align_to(
851 align_to(discrim_size, max_align32) + max_size32,
852 max_align32,
853 ),
854 align32: max_align32,
855 size64: align_to(
856 align_to(discrim_size, max_align64) + max_size64,
857 max_align64,
858 ),
859 align64: max_align64,
860 flat_count: add_flat(max_case_count, Some(1)),
861 }
862 }
863
864 pub const fn enum_(cases: usize) -> CanonicalAbiInfo {
866 let discrim_size = match DiscriminantSize::from_count(cases) {
870 Some(size) => size.byte_size(),
871 None => unreachable!(),
872 };
873 CanonicalAbiInfo {
874 size32: discrim_size,
875 align32: discrim_size,
876 size64: discrim_size,
877 align64: discrim_size,
878 flat_count: Some(1),
879 }
880 }
881
882 pub fn flat_count(&self, max: usize) -> Option<usize> {
885 let flat = usize::from(self.flat_count?);
886 if flat > max {
887 None
888 } else {
889 Some(flat)
890 }
891 }
892}
893
894#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
896pub struct VariantInfo {
897 #[serde(with = "serde_discrim_size")]
899 pub size: DiscriminantSize,
900 pub payload_offset32: u32,
903 pub payload_offset64: u32,
906}
907
908impl VariantInfo {
909 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
912 where
913 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
914 I::IntoIter: ExactSizeIterator,
915 {
916 let cases = cases.into_iter();
917 let size = DiscriminantSize::from_count(cases.len()).unwrap();
918 let abi = CanonicalAbiInfo::variant(cases);
919 (
920 VariantInfo {
921 size,
922 payload_offset32: align_to(u32::from(size), abi.align32),
923 payload_offset64: align_to(u32::from(size), abi.align64),
924 },
925 abi,
926 )
927 }
928 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
930 let size = match DiscriminantSize::from_count(cases.len()) {
931 Some(size) => size,
932 None => unreachable!(),
933 };
934 let abi = CanonicalAbiInfo::variant_static(cases);
935 VariantInfo {
936 size,
937 payload_offset32: align_to(size.byte_size(), abi.align32),
938 payload_offset64: align_to(size.byte_size(), abi.align64),
939 }
940 }
941}
942
943mod serde_discrim_size {
944 use super::DiscriminantSize;
945 use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
946
947 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
948 where
949 S: Serializer,
950 {
951 u32::from(*disc).serialize(ser)
952 }
953
954 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
955 where
956 D: Deserializer<'de>,
957 {
958 match u32::deserialize(deser)? {
959 1 => Ok(DiscriminantSize::Size1),
960 2 => Ok(DiscriminantSize::Size2),
961 4 => Ok(DiscriminantSize::Size4),
962 _ => Err(D::Error::custom("invalid discriminant size")),
963 }
964 }
965}
966
967#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
971pub struct TypeRecord {
972 pub fields: Box<[RecordField]>,
974 pub abi: CanonicalAbiInfo,
976}
977
978#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
980pub struct RecordField {
981 pub name: String,
983 pub ty: InterfaceType,
985}
986
987#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
993pub struct TypeVariant {
994 pub cases: IndexMap<String, Option<InterfaceType>>,
996 pub abi: CanonicalAbiInfo,
998 pub info: VariantInfo,
1000}
1001
1002impl Hash for TypeVariant {
1003 fn hash<H: Hasher>(&self, h: &mut H) {
1004 let TypeVariant { cases, abi, info } = self;
1005 cases.len().hash(h);
1006 for pair in cases {
1007 pair.hash(h);
1008 }
1009 abi.hash(h);
1010 info.hash(h);
1011 }
1012}
1013
1014#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1019pub struct TypeTuple {
1020 pub types: Box<[InterfaceType]>,
1022 pub abi: CanonicalAbiInfo,
1024}
1025
1026#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1031pub struct TypeFlags {
1032 pub names: IndexSet<String>,
1034 pub abi: CanonicalAbiInfo,
1036}
1037
1038impl Hash for TypeFlags {
1039 fn hash<H: Hasher>(&self, h: &mut H) {
1040 let TypeFlags { names, abi } = self;
1041 names.len().hash(h);
1042 for name in names {
1043 name.hash(h);
1044 }
1045 abi.hash(h);
1046 }
1047}
1048
1049#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
1055pub struct TypeEnum {
1056 pub names: IndexSet<String>,
1058 pub abi: CanonicalAbiInfo,
1060 pub info: VariantInfo,
1062}
1063
1064impl Hash for TypeEnum {
1065 fn hash<H: Hasher>(&self, h: &mut H) {
1066 let TypeEnum { names, abi, info } = self;
1067 names.len().hash(h);
1068 for name in names {
1069 name.hash(h);
1070 }
1071 abi.hash(h);
1072 info.hash(h);
1073 }
1074}
1075
1076#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1078pub struct TypeOption {
1079 pub ty: InterfaceType,
1081 pub abi: CanonicalAbiInfo,
1083 pub info: VariantInfo,
1085}
1086
1087#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1089pub struct TypeResult {
1090 pub ok: Option<InterfaceType>,
1092 pub err: Option<InterfaceType>,
1094 pub abi: CanonicalAbiInfo,
1096 pub info: VariantInfo,
1098}
1099
1100#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1102pub struct TypeFuture {
1103 pub payload: Option<InterfaceType>,
1105}
1106
1107#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1109pub struct TypeFutureTable {
1110 pub ty: TypeFutureIndex,
1112 pub instance: RuntimeComponentInstanceIndex,
1114}
1115
1116#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1118pub struct TypeStream {
1119 pub payload: Option<InterfaceType>,
1121}
1122
1123#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1125pub struct TypeStreamTable {
1126 pub ty: TypeStreamIndex,
1128 pub instance: RuntimeComponentInstanceIndex,
1130}
1131
1132#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1134pub struct TypeErrorContextTable {
1135 pub instance: RuntimeComponentInstanceIndex,
1137}
1138
1139#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1141pub struct TypeResourceTable {
1142 pub ty: ResourceIndex,
1147
1148 pub instance: RuntimeComponentInstanceIndex,
1150}
1151
1152#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
1154pub struct TypeList {
1155 pub element: InterfaceType,
1157}
1158
1159pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
1161 MAX_FLAT_PARAMS
1162} else {
1163 MAX_FLAT_RESULTS
1164};
1165
1166const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1167 const MAX: u8 = MAX_FLAT_TYPES as u8;
1168 let sum = match (a, b) {
1169 (Some(a), Some(b)) => match a.checked_add(b) {
1170 Some(c) => c,
1171 None => return None,
1172 },
1173 _ => return None,
1174 };
1175 if sum > MAX {
1176 None
1177 } else {
1178 Some(sum)
1179 }
1180}
1181
1182const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1183 match (a, b) {
1184 (Some(a), Some(b)) => {
1185 if a > b {
1186 Some(a)
1187 } else {
1188 Some(b)
1189 }
1190 }
1191 _ => None,
1192 }
1193}
1194
1195pub struct FlatTypes<'a> {
1197 pub memory32: &'a [FlatType],
1199 pub memory64: &'a [FlatType],
1201}
1202
1203impl FlatTypes<'_> {
1204 pub fn len(&self) -> usize {
1208 assert_eq!(self.memory32.len(), self.memory64.len());
1209 self.memory32.len()
1210 }
1211}
1212
1213#[derive(Serialize, Deserialize, Hash, Debug, PartialEq, Eq, Copy, Clone)]
1217#[allow(missing_docs, reason = "self-describing variants")]
1218pub enum FlatType {
1219 I32,
1220 I64,
1221 F32,
1222 F64,
1223}