1use anyhow::{bail, Result};
2use std::fmt::{self, Display};
3use wasmtime_environ::{
4 EngineOrModuleTypeIndex, EntityType, Global, Memory, ModuleTypes, Table, TypeTrace,
5 WasmFuncType, WasmHeapType, WasmRefType, WasmValType,
6};
7use wasmtime_runtime::VMSharedTypeIndex;
8
9use crate::{type_registry::RegisteredType, Engine};
10
11pub(crate) mod matching;
12
13#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq)]
19pub enum Mutability {
20 Const,
22 Var,
24}
25
26#[derive(Clone, Hash)]
40pub enum ValType {
41 I32,
46 I64,
48 F32,
50 F64,
52 V128,
54 Ref(RefType),
56}
57
58impl fmt::Debug for ValType {
59 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60 fmt::Display::fmt(self, f)
61 }
62}
63
64impl Display for ValType {
65 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
66 match self {
67 ValType::I32 => write!(f, "i32"),
68 ValType::I64 => write!(f, "i64"),
69 ValType::F32 => write!(f, "f32"),
70 ValType::F64 => write!(f, "f64"),
71 ValType::V128 => write!(f, "v128"),
72 ValType::Ref(r) => Display::fmt(r, f),
73 }
74 }
75}
76
77impl From<RefType> for ValType {
78 #[inline]
79 fn from(r: RefType) -> Self {
80 ValType::Ref(r)
81 }
82}
83
84impl ValType {
85 pub const EXTERNREF: Self = ValType::Ref(RefType::EXTERNREF);
87
88 pub const FUNCREF: Self = ValType::Ref(RefType::FUNCREF);
90
91 pub const NULLFUNCREF: Self = ValType::Ref(RefType::NULLFUNCREF);
93
94 pub const ANYREF: Self = ValType::Ref(RefType::ANYREF);
96
97 pub const I31REF: Self = ValType::Ref(RefType::I31REF);
99
100 pub const NULLREF: Self = ValType::Ref(RefType::NULLREF);
102
103 #[inline]
106 pub fn is_num(&self) -> bool {
107 match self {
108 ValType::I32 | ValType::I64 | ValType::F32 | ValType::F64 => true,
109 _ => false,
110 }
111 }
112
113 #[inline]
115 pub fn is_i32(&self) -> bool {
116 matches!(self, ValType::I32)
117 }
118
119 #[inline]
121 pub fn is_i64(&self) -> bool {
122 matches!(self, ValType::I64)
123 }
124
125 #[inline]
127 pub fn is_f32(&self) -> bool {
128 matches!(self, ValType::F32)
129 }
130
131 #[inline]
133 pub fn is_f64(&self) -> bool {
134 matches!(self, ValType::F64)
135 }
136
137 #[inline]
139 pub fn is_v128(&self) -> bool {
140 matches!(self, ValType::V128)
141 }
142
143 #[inline]
145 pub fn is_ref(&self) -> bool {
146 matches!(self, ValType::Ref(_))
147 }
148
149 #[inline]
151 pub fn is_funcref(&self) -> bool {
152 matches!(
153 self,
154 ValType::Ref(RefType {
155 is_nullable: true,
156 heap_type: HeapType::Func
157 })
158 )
159 }
160
161 #[inline]
163 pub fn is_externref(&self) -> bool {
164 matches!(
165 self,
166 ValType::Ref(RefType {
167 is_nullable: true,
168 heap_type: HeapType::Extern
169 })
170 )
171 }
172
173 #[inline]
175 pub fn is_anyref(&self) -> bool {
176 matches!(
177 self,
178 ValType::Ref(RefType {
179 is_nullable: true,
180 heap_type: HeapType::Any
181 })
182 )
183 }
184
185 #[inline]
188 pub fn as_ref(&self) -> Option<&RefType> {
189 match self {
190 ValType::Ref(r) => Some(r),
191 _ => None,
192 }
193 }
194
195 #[inline]
198 pub fn unwrap_ref(&self) -> &RefType {
199 self.as_ref()
200 .expect("ValType::unwrap_ref on a non-reference type")
201 }
202
203 pub fn matches(&self, other: &ValType) -> bool {
212 match (self, other) {
213 (Self::I32, Self::I32) => true,
214 (Self::I64, Self::I64) => true,
215 (Self::F32, Self::F32) => true,
216 (Self::F64, Self::F64) => true,
217 (Self::V128, Self::V128) => true,
218 (Self::Ref(a), Self::Ref(b)) => a.matches(b),
219 (Self::I32, _)
220 | (Self::I64, _)
221 | (Self::F32, _)
222 | (Self::F64, _)
223 | (Self::V128, _)
224 | (Self::Ref(_), _) => false,
225 }
226 }
227
228 pub fn eq(a: &Self, b: &Self) -> bool {
237 a.matches(b) && b.matches(a)
238 }
239
240 pub(crate) fn ensure_matches(&self, engine: &Engine, other: &ValType) -> Result<()> {
241 if !self.comes_from_same_engine(engine) || !other.comes_from_same_engine(engine) {
242 bail!("type used with wrong engine");
243 }
244 if self.matches(other) {
245 Ok(())
246 } else {
247 bail!("type mismatch: expected {other}, found {self}")
248 }
249 }
250
251 pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
252 match self {
253 Self::I32 | Self::I64 | Self::F32 | Self::F64 | Self::V128 => true,
254 Self::Ref(r) => r.comes_from_same_engine(engine),
255 }
256 }
257
258 pub(crate) fn to_wasm_type(&self) -> WasmValType {
259 match self {
260 Self::I32 => WasmValType::I32,
261 Self::I64 => WasmValType::I64,
262 Self::F32 => WasmValType::F32,
263 Self::F64 => WasmValType::F64,
264 Self::V128 => WasmValType::V128,
265 Self::Ref(r) => WasmValType::Ref(r.to_wasm_type()),
266 }
267 }
268
269 #[inline]
270 pub(crate) fn from_wasm_type(engine: &Engine, ty: &WasmValType) -> Self {
271 match ty {
272 WasmValType::I32 => Self::I32,
273 WasmValType::I64 => Self::I64,
274 WasmValType::F32 => Self::F32,
275 WasmValType::F64 => Self::F64,
276 WasmValType::V128 => Self::V128,
277 WasmValType::Ref(r) => Self::Ref(RefType::from_wasm_type(engine, r)),
278 }
279 }
280}
281
282#[derive(Clone, Hash)]
294pub struct RefType {
295 is_nullable: bool,
296 heap_type: HeapType,
297}
298
299impl fmt::Debug for RefType {
300 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
301 Display::fmt(self, f)
302 }
303}
304
305impl fmt::Display for RefType {
306 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
307 write!(f, "(ref ")?;
308 if self.is_nullable() {
309 write!(f, "null ")?;
310 }
311 write!(f, "{})", self.heap_type())
312 }
313}
314
315impl RefType {
316 pub const EXTERNREF: Self = RefType {
318 is_nullable: true,
319 heap_type: HeapType::Extern,
320 };
321
322 pub const FUNCREF: Self = RefType {
324 is_nullable: true,
325 heap_type: HeapType::Func,
326 };
327
328 pub const NULLFUNCREF: Self = RefType {
330 is_nullable: true,
331 heap_type: HeapType::NoFunc,
332 };
333
334 pub const ANYREF: Self = RefType {
336 is_nullable: true,
337 heap_type: HeapType::Any,
338 };
339
340 pub const I31REF: Self = RefType {
342 is_nullable: true,
343 heap_type: HeapType::I31,
344 };
345
346 pub const NULLREF: Self = RefType {
348 is_nullable: true,
349 heap_type: HeapType::None,
350 };
351
352 pub fn new(is_nullable: bool, heap_type: HeapType) -> RefType {
354 RefType {
355 is_nullable,
356 heap_type,
357 }
358 }
359
360 pub fn is_nullable(&self) -> bool {
362 self.is_nullable
363 }
364
365 pub fn heap_type(&self) -> &HeapType {
367 &self.heap_type
368 }
369
370 pub fn matches(&self, other: &RefType) -> bool {
379 if self.is_nullable() && !other.is_nullable() {
380 return false;
381 }
382 self.heap_type().matches(other.heap_type())
383 }
384
385 pub fn eq(a: &RefType, b: &RefType) -> bool {
394 a.matches(b) && b.matches(a)
395 }
396
397 pub(crate) fn ensure_matches(&self, engine: &Engine, other: &RefType) -> Result<()> {
398 if !self.comes_from_same_engine(engine) || !other.comes_from_same_engine(engine) {
399 bail!("type used with wrong engine");
400 }
401 if self.matches(other) {
402 Ok(())
403 } else {
404 bail!("type mismatch: expected {other}, found {self}")
405 }
406 }
407
408 pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
409 self.heap_type().comes_from_same_engine(engine)
410 }
411
412 pub(crate) fn to_wasm_type(&self) -> WasmRefType {
413 WasmRefType {
414 nullable: self.is_nullable(),
415 heap_type: self.heap_type().to_wasm_type(),
416 }
417 }
418
419 pub(crate) fn from_wasm_type(engine: &Engine, ty: &WasmRefType) -> RefType {
420 RefType {
421 is_nullable: ty.nullable,
422 heap_type: HeapType::from_wasm_type(engine, &ty.heap_type),
423 }
424 }
425
426 pub(crate) fn is_gc_heap_type(&self) -> bool {
427 self.heap_type().is_gc_heap_type()
428 }
429}
430
431#[derive(Debug, Clone, Hash)]
442pub enum HeapType {
443 Extern,
445
446 Func,
451
452 Concrete(FuncType),
457
458 NoFunc,
463
464 Any,
470
471 I31,
473
474 None,
479}
480
481impl Display for HeapType {
482 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
483 match self {
484 HeapType::Extern => write!(f, "extern"),
485 HeapType::Func => write!(f, "func"),
486 HeapType::NoFunc => write!(f, "nofunc"),
487 HeapType::Any => write!(f, "any"),
488 HeapType::I31 => write!(f, "i31"),
489 HeapType::None => write!(f, "none"),
490 HeapType::Concrete(ty) => write!(f, "(concrete {:?})", ty.type_index()),
491 }
492 }
493}
494
495impl From<FuncType> for HeapType {
496 #[inline]
497 fn from(f: FuncType) -> Self {
498 HeapType::Concrete(f)
499 }
500}
501
502impl HeapType {
503 pub fn is_extern(&self) -> bool {
505 matches!(self, HeapType::Extern)
506 }
507
508 pub fn is_func(&self) -> bool {
510 matches!(self, HeapType::Func)
511 }
512
513 pub fn is_no_func(&self) -> bool {
515 matches!(self, HeapType::NoFunc)
516 }
517
518 pub fn is_any(&self) -> bool {
520 matches!(self, HeapType::Any)
521 }
522
523 pub fn is_i31(&self) -> bool {
525 matches!(self, HeapType::I31)
526 }
527
528 pub fn is_none(&self) -> bool {
530 matches!(self, HeapType::None)
531 }
532
533 pub fn is_abstract(&self) -> bool {
537 !self.is_concrete()
538 }
539
540 pub fn is_concrete(&self) -> bool {
544 matches!(self, HeapType::Concrete(_))
545 }
546
547 pub fn as_concrete(&self) -> Option<&FuncType> {
551 match self {
552 HeapType::Concrete(f) => Some(f),
553 _ => None,
554 }
555 }
556
557 pub fn unwrap_concrete(&self) -> &FuncType {
560 self.as_concrete()
561 .expect("HeapType::unwrap_concrete on non-concrete heap type")
562 }
563
564 pub fn top(&self, engine: &Engine) -> HeapType {
569 let _ = engine;
572
573 match self {
574 HeapType::Func | HeapType::Concrete(_) | HeapType::NoFunc => HeapType::Func,
575 HeapType::Extern => HeapType::Extern,
576 HeapType::Any | HeapType::I31 | HeapType::None => HeapType::Any,
577 }
578 }
579
580 pub fn matches(&self, other: &HeapType) -> bool {
589 match (self, other) {
590 (HeapType::Extern, HeapType::Extern) => true,
591 (HeapType::Extern, _) => false,
592
593 (HeapType::NoFunc, HeapType::NoFunc | HeapType::Concrete(_) | HeapType::Func) => true,
594 (HeapType::NoFunc, _) => false,
595
596 (HeapType::Concrete(_), HeapType::Func) => true,
597 (HeapType::Concrete(a), HeapType::Concrete(b)) => a.matches(b),
598 (HeapType::Concrete(_), _) => false,
599
600 (HeapType::Func, HeapType::Func) => true,
601 (HeapType::Func, _) => false,
602
603 (HeapType::None, HeapType::None | HeapType::I31 | HeapType::Any) => true,
604 (HeapType::None, _) => false,
605
606 (HeapType::I31, HeapType::I31 | HeapType::Any) => true,
607 (HeapType::I31, _) => false,
608
609 (HeapType::Any, HeapType::Any) => true,
610 (HeapType::Any, _) => false,
611 }
612 }
613
614 pub fn eq(a: &HeapType, b: &HeapType) -> bool {
624 a.matches(b) && b.matches(a)
625 }
626
627 pub(crate) fn ensure_matches(&self, engine: &Engine, other: &HeapType) -> Result<()> {
628 if !self.comes_from_same_engine(engine) || !other.comes_from_same_engine(engine) {
629 bail!("type used with wrong engine");
630 }
631 if self.matches(other) {
632 Ok(())
633 } else {
634 bail!("type mismatch: expected {other}, found {self}");
635 }
636 }
637
638 pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
639 match self {
640 HeapType::Extern
641 | HeapType::Func
642 | HeapType::NoFunc
643 | HeapType::Any
644 | HeapType::I31
645 | HeapType::None => true,
646 HeapType::Concrete(ty) => ty.comes_from_same_engine(engine),
647 }
648 }
649
650 pub(crate) fn to_wasm_type(&self) -> WasmHeapType {
651 match self {
652 HeapType::Extern => WasmHeapType::Extern,
653 HeapType::Func => WasmHeapType::Func,
654 HeapType::NoFunc => WasmHeapType::NoFunc,
655 HeapType::Any => WasmHeapType::Any,
656 HeapType::I31 => WasmHeapType::I31,
657 HeapType::None => WasmHeapType::None,
658 HeapType::Concrete(f) => {
659 WasmHeapType::Concrete(EngineOrModuleTypeIndex::Engine(f.type_index().bits()))
660 }
661 }
662 }
663
664 pub(crate) fn from_wasm_type(engine: &Engine, ty: &WasmHeapType) -> HeapType {
665 match ty {
666 WasmHeapType::Extern => HeapType::Extern,
667 WasmHeapType::Func => HeapType::Func,
668 WasmHeapType::NoFunc => HeapType::NoFunc,
669 WasmHeapType::Any => HeapType::Any,
670 WasmHeapType::I31 => HeapType::I31,
671 WasmHeapType::None => HeapType::None,
672 WasmHeapType::Concrete(EngineOrModuleTypeIndex::Engine(idx)) => {
673 let idx = VMSharedTypeIndex::new(*idx);
674 HeapType::Concrete(FuncType::from_shared_type_index(engine, idx))
675 }
676 WasmHeapType::Concrete(EngineOrModuleTypeIndex::Module(_)) => {
677 panic!("HeapType::from_wasm_type on non-canonical heap type")
678 }
679 }
680 }
681
682 pub(crate) fn is_gc_heap_type(&self) -> bool {
683 match self {
686 HeapType::Extern | HeapType::Any => true,
688
689 Self::Concrete(_) => false,
693
694 HeapType::I31 => false,
698
699 HeapType::None => false,
703
704 HeapType::Func | HeapType::NoFunc => false,
706 }
707 }
708}
709
710#[derive(Debug, Clone)]
718pub enum ExternType {
719 Func(FuncType),
721 Global(GlobalType),
723 Table(TableType),
725 Memory(MemoryType),
727}
728
729macro_rules! extern_type_accessors {
730 ($(($variant:ident($ty:ty) $get:ident $unwrap:ident))*) => ($(
731 pub fn $get(&self) -> Option<&$ty> {
734 if let ExternType::$variant(e) = self {
735 Some(e)
736 } else {
737 None
738 }
739 }
740
741 pub fn $unwrap(&self) -> &$ty {
748 self.$get().expect(concat!("expected ", stringify!($ty)))
749 }
750 )*)
751}
752
753impl ExternType {
754 extern_type_accessors! {
755 (Func(FuncType) func unwrap_func)
756 (Global(GlobalType) global unwrap_global)
757 (Table(TableType) table unwrap_table)
758 (Memory(MemoryType) memory unwrap_memory)
759 }
760
761 pub(crate) fn from_wasmtime(
762 engine: &Engine,
763 types: &ModuleTypes,
764 ty: &EntityType,
765 ) -> ExternType {
766 match ty {
767 EntityType::Function(idx) => match idx {
768 EngineOrModuleTypeIndex::Engine(e) => {
769 FuncType::from_shared_type_index(engine, VMSharedTypeIndex::new(*e)).into()
770 }
771 EngineOrModuleTypeIndex::Module(m) => {
772 FuncType::from_wasm_func_type(engine, types[*m].clone()).into()
773 }
774 },
775 EntityType::Global(ty) => GlobalType::from_wasmtime_global(engine, ty).into(),
776 EntityType::Memory(ty) => MemoryType::from_wasmtime_memory(ty).into(),
777 EntityType::Table(ty) => TableType::from_wasmtime_table(engine, ty).into(),
778 EntityType::Tag(_) => unimplemented!("wasm tag support"),
779 }
780 }
781}
782
783impl From<FuncType> for ExternType {
784 fn from(ty: FuncType) -> ExternType {
785 ExternType::Func(ty)
786 }
787}
788
789impl From<GlobalType> for ExternType {
790 fn from(ty: GlobalType) -> ExternType {
791 ExternType::Global(ty)
792 }
793}
794
795impl From<MemoryType> for ExternType {
796 fn from(ty: MemoryType) -> ExternType {
797 ExternType::Memory(ty)
798 }
799}
800
801impl From<TableType> for ExternType {
802 fn from(ty: TableType) -> ExternType {
803 ExternType::Table(ty)
804 }
805}
806
807#[derive(Debug, Clone, Hash)]
821pub struct FuncType {
822 registered_type: RegisteredType,
823}
824
825impl Display for FuncType {
826 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
827 write!(f, "(type (func")?;
828 if self.params().len() > 0 {
829 write!(f, " (param")?;
830 for p in self.params() {
831 write!(f, " {p}")?;
832 }
833 write!(f, ")")?;
834 }
835 if self.results().len() > 0 {
836 write!(f, " (result")?;
837 for r in self.results() {
838 write!(f, " {r}")?;
839 }
840 write!(f, ")")?;
841 }
842 write!(f, "))")
843 }
844}
845
846impl FuncType {
847 pub fn new(
852 engine: &Engine,
853 params: impl IntoIterator<Item = ValType>,
854 results: impl IntoIterator<Item = ValType>,
855 ) -> FuncType {
856 let mut registrations = vec![];
862
863 let mut to_wasm_type = |ty: ValType| {
864 if let Some(r) = ty.as_ref() {
865 if let Some(c) = r.heap_type().as_concrete() {
866 registrations.push(c.registered_type.clone());
867 }
868 }
869 ty.to_wasm_type()
870 };
871
872 Self::from_wasm_func_type(
873 engine,
874 WasmFuncType::new(
875 params.into_iter().map(&mut to_wasm_type).collect(),
876 results.into_iter().map(&mut to_wasm_type).collect(),
877 ),
878 )
879 }
880
881 pub fn engine(&self) -> &Engine {
883 self.registered_type.engine()
884 }
885
886 pub fn param(&self, i: usize) -> Option<ValType> {
890 let engine = self.engine();
891 self.registered_type
892 .params()
893 .get(i)
894 .map(|ty| ValType::from_wasm_type(engine, ty))
895 }
896
897 #[inline]
899 pub fn params(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
900 let engine = self.engine();
901 self.registered_type
902 .params()
903 .iter()
904 .map(|ty| ValType::from_wasm_type(engine, ty))
905 }
906
907 pub fn result(&self, i: usize) -> Option<ValType> {
911 let engine = self.engine();
912 self.registered_type
913 .returns()
914 .get(i)
915 .map(|ty| ValType::from_wasm_type(engine, ty))
916 }
917
918 #[inline]
920 pub fn results(&self) -> impl ExactSizeIterator<Item = ValType> + '_ {
921 let engine = self.engine();
922 self.registered_type
923 .returns()
924 .iter()
925 .map(|ty| ValType::from_wasm_type(engine, ty))
926 }
927
928 pub fn matches(&self, other: &FuncType) -> bool {
937 assert!(self.comes_from_same_engine(other.engine()));
938
939 if self.type_index() == other.type_index() {
942 return true;
943 }
944
945 self.params().len() == other.params().len()
946 && self.results().len() == other.results().len()
947 && self
951 .params()
952 .zip(other.params())
953 .all(|(a, b)| b.matches(&a))
954 && self
955 .results()
956 .zip(other.results())
957 .all(|(a, b)| a.matches(&b))
958 }
959
960 pub fn eq(a: &FuncType, b: &FuncType) -> bool {
970 assert!(a.comes_from_same_engine(b.engine()));
971 a.type_index() == b.type_index()
972 }
973
974 pub(crate) fn comes_from_same_engine(&self, engine: &Engine) -> bool {
975 Engine::same(self.registered_type.engine(), engine)
976 }
977
978 pub(crate) fn type_index(&self) -> VMSharedTypeIndex {
979 self.registered_type.index()
980 }
981
982 pub(crate) fn as_wasm_func_type(&self) -> &WasmFuncType {
983 &self.registered_type
984 }
985
986 pub(crate) fn into_registered_type(self) -> RegisteredType {
987 self.registered_type
988 }
989
990 pub(crate) fn from_wasm_func_type(engine: &Engine, ty: WasmFuncType) -> FuncType {
1001 let ty = RegisteredType::new(engine, ty);
1002 Self {
1003 registered_type: ty,
1004 }
1005 }
1006
1007 pub(crate) fn from_shared_type_index(engine: &Engine, index: VMSharedTypeIndex) -> FuncType {
1008 let ty = RegisteredType::root(engine, index).expect(
1009 "VMSharedTypeIndex is not registered in the Engine! Wrong \
1010 engine? Didn't root the index somewhere?",
1011 );
1012 Self {
1013 registered_type: ty,
1014 }
1015 }
1016}
1017
1018#[derive(Debug, Clone, Hash)]
1026pub struct GlobalType {
1027 content: ValType,
1028 mutability: Mutability,
1029}
1030
1031impl GlobalType {
1032 pub fn new(content: ValType, mutability: Mutability) -> GlobalType {
1035 GlobalType {
1036 content,
1037 mutability,
1038 }
1039 }
1040
1041 pub fn content(&self) -> &ValType {
1043 &self.content
1044 }
1045
1046 pub fn mutability(&self) -> Mutability {
1048 self.mutability
1049 }
1050
1051 pub(crate) fn to_wasm_type(&self) -> Global {
1052 let wasm_ty = self.content().to_wasm_type();
1053 let mutability = matches!(self.mutability(), Mutability::Var);
1054 Global {
1055 wasm_ty,
1056 mutability,
1057 }
1058 }
1059
1060 pub(crate) fn from_wasmtime_global(engine: &Engine, global: &Global) -> GlobalType {
1063 let ty = ValType::from_wasm_type(engine, &global.wasm_ty);
1064 let mutability = if global.mutability {
1065 Mutability::Var
1066 } else {
1067 Mutability::Const
1068 };
1069 GlobalType::new(ty, mutability)
1070 }
1071}
1072
1073#[derive(Debug, Clone, Hash)]
1081pub struct TableType {
1082 element: RefType,
1085 ty: Table,
1086}
1087
1088impl TableType {
1089 pub fn new(element: RefType, min: u32, max: Option<u32>) -> TableType {
1092 let wasm_ty = element.to_wasm_type();
1093
1094 if cfg!(debug_assertions) {
1095 wasm_ty
1096 .trace(&mut |idx| match idx {
1097 EngineOrModuleTypeIndex::Engine(_) => Ok(()),
1098 EngineOrModuleTypeIndex::Module(module_idx) => Err(format!(
1099 "found module-level canonicalized type index: {module_idx:?}"
1100 )),
1101 })
1102 .expect("element type should be engine-level canonicalized");
1103 }
1104
1105 TableType {
1106 element,
1107 ty: Table {
1108 wasm_ty,
1109 minimum: min,
1110 maximum: max,
1111 },
1112 }
1113 }
1114
1115 pub fn element(&self) -> &RefType {
1117 &self.element
1118 }
1119
1120 pub fn minimum(&self) -> u32 {
1122 self.ty.minimum
1123 }
1124
1125 pub fn maximum(&self) -> Option<u32> {
1130 self.ty.maximum
1131 }
1132
1133 pub(crate) fn from_wasmtime_table(engine: &Engine, table: &Table) -> TableType {
1134 let element = RefType::from_wasm_type(engine, &table.wasm_ty);
1135 TableType {
1136 element,
1137 ty: table.clone(),
1138 }
1139 }
1140
1141 pub(crate) fn wasmtime_table(&self) -> &Table {
1142 &self.ty
1143 }
1144}
1145
1146#[derive(Debug, Clone, Hash, Eq, PartialEq)]
1153pub struct MemoryType {
1154 ty: Memory,
1155}
1156
1157impl MemoryType {
1158 pub fn new(minimum: u32, maximum: Option<u32>) -> MemoryType {
1164 MemoryType {
1165 ty: Memory {
1166 memory64: false,
1167 shared: false,
1168 minimum: minimum.into(),
1169 maximum: maximum.map(|i| i.into()),
1170 },
1171 }
1172 }
1173
1174 pub fn new64(minimum: u64, maximum: Option<u64>) -> MemoryType {
1183 MemoryType {
1184 ty: Memory {
1185 memory64: true,
1186 shared: false,
1187 minimum,
1188 maximum,
1189 },
1190 }
1191 }
1192
1193 pub fn shared(minimum: u32, maximum: u32) -> MemoryType {
1202 MemoryType {
1203 ty: Memory {
1204 memory64: false,
1205 shared: true,
1206 minimum: minimum.into(),
1207 maximum: Some(maximum.into()),
1208 },
1209 }
1210 }
1211
1212 pub fn is_64(&self) -> bool {
1217 self.ty.memory64
1218 }
1219
1220 pub fn is_shared(&self) -> bool {
1225 self.ty.shared
1226 }
1227
1228 pub fn minimum(&self) -> u64 {
1233 self.ty.minimum
1234 }
1235
1236 pub fn maximum(&self) -> Option<u64> {
1244 self.ty.maximum
1245 }
1246
1247 pub(crate) fn from_wasmtime_memory(memory: &Memory) -> MemoryType {
1248 MemoryType { ty: memory.clone() }
1249 }
1250
1251 pub(crate) fn wasmtime_memory(&self) -> &Memory {
1252 &self.ty
1253 }
1254}
1255
1256#[derive(Clone)]
1265pub struct ImportType<'module> {
1266 module: &'module str,
1268
1269 name: &'module str,
1271
1272 ty: EntityType,
1274 types: &'module ModuleTypes,
1275 engine: &'module Engine,
1276}
1277
1278impl<'module> ImportType<'module> {
1279 pub(crate) fn new(
1282 module: &'module str,
1283 name: &'module str,
1284 ty: EntityType,
1285 types: &'module ModuleTypes,
1286 engine: &'module Engine,
1287 ) -> ImportType<'module> {
1288 ImportType {
1289 module,
1290 name,
1291 ty,
1292 types,
1293 engine,
1294 }
1295 }
1296
1297 pub fn module(&self) -> &'module str {
1299 self.module
1300 }
1301
1302 pub fn name(&self) -> &'module str {
1305 self.name
1306 }
1307
1308 pub fn ty(&self) -> ExternType {
1310 ExternType::from_wasmtime(self.engine, self.types, &self.ty)
1311 }
1312}
1313
1314impl<'module> fmt::Debug for ImportType<'module> {
1315 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1316 f.debug_struct("ImportType")
1317 .field("module", &self.module())
1318 .field("name", &self.name())
1319 .field("ty", &self.ty())
1320 .finish()
1321 }
1322}
1323
1324#[derive(Clone)]
1333pub struct ExportType<'module> {
1334 name: &'module str,
1336
1337 ty: EntityType,
1339 types: &'module ModuleTypes,
1340 engine: &'module Engine,
1341}
1342
1343impl<'module> ExportType<'module> {
1344 pub(crate) fn new(
1347 name: &'module str,
1348 ty: EntityType,
1349 types: &'module ModuleTypes,
1350 engine: &'module Engine,
1351 ) -> ExportType<'module> {
1352 ExportType {
1353 name,
1354 ty,
1355 types,
1356 engine,
1357 }
1358 }
1359
1360 pub fn name(&self) -> &'module str {
1362 self.name
1363 }
1364
1365 pub fn ty(&self) -> ExternType {
1367 ExternType::from_wasmtime(self.engine, self.types, &self.ty)
1368 }
1369}
1370
1371impl<'module> fmt::Debug for ExportType<'module> {
1372 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1373 f.debug_struct("ExportType")
1374 .field("name", &self.name().to_owned())
1375 .field("ty", &self.ty())
1376 .finish()
1377 }
1378}