1use crate::component::{MAX_FLAT_PARAMS, MAX_FLAT_RESULTS};
2use crate::prelude::*;
3use crate::{EntityType, ModuleTypes, PrimaryMap};
4use core::hash::{Hash, Hasher};
5use core::ops::Index;
6use serde_derive::{Deserialize, Serialize};
7use wasmparser::types;
8use wasmtime_component_util::{DiscriminantSize, FlagsSize};
9use wasmtime_types::ModuleInternedTypeIndex;
10
11pub use wasmtime_types::StaticModuleIndex;
12
13macro_rules! indices {
14 ($(
15 $(#[$a:meta])*
16 pub struct $name:ident(u32);
17 )*) => ($(
18 $(#[$a])*
19 #[derive(
20 Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug,
21 Serialize, Deserialize,
22 )]
23 #[repr(transparent)]
24 pub struct $name(u32);
25 cranelift_entity::entity_impl!($name);
26 )*);
27}
28
29indices! {
30 pub struct ComponentTypeIndex(u32);
38
39 pub struct ModuleIndex(u32);
41
42 pub struct ComponentIndex(u32);
44
45 pub struct ModuleInstanceIndex(u32);
47
48 pub struct ComponentInstanceIndex(u32);
50
51 pub struct ComponentFuncIndex(u32);
53
54 pub struct TypeComponentIndex(u32);
62
63 pub struct TypeComponentInstanceIndex(u32);
66
67 pub struct TypeModuleIndex(u32);
70
71 pub struct TypeFuncIndex(u32);
74
75 pub struct TypeRecordIndex(u32);
77 pub struct TypeVariantIndex(u32);
79 pub struct TypeTupleIndex(u32);
81 pub struct TypeFlagsIndex(u32);
83 pub struct TypeEnumIndex(u32);
85 pub struct TypeOptionIndex(u32);
88 pub struct TypeResultIndex(u32);
91 pub struct TypeListIndex(u32);
93
94 pub struct TypeResourceTableIndex(u32);
109
110 pub struct ResourceIndex(u32);
123
124 pub struct DefinedResourceIndex(u32);
130
131 pub struct ModuleUpvarIndex(u32);
138
139 pub struct ComponentUpvarIndex(u32);
141
142 pub struct StaticComponentIndex(u32);
144
145 pub struct RuntimeInstanceIndex(u32);
154
155 pub struct RuntimeComponentInstanceIndex(u32);
157
158 pub struct ImportIndex(u32);
163
164 pub struct RuntimeImportIndex(u32);
170
171 pub struct LoweredIndex(u32);
177
178 pub struct RuntimeMemoryIndex(u32);
186
187 pub struct RuntimeReallocIndex(u32);
189
190 pub struct RuntimePostReturnIndex(u32);
192
193 pub struct TrampolineIndex(u32);
200
201 pub struct ExportIndex(u32);
203}
204
205pub use crate::{FuncIndex, GlobalIndex, MemoryIndex, TableIndex};
208
209#[derive(Debug, Clone, Copy)]
212#[allow(missing_docs)]
213pub enum ComponentItem {
214 Func(ComponentFuncIndex),
215 Module(ModuleIndex),
216 Component(ComponentIndex),
217 ComponentInstance(ComponentInstanceIndex),
218 Type(types::ComponentAnyTypeId),
219}
220
221#[derive(Default, Serialize, Deserialize)]
227pub struct ComponentTypes {
228 pub(super) modules: PrimaryMap<TypeModuleIndex, TypeModule>,
229 pub(super) components: PrimaryMap<TypeComponentIndex, TypeComponent>,
230 pub(super) component_instances: PrimaryMap<TypeComponentInstanceIndex, TypeComponentInstance>,
231 pub(super) functions: PrimaryMap<TypeFuncIndex, TypeFunc>,
232 pub(super) lists: PrimaryMap<TypeListIndex, TypeList>,
233 pub(super) records: PrimaryMap<TypeRecordIndex, TypeRecord>,
234 pub(super) variants: PrimaryMap<TypeVariantIndex, TypeVariant>,
235 pub(super) tuples: PrimaryMap<TypeTupleIndex, TypeTuple>,
236 pub(super) enums: PrimaryMap<TypeEnumIndex, TypeEnum>,
237 pub(super) flags: PrimaryMap<TypeFlagsIndex, TypeFlags>,
238 pub(super) options: PrimaryMap<TypeOptionIndex, TypeOption>,
239 pub(super) results: PrimaryMap<TypeResultIndex, TypeResult>,
240 pub(super) resource_tables: PrimaryMap<TypeResourceTableIndex, TypeResourceTable>,
241
242 pub(super) module_types: Option<ModuleTypes>,
243}
244
245impl ComponentTypes {
246 pub fn module_types(&self) -> &ModuleTypes {
248 self.module_types.as_ref().unwrap()
249 }
250
251 pub fn canonical_abi(&self, ty: &InterfaceType) -> &CanonicalAbiInfo {
253 match ty {
254 InterfaceType::U8 | InterfaceType::S8 | InterfaceType::Bool => {
255 &CanonicalAbiInfo::SCALAR1
256 }
257
258 InterfaceType::U16 | InterfaceType::S16 => &CanonicalAbiInfo::SCALAR2,
259
260 InterfaceType::U32
261 | InterfaceType::S32
262 | InterfaceType::Float32
263 | InterfaceType::Char
264 | InterfaceType::Own(_)
265 | InterfaceType::Borrow(_) => &CanonicalAbiInfo::SCALAR4,
266
267 InterfaceType::U64 | InterfaceType::S64 | InterfaceType::Float64 => {
268 &CanonicalAbiInfo::SCALAR8
269 }
270
271 InterfaceType::String | InterfaceType::List(_) => &CanonicalAbiInfo::POINTER_PAIR,
272
273 InterfaceType::Record(i) => &self[*i].abi,
274 InterfaceType::Variant(i) => &self[*i].abi,
275 InterfaceType::Tuple(i) => &self[*i].abi,
276 InterfaceType::Flags(i) => &self[*i].abi,
277 InterfaceType::Enum(i) => &self[*i].abi,
278 InterfaceType::Option(i) => &self[*i].abi,
279 InterfaceType::Result(i) => &self[*i].abi,
280 }
281 }
282
283 pub fn push_resource_table(&mut self, table: TypeResourceTable) -> TypeResourceTableIndex {
285 self.resource_tables.push(table)
286 }
287}
288
289macro_rules! impl_index {
290 ($(impl Index<$ty:ident> for ComponentTypes { $output:ident => $field:ident })*) => ($(
291 impl core::ops::Index<$ty> for ComponentTypes {
292 type Output = $output;
293 #[inline]
294 fn index(&self, idx: $ty) -> &$output {
295 &self.$field[idx]
296 }
297 }
298
299 #[cfg(feature = "compile")]
300 impl core::ops::Index<$ty> for super::ComponentTypesBuilder {
301 type Output = $output;
302 #[inline]
303 fn index(&self, idx: $ty) -> &$output {
304 &self.component_types()[idx]
305 }
306 }
307 )*)
308}
309
310impl_index! {
311 impl Index<TypeModuleIndex> for ComponentTypes { TypeModule => modules }
312 impl Index<TypeComponentIndex> for ComponentTypes { TypeComponent => components }
313 impl Index<TypeComponentInstanceIndex> for ComponentTypes { TypeComponentInstance => component_instances }
314 impl Index<TypeFuncIndex> for ComponentTypes { TypeFunc => functions }
315 impl Index<TypeRecordIndex> for ComponentTypes { TypeRecord => records }
316 impl Index<TypeVariantIndex> for ComponentTypes { TypeVariant => variants }
317 impl Index<TypeTupleIndex> for ComponentTypes { TypeTuple => tuples }
318 impl Index<TypeEnumIndex> for ComponentTypes { TypeEnum => enums }
319 impl Index<TypeFlagsIndex> for ComponentTypes { TypeFlags => flags }
320 impl Index<TypeOptionIndex> for ComponentTypes { TypeOption => options }
321 impl Index<TypeResultIndex> for ComponentTypes { TypeResult => results }
322 impl Index<TypeListIndex> for ComponentTypes { TypeList => lists }
323 impl Index<TypeResourceTableIndex> for ComponentTypes { TypeResourceTable => resource_tables }
324}
325
326impl<T> Index<T> for ComponentTypes
329where
330 ModuleTypes: Index<T>,
331{
332 type Output = <ModuleTypes as Index<T>>::Output;
333 fn index(&self, idx: T) -> &Self::Output {
334 self.module_types.as_ref().unwrap().index(idx)
335 }
336}
337
338#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
344pub enum TypeDef {
345 Component(TypeComponentIndex),
347 ComponentInstance(TypeComponentInstanceIndex),
349 ComponentFunc(TypeFuncIndex),
351 Interface(InterfaceType),
353 Module(TypeModuleIndex),
355 CoreFunc(ModuleInternedTypeIndex),
357 Resource(TypeResourceTableIndex),
362}
363
364impl TypeDef {
365 pub fn desc(&self) -> &str {
367 match self {
368 TypeDef::Component(_) => "component",
369 TypeDef::ComponentInstance(_) => "instance",
370 TypeDef::ComponentFunc(_) => "function",
371 TypeDef::Interface(_) => "type",
372 TypeDef::Module(_) => "core module",
373 TypeDef::CoreFunc(_) => "core function",
374 TypeDef::Resource(_) => "resource",
375 }
376 }
377}
378
379#[derive(Serialize, Deserialize, Default)]
389pub struct TypeModule {
390 pub imports: IndexMap<(String, String), EntityType>,
398
399 pub exports: IndexMap<String, EntityType>,
404}
405
406#[derive(Serialize, Deserialize, Default)]
408pub struct TypeComponent {
409 pub imports: IndexMap<String, TypeDef>,
411 pub exports: IndexMap<String, TypeDef>,
413}
414
415#[derive(Serialize, Deserialize, Default)]
420pub struct TypeComponentInstance {
421 pub exports: IndexMap<String, TypeDef>,
423}
424
425#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
427pub struct TypeFunc {
428 pub params: TypeTupleIndex,
430 pub results: TypeTupleIndex,
432}
433
434#[derive(Serialize, Deserialize, Copy, Clone, Hash, Eq, PartialEq, Debug)]
441#[allow(missing_docs)]
442pub enum InterfaceType {
443 Bool,
444 S8,
445 U8,
446 S16,
447 U16,
448 S32,
449 U32,
450 S64,
451 U64,
452 Float32,
453 Float64,
454 Char,
455 String,
456 Record(TypeRecordIndex),
457 Variant(TypeVariantIndex),
458 List(TypeListIndex),
459 Tuple(TypeTupleIndex),
460 Flags(TypeFlagsIndex),
461 Enum(TypeEnumIndex),
462 Option(TypeOptionIndex),
463 Result(TypeResultIndex),
464 Own(TypeResourceTableIndex),
465 Borrow(TypeResourceTableIndex),
466}
467
468impl From<&wasmparser::PrimitiveValType> for InterfaceType {
469 fn from(ty: &wasmparser::PrimitiveValType) -> InterfaceType {
470 match ty {
471 wasmparser::PrimitiveValType::Bool => InterfaceType::Bool,
472 wasmparser::PrimitiveValType::S8 => InterfaceType::S8,
473 wasmparser::PrimitiveValType::U8 => InterfaceType::U8,
474 wasmparser::PrimitiveValType::S16 => InterfaceType::S16,
475 wasmparser::PrimitiveValType::U16 => InterfaceType::U16,
476 wasmparser::PrimitiveValType::S32 => InterfaceType::S32,
477 wasmparser::PrimitiveValType::U32 => InterfaceType::U32,
478 wasmparser::PrimitiveValType::S64 => InterfaceType::S64,
479 wasmparser::PrimitiveValType::U64 => InterfaceType::U64,
480 wasmparser::PrimitiveValType::F32 => InterfaceType::Float32,
481 wasmparser::PrimitiveValType::F64 => InterfaceType::Float64,
482 wasmparser::PrimitiveValType::Char => InterfaceType::Char,
483 wasmparser::PrimitiveValType::String => InterfaceType::String,
484 }
485 }
486}
487
488#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
491pub struct CanonicalAbiInfo {
492 pub size32: u32,
494 pub align32: u32,
496 pub size64: u32,
498 pub align64: u32,
500 pub flat_count: Option<u8>,
507}
508
509impl Default for CanonicalAbiInfo {
510 fn default() -> CanonicalAbiInfo {
511 CanonicalAbiInfo {
512 size32: 0,
513 align32: 1,
514 size64: 0,
515 align64: 1,
516 flat_count: Some(0),
517 }
518 }
519}
520
521const fn align_to(a: u32, b: u32) -> u32 {
522 assert!(b.is_power_of_two());
523 (a + (b - 1)) & !(b - 1)
524}
525
526const fn max(a: u32, b: u32) -> u32 {
527 if a > b {
528 a
529 } else {
530 b
531 }
532}
533
534impl CanonicalAbiInfo {
535 const ZERO: CanonicalAbiInfo = CanonicalAbiInfo {
537 size32: 0,
538 align32: 1,
539 size64: 0,
540 align64: 1,
541 flat_count: Some(0),
542 };
543
544 pub const SCALAR1: CanonicalAbiInfo = CanonicalAbiInfo::scalar(1);
546 pub const SCALAR2: CanonicalAbiInfo = CanonicalAbiInfo::scalar(2);
548 pub const SCALAR4: CanonicalAbiInfo = CanonicalAbiInfo::scalar(4);
550 pub const SCALAR8: CanonicalAbiInfo = CanonicalAbiInfo::scalar(8);
552
553 const fn scalar(size: u32) -> CanonicalAbiInfo {
554 CanonicalAbiInfo {
555 size32: size,
556 align32: size,
557 size64: size,
558 align64: size,
559 flat_count: Some(1),
560 }
561 }
562
563 pub const POINTER_PAIR: CanonicalAbiInfo = CanonicalAbiInfo {
565 size32: 8,
566 align32: 4,
567 size64: 16,
568 align64: 8,
569 flat_count: Some(2),
570 };
571
572 pub fn record<'a>(fields: impl Iterator<Item = &'a CanonicalAbiInfo>) -> CanonicalAbiInfo {
574 let mut ret = CanonicalAbiInfo::default();
578 for field in fields {
579 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
580 ret.align32 = ret.align32.max(field.align32);
581 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
582 ret.align64 = ret.align64.max(field.align64);
583 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
584 }
585 ret.size32 = align_to(ret.size32, ret.align32);
586 ret.size64 = align_to(ret.size64, ret.align64);
587 return ret;
588 }
589
590 pub const fn record_static(fields: &[CanonicalAbiInfo]) -> CanonicalAbiInfo {
592 let mut ret = CanonicalAbiInfo::ZERO;
596 let mut i = 0;
597 while i < fields.len() {
598 let field = &fields[i];
599 ret.size32 = align_to(ret.size32, field.align32) + field.size32;
600 ret.align32 = max(ret.align32, field.align32);
601 ret.size64 = align_to(ret.size64, field.align64) + field.size64;
602 ret.align64 = max(ret.align64, field.align64);
603 ret.flat_count = add_flat(ret.flat_count, field.flat_count);
604 i += 1;
605 }
606 ret.size32 = align_to(ret.size32, ret.align32);
607 ret.size64 = align_to(ret.size64, ret.align64);
608 return ret;
609 }
610
611 pub fn next_field32(&self, offset: &mut u32) -> u32 {
614 *offset = align_to(*offset, self.align32) + self.size32;
615 *offset - self.size32
616 }
617
618 pub fn next_field32_size(&self, offset: &mut usize) -> usize {
620 let cur = u32::try_from(*offset).unwrap();
621 let cur = align_to(cur, self.align32) + self.size32;
622 *offset = usize::try_from(cur).unwrap();
623 usize::try_from(cur - self.size32).unwrap()
624 }
625
626 pub fn next_field64(&self, offset: &mut u32) -> u32 {
629 *offset = align_to(*offset, self.align64) + self.size64;
630 *offset - self.size64
631 }
632
633 pub fn next_field64_size(&self, offset: &mut usize) -> usize {
635 let cur = u32::try_from(*offset).unwrap();
636 let cur = align_to(cur, self.align64) + self.size64;
637 *offset = usize::try_from(cur).unwrap();
638 usize::try_from(cur - self.size64).unwrap()
639 }
640
641 pub const fn flags(count: usize) -> CanonicalAbiInfo {
643 let (size, align, flat_count) = match FlagsSize::from_count(count) {
644 FlagsSize::Size0 => (0, 1, 0),
645 FlagsSize::Size1 => (1, 1, 1),
646 FlagsSize::Size2 => (2, 2, 1),
647 FlagsSize::Size4Plus(n) => ((n as u32) * 4, 4, n),
648 };
649 CanonicalAbiInfo {
650 size32: size,
651 align32: align,
652 size64: size,
653 align64: align,
654 flat_count: Some(flat_count),
655 }
656 }
657
658 fn variant<'a, I>(cases: I) -> CanonicalAbiInfo
659 where
660 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
661 I::IntoIter: ExactSizeIterator,
662 {
663 let cases = cases.into_iter();
667 let discrim_size = u32::from(DiscriminantSize::from_count(cases.len()).unwrap());
668 let mut max_size32 = 0;
669 let mut max_align32 = discrim_size;
670 let mut max_size64 = 0;
671 let mut max_align64 = discrim_size;
672 let mut max_case_count = Some(0);
673 for case in cases {
674 if let Some(case) = case {
675 max_size32 = max_size32.max(case.size32);
676 max_align32 = max_align32.max(case.align32);
677 max_size64 = max_size64.max(case.size64);
678 max_align64 = max_align64.max(case.align64);
679 max_case_count = max_flat(max_case_count, case.flat_count);
680 }
681 }
682 CanonicalAbiInfo {
683 size32: align_to(
684 align_to(discrim_size, max_align32) + max_size32,
685 max_align32,
686 ),
687 align32: max_align32,
688 size64: align_to(
689 align_to(discrim_size, max_align64) + max_size64,
690 max_align64,
691 ),
692 align64: max_align64,
693 flat_count: add_flat(max_case_count, Some(1)),
694 }
695 }
696
697 pub const fn variant_static(cases: &[Option<CanonicalAbiInfo>]) -> CanonicalAbiInfo {
699 let discrim_size = match DiscriminantSize::from_count(cases.len()) {
703 Some(size) => size.byte_size(),
704 None => unreachable!(),
705 };
706 let mut max_size32 = 0;
707 let mut max_align32 = discrim_size;
708 let mut max_size64 = 0;
709 let mut max_align64 = discrim_size;
710 let mut max_case_count = Some(0);
711 let mut i = 0;
712 while i < cases.len() {
713 let case = &cases[i];
714 if let Some(case) = case {
715 max_size32 = max(max_size32, case.size32);
716 max_align32 = max(max_align32, case.align32);
717 max_size64 = max(max_size64, case.size64);
718 max_align64 = max(max_align64, case.align64);
719 max_case_count = max_flat(max_case_count, case.flat_count);
720 }
721 i += 1;
722 }
723 CanonicalAbiInfo {
724 size32: align_to(
725 align_to(discrim_size, max_align32) + max_size32,
726 max_align32,
727 ),
728 align32: max_align32,
729 size64: align_to(
730 align_to(discrim_size, max_align64) + max_size64,
731 max_align64,
732 ),
733 align64: max_align64,
734 flat_count: add_flat(max_case_count, Some(1)),
735 }
736 }
737
738 pub fn flat_count(&self, max: usize) -> Option<usize> {
741 let flat = usize::from(self.flat_count?);
742 if flat > max {
743 None
744 } else {
745 Some(flat)
746 }
747 }
748}
749
750#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
752pub struct VariantInfo {
753 #[serde(with = "serde_discrim_size")]
755 pub size: DiscriminantSize,
756 pub payload_offset32: u32,
759 pub payload_offset64: u32,
762}
763
764impl VariantInfo {
765 pub fn new<'a, I>(cases: I) -> (VariantInfo, CanonicalAbiInfo)
768 where
769 I: IntoIterator<Item = Option<&'a CanonicalAbiInfo>>,
770 I::IntoIter: ExactSizeIterator,
771 {
772 let cases = cases.into_iter();
773 let size = DiscriminantSize::from_count(cases.len()).unwrap();
774 let abi = CanonicalAbiInfo::variant(cases);
775 (
776 VariantInfo {
777 size,
778 payload_offset32: align_to(u32::from(size), abi.align32),
779 payload_offset64: align_to(u32::from(size), abi.align64),
780 },
781 abi,
782 )
783 }
784 pub const fn new_static(cases: &[Option<CanonicalAbiInfo>]) -> VariantInfo {
786 let size = match DiscriminantSize::from_count(cases.len()) {
787 Some(size) => size,
788 None => unreachable!(),
789 };
790 let abi = CanonicalAbiInfo::variant_static(cases);
791 VariantInfo {
792 size,
793 payload_offset32: align_to(size.byte_size(), abi.align32),
794 payload_offset64: align_to(size.byte_size(), abi.align64),
795 }
796 }
797}
798
799mod serde_discrim_size {
800 use super::DiscriminantSize;
801 use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
802
803 pub fn serialize<S>(disc: &DiscriminantSize, ser: S) -> Result<S::Ok, S::Error>
804 where
805 S: Serializer,
806 {
807 u32::from(*disc).serialize(ser)
808 }
809
810 pub fn deserialize<'de, D>(deser: D) -> Result<DiscriminantSize, D::Error>
811 where
812 D: Deserializer<'de>,
813 {
814 match u32::deserialize(deser)? {
815 1 => Ok(DiscriminantSize::Size1),
816 2 => Ok(DiscriminantSize::Size2),
817 4 => Ok(DiscriminantSize::Size4),
818 _ => Err(D::Error::custom("invalid discriminant size")),
819 }
820 }
821}
822
823#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
827pub struct TypeRecord {
828 pub fields: Box<[RecordField]>,
830 pub abi: CanonicalAbiInfo,
832}
833
834#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
836pub struct RecordField {
837 pub name: String,
839 pub ty: InterfaceType,
841}
842
843#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
849pub struct TypeVariant {
850 pub cases: IndexMap<String, Option<InterfaceType>>,
852 pub abi: CanonicalAbiInfo,
854 pub info: VariantInfo,
856}
857
858impl Hash for TypeVariant {
859 fn hash<H: Hasher>(&self, h: &mut H) {
860 let TypeVariant { cases, abi, info } = self;
861 cases.len().hash(h);
862 for pair in cases {
863 pair.hash(h);
864 }
865 abi.hash(h);
866 info.hash(h);
867 }
868}
869
870#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
875pub struct TypeTuple {
876 pub types: Box<[InterfaceType]>,
878 pub abi: CanonicalAbiInfo,
880}
881
882#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
887pub struct TypeFlags {
888 pub names: IndexSet<String>,
890 pub abi: CanonicalAbiInfo,
892}
893
894impl Hash for TypeFlags {
895 fn hash<H: Hasher>(&self, h: &mut H) {
896 let TypeFlags { names, abi } = self;
897 names.len().hash(h);
898 for name in names {
899 name.hash(h);
900 }
901 abi.hash(h);
902 }
903}
904
905#[derive(Serialize, Deserialize, Clone, Eq, PartialEq, Debug)]
911pub struct TypeEnum {
912 pub names: IndexSet<String>,
914 pub abi: CanonicalAbiInfo,
916 pub info: VariantInfo,
918}
919
920impl Hash for TypeEnum {
921 fn hash<H: Hasher>(&self, h: &mut H) {
922 let TypeEnum { names, abi, info } = self;
923 names.len().hash(h);
924 for name in names {
925 name.hash(h);
926 }
927 abi.hash(h);
928 info.hash(h);
929 }
930}
931
932#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
934pub struct TypeOption {
935 pub ty: InterfaceType,
937 pub abi: CanonicalAbiInfo,
939 pub info: VariantInfo,
941}
942
943#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
945pub struct TypeResult {
946 pub ok: Option<InterfaceType>,
948 pub err: Option<InterfaceType>,
950 pub abi: CanonicalAbiInfo,
952 pub info: VariantInfo,
954}
955
956#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
958pub struct TypeResourceTable {
959 pub ty: ResourceIndex,
964
965 pub instance: RuntimeComponentInstanceIndex,
967}
968
969#[derive(Serialize, Deserialize, Clone, Hash, Eq, PartialEq, Debug)]
971pub struct TypeList {
972 pub element: InterfaceType,
974}
975
976pub const MAX_FLAT_TYPES: usize = if MAX_FLAT_PARAMS > MAX_FLAT_RESULTS {
978 MAX_FLAT_PARAMS
979} else {
980 MAX_FLAT_RESULTS
981};
982
983const fn add_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
984 const MAX: u8 = MAX_FLAT_TYPES as u8;
985 let sum = match (a, b) {
986 (Some(a), Some(b)) => match a.checked_add(b) {
987 Some(c) => c,
988 None => return None,
989 },
990 _ => return None,
991 };
992 if sum > MAX {
993 None
994 } else {
995 Some(sum)
996 }
997}
998
999const fn max_flat(a: Option<u8>, b: Option<u8>) -> Option<u8> {
1000 match (a, b) {
1001 (Some(a), Some(b)) => {
1002 if a > b {
1003 Some(a)
1004 } else {
1005 Some(b)
1006 }
1007 }
1008 _ => None,
1009 }
1010}
1011
1012pub struct FlatTypes<'a> {
1014 pub memory32: &'a [FlatType],
1016 pub memory64: &'a [FlatType],
1018}
1019
1020#[allow(missing_docs)]
1021impl FlatTypes<'_> {
1022 pub fn len(&self) -> usize {
1026 assert_eq!(self.memory32.len(), self.memory64.len());
1027 self.memory32.len()
1028 }
1029}
1030
1031#[derive(PartialEq, Eq, Copy, Clone)]
1035#[allow(missing_docs)]
1036pub enum FlatType {
1037 I32,
1038 I64,
1039 F32,
1040 F64,
1041}