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}