1use crate::component::matching::InstanceType;
4use crate::{Engine, ExternType, FuncType};
5use alloc::sync::Arc;
6use core::fmt;
7use core::ops::Deref;
8use wasmtime_environ::PrimaryMap;
9use wasmtime_environ::component::{
10 ComponentTypes, Export, InterfaceType, ResourceIndex, TypeComponentIndex,
11 TypeComponentInstanceIndex, TypeDef, TypeEnumIndex, TypeFlagsIndex, TypeFuncIndex,
12 TypeFutureIndex, TypeFutureTableIndex, TypeListIndex, TypeModuleIndex, TypeOptionIndex,
13 TypeRecordIndex, TypeResourceTable, TypeResourceTableIndex, TypeResultIndex, TypeStreamIndex,
14 TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex,
15};
16
17pub use crate::component::resources::ResourceType;
18
19#[derive(Clone)]
38struct Handle<T> {
39 index: T,
40 types: Arc<ComponentTypes>,
41 resources: Arc<PrimaryMap<ResourceIndex, ResourceType>>,
42}
43
44impl<T> Handle<T> {
45 fn new(index: T, ty: &InstanceType<'_>) -> Handle<T> {
46 Handle {
47 index,
48 types: ty.types.clone(),
49 resources: ty.resources.clone(),
50 }
51 }
52
53 fn instance(&self) -> InstanceType<'_> {
54 InstanceType {
55 types: &self.types,
56 resources: &self.resources,
57 }
58 }
59
60 fn equivalent<'a>(
61 &'a self,
62 other: &'a Self,
63 type_check: fn(&TypeChecker<'a>, T, T) -> bool,
64 ) -> bool
65 where
66 T: PartialEq + Copy,
67 {
68 (self.index == other.index
69 && Arc::ptr_eq(&self.types, &other.types)
70 && Arc::ptr_eq(&self.resources, &other.resources))
71 || type_check(
72 &TypeChecker {
73 a_types: &self.types,
74 b_types: &other.types,
75 a_resource: &self.resources,
76 b_resource: &other.resources,
77 },
78 self.index,
79 other.index,
80 )
81 }
82}
83
84impl<T: fmt::Debug> fmt::Debug for Handle<T> {
85 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86 f.debug_struct("Handle")
87 .field("index", &self.index)
88 .finish()
89 }
90}
91
92struct TypeChecker<'a> {
94 a_types: &'a ComponentTypes,
95 a_resource: &'a PrimaryMap<ResourceIndex, ResourceType>,
96 b_types: &'a ComponentTypes,
97 b_resource: &'a PrimaryMap<ResourceIndex, ResourceType>,
98}
99
100impl TypeChecker<'_> {
101 fn interface_types_equal(&self, a: InterfaceType, b: InterfaceType) -> bool {
102 match (a, b) {
103 (InterfaceType::Own(o1), InterfaceType::Own(o2)) => self.resources_equal(o1, o2),
104 (InterfaceType::Own(_), _) => false,
105 (InterfaceType::Borrow(b1), InterfaceType::Borrow(b2)) => self.resources_equal(b1, b2),
106 (InterfaceType::Borrow(_), _) => false,
107 (InterfaceType::List(l1), InterfaceType::List(l2)) => self.lists_equal(l1, l2),
108 (InterfaceType::List(_), _) => false,
109 (InterfaceType::Record(r1), InterfaceType::Record(r2)) => self.records_equal(r1, r2),
110 (InterfaceType::Record(_), _) => false,
111 (InterfaceType::Variant(v1), InterfaceType::Variant(v2)) => self.variants_equal(v1, v2),
112 (InterfaceType::Variant(_), _) => false,
113 (InterfaceType::Result(r1), InterfaceType::Result(r2)) => self.results_equal(r1, r2),
114 (InterfaceType::Result(_), _) => false,
115 (InterfaceType::Option(o1), InterfaceType::Option(o2)) => self.options_equal(o1, o2),
116 (InterfaceType::Option(_), _) => false,
117 (InterfaceType::Enum(e1), InterfaceType::Enum(e2)) => self.enums_equal(e1, e2),
118 (InterfaceType::Enum(_), _) => false,
119 (InterfaceType::Tuple(t1), InterfaceType::Tuple(t2)) => self.tuples_equal(t1, t2),
120 (InterfaceType::Tuple(_), _) => false,
121 (InterfaceType::Flags(f1), InterfaceType::Flags(f2)) => self.flags_equal(f1, f2),
122 (InterfaceType::Flags(_), _) => false,
123 (InterfaceType::Bool, InterfaceType::Bool) => true,
124 (InterfaceType::Bool, _) => false,
125 (InterfaceType::U8, InterfaceType::U8) => true,
126 (InterfaceType::U8, _) => false,
127 (InterfaceType::U16, InterfaceType::U16) => true,
128 (InterfaceType::U16, _) => false,
129 (InterfaceType::U32, InterfaceType::U32) => true,
130 (InterfaceType::U32, _) => false,
131 (InterfaceType::U64, InterfaceType::U64) => true,
132 (InterfaceType::U64, _) => false,
133 (InterfaceType::S8, InterfaceType::S8) => true,
134 (InterfaceType::S8, _) => false,
135 (InterfaceType::S16, InterfaceType::S16) => true,
136 (InterfaceType::S16, _) => false,
137 (InterfaceType::S32, InterfaceType::S32) => true,
138 (InterfaceType::S32, _) => false,
139 (InterfaceType::S64, InterfaceType::S64) => true,
140 (InterfaceType::S64, _) => false,
141 (InterfaceType::Float32, InterfaceType::Float32) => true,
142 (InterfaceType::Float32, _) => false,
143 (InterfaceType::Float64, InterfaceType::Float64) => true,
144 (InterfaceType::Float64, _) => false,
145 (InterfaceType::String, InterfaceType::String) => true,
146 (InterfaceType::String, _) => false,
147 (InterfaceType::Char, InterfaceType::Char) => true,
148 (InterfaceType::Char, _) => false,
149 (InterfaceType::Future(t1), InterfaceType::Future(t2)) => {
150 self.future_table_types_equal(t1, t2)
151 }
152 (InterfaceType::Future(_), _) => false,
153 (InterfaceType::Stream(t1), InterfaceType::Stream(t2)) => {
154 self.stream_table_types_equal(t1, t2)
155 }
156 (InterfaceType::Stream(_), _) => false,
157 (InterfaceType::ErrorContext(_), InterfaceType::ErrorContext(_)) => true,
158 (InterfaceType::ErrorContext(_), _) => false,
159 }
160 }
161
162 fn lists_equal(&self, l1: TypeListIndex, l2: TypeListIndex) -> bool {
163 let a = &self.a_types[l1];
164 let b = &self.b_types[l2];
165 self.interface_types_equal(a.element, b.element)
166 }
167
168 fn resources_equal(&self, o1: TypeResourceTableIndex, o2: TypeResourceTableIndex) -> bool {
169 match (&self.a_types[o1], &self.b_types[o2]) {
170 (
174 TypeResourceTable::Concrete { ty: a, .. },
175 TypeResourceTable::Concrete { ty: b, .. },
176 ) => self.a_resource[*a] == self.b_resource[*b],
177 (TypeResourceTable::Concrete { .. }, _) => false,
178
179 (TypeResourceTable::Abstract(a), TypeResourceTable::Abstract(b)) => {
182 core::ptr::eq(self.a_types, self.b_types) && a == b
183 }
184 (TypeResourceTable::Abstract(_), _) => false,
185 }
186 }
187
188 fn records_equal(&self, r1: TypeRecordIndex, r2: TypeRecordIndex) -> bool {
189 let a = &self.a_types[r1];
190 let b = &self.b_types[r2];
191 if a.fields.len() != b.fields.len() {
192 return false;
193 }
194 a.fields
195 .iter()
196 .zip(b.fields.iter())
197 .all(|(a_field, b_field)| {
198 a_field.name == b_field.name && self.interface_types_equal(a_field.ty, b_field.ty)
199 })
200 }
201
202 fn variants_equal(&self, v1: TypeVariantIndex, v2: TypeVariantIndex) -> bool {
203 let a = &self.a_types[v1];
204 let b = &self.b_types[v2];
205 if a.cases.len() != b.cases.len() {
206 return false;
207 }
208 a.cases
209 .iter()
210 .zip(b.cases.iter())
211 .all(|((a_name, a_ty), (b_name, b_ty))| {
212 if a_name != b_name {
213 return false;
214 }
215 match (a_ty, b_ty) {
216 (Some(a_case_ty), Some(b_case_ty)) => {
217 self.interface_types_equal(*a_case_ty, *b_case_ty)
218 }
219 (None, None) => true,
220 _ => false,
221 }
222 })
223 }
224
225 fn results_equal(&self, r1: TypeResultIndex, r2: TypeResultIndex) -> bool {
226 let a = &self.a_types[r1];
227 let b = &self.b_types[r2];
228 let oks = match (a.ok, b.ok) {
229 (Some(ok1), Some(ok2)) => self.interface_types_equal(ok1, ok2),
230 (None, None) => true,
231 _ => false,
232 };
233 if !oks {
234 return false;
235 }
236 match (a.err, b.err) {
237 (Some(err1), Some(err2)) => self.interface_types_equal(err1, err2),
238 (None, None) => true,
239 _ => false,
240 }
241 }
242
243 fn options_equal(&self, o1: TypeOptionIndex, o2: TypeOptionIndex) -> bool {
244 let a = &self.a_types[o1];
245 let b = &self.b_types[o2];
246 self.interface_types_equal(a.ty, b.ty)
247 }
248
249 fn enums_equal(&self, e1: TypeEnumIndex, e2: TypeEnumIndex) -> bool {
250 let a = &self.a_types[e1];
251 let b = &self.b_types[e2];
252 a.names == b.names
253 }
254
255 fn tuples_equal(&self, t1: TypeTupleIndex, t2: TypeTupleIndex) -> bool {
256 let a = &self.a_types[t1];
257 let b = &self.b_types[t2];
258 if a.types.len() != b.types.len() {
259 return false;
260 }
261 a.types
262 .iter()
263 .zip(b.types.iter())
264 .all(|(&a, &b)| self.interface_types_equal(a, b))
265 }
266
267 fn flags_equal(&self, f1: TypeFlagsIndex, f2: TypeFlagsIndex) -> bool {
268 let a = &self.a_types[f1];
269 let b = &self.b_types[f2];
270 a.names == b.names
271 }
272
273 fn future_table_types_equal(&self, t1: TypeFutureTableIndex, t2: TypeFutureTableIndex) -> bool {
274 self.futures_equal(self.a_types[t1].ty, self.b_types[t2].ty)
275 }
276
277 fn futures_equal(&self, t1: TypeFutureIndex, t2: TypeFutureIndex) -> bool {
278 let a = &self.a_types[t1];
279 let b = &self.b_types[t2];
280 match (a.payload, b.payload) {
281 (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
282 (None, None) => true,
283 _ => false,
284 }
285 }
286
287 fn stream_table_types_equal(&self, t1: TypeStreamTableIndex, t2: TypeStreamTableIndex) -> bool {
288 self.streams_equal(self.a_types[t1].ty, self.b_types[t2].ty)
289 }
290
291 fn streams_equal(&self, t1: TypeStreamIndex, t2: TypeStreamIndex) -> bool {
292 let a = &self.a_types[t1];
293 let b = &self.b_types[t2];
294 match (a.payload, b.payload) {
295 (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
296 (None, None) => true,
297 _ => false,
298 }
299 }
300}
301
302#[derive(Clone, Debug)]
304pub struct List(Handle<TypeListIndex>);
305
306impl PartialEq for List {
307 fn eq(&self, other: &Self) -> bool {
308 self.0.equivalent(&other.0, TypeChecker::lists_equal)
309 }
310}
311
312impl Eq for List {}
313
314impl List {
315 pub(crate) fn from(index: TypeListIndex, ty: &InstanceType<'_>) -> Self {
316 List(Handle::new(index, ty))
317 }
318
319 pub fn ty(&self) -> Type {
321 Type::from(&self.0.types[self.0.index].element, &self.0.instance())
322 }
323}
324
325#[derive(Debug)]
327pub struct Field<'a> {
328 pub name: &'a str,
330 pub ty: Type,
332}
333
334#[derive(Clone, Debug)]
336pub struct Record(Handle<TypeRecordIndex>);
337
338impl Record {
339 pub(crate) fn from(index: TypeRecordIndex, ty: &InstanceType<'_>) -> Self {
340 Record(Handle::new(index, ty))
341 }
342
343 pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> {
345 self.0.types[self.0.index].fields.iter().map(|field| Field {
346 name: &field.name,
347 ty: Type::from(&field.ty, &self.0.instance()),
348 })
349 }
350}
351
352impl PartialEq for Record {
353 fn eq(&self, other: &Self) -> bool {
354 self.0.equivalent(&other.0, TypeChecker::records_equal)
355 }
356}
357
358impl Eq for Record {}
359
360#[derive(Clone, Debug)]
362pub struct Tuple(Handle<TypeTupleIndex>);
363
364impl Tuple {
365 pub(crate) fn from(index: TypeTupleIndex, ty: &InstanceType<'_>) -> Self {
366 Tuple(Handle::new(index, ty))
367 }
368
369 pub fn types(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
371 self.0.types[self.0.index]
372 .types
373 .iter()
374 .map(|ty| Type::from(ty, &self.0.instance()))
375 }
376}
377
378impl PartialEq for Tuple {
379 fn eq(&self, other: &Self) -> bool {
380 self.0.equivalent(&other.0, TypeChecker::tuples_equal)
381 }
382}
383
384impl Eq for Tuple {}
385
386pub struct Case<'a> {
388 pub name: &'a str,
390 pub ty: Option<Type>,
392}
393
394#[derive(Clone, Debug)]
396pub struct Variant(Handle<TypeVariantIndex>);
397
398impl Variant {
399 pub(crate) fn from(index: TypeVariantIndex, ty: &InstanceType<'_>) -> Self {
400 Variant(Handle::new(index, ty))
401 }
402
403 pub fn cases(&self) -> impl ExactSizeIterator<Item = Case<'_>> {
405 self.0.types[self.0.index]
406 .cases
407 .iter()
408 .map(|(name, ty)| Case {
409 name,
410 ty: ty.as_ref().map(|ty| Type::from(ty, &self.0.instance())),
411 })
412 }
413}
414
415impl PartialEq for Variant {
416 fn eq(&self, other: &Self) -> bool {
417 self.0.equivalent(&other.0, TypeChecker::variants_equal)
418 }
419}
420
421impl Eq for Variant {}
422
423#[derive(Clone, Debug)]
425pub struct Enum(Handle<TypeEnumIndex>);
426
427impl Enum {
428 pub(crate) fn from(index: TypeEnumIndex, ty: &InstanceType<'_>) -> Self {
429 Enum(Handle::new(index, ty))
430 }
431
432 pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
434 self.0.types[self.0.index]
435 .names
436 .iter()
437 .map(|name| name.deref())
438 }
439}
440
441impl PartialEq for Enum {
442 fn eq(&self, other: &Self) -> bool {
443 self.0.equivalent(&other.0, TypeChecker::enums_equal)
444 }
445}
446
447impl Eq for Enum {}
448
449#[derive(Clone, Debug)]
451pub struct OptionType(Handle<TypeOptionIndex>);
452
453impl OptionType {
454 pub(crate) fn from(index: TypeOptionIndex, ty: &InstanceType<'_>) -> Self {
455 OptionType(Handle::new(index, ty))
456 }
457
458 pub fn ty(&self) -> Type {
460 Type::from(&self.0.types[self.0.index].ty, &self.0.instance())
461 }
462}
463
464impl PartialEq for OptionType {
465 fn eq(&self, other: &Self) -> bool {
466 self.0.equivalent(&other.0, TypeChecker::options_equal)
467 }
468}
469
470impl Eq for OptionType {}
471
472#[derive(Clone, Debug)]
474pub struct ResultType(Handle<TypeResultIndex>);
475
476impl ResultType {
477 pub(crate) fn from(index: TypeResultIndex, ty: &InstanceType<'_>) -> Self {
478 ResultType(Handle::new(index, ty))
479 }
480
481 pub fn ok(&self) -> Option<Type> {
483 Some(Type::from(
484 self.0.types[self.0.index].ok.as_ref()?,
485 &self.0.instance(),
486 ))
487 }
488
489 pub fn err(&self) -> Option<Type> {
491 Some(Type::from(
492 self.0.types[self.0.index].err.as_ref()?,
493 &self.0.instance(),
494 ))
495 }
496}
497
498impl PartialEq for ResultType {
499 fn eq(&self, other: &Self) -> bool {
500 self.0.equivalent(&other.0, TypeChecker::results_equal)
501 }
502}
503
504impl Eq for ResultType {}
505
506#[derive(Clone, Debug)]
508pub struct Flags(Handle<TypeFlagsIndex>);
509
510impl Flags {
511 pub(crate) fn from(index: TypeFlagsIndex, ty: &InstanceType<'_>) -> Self {
512 Flags(Handle::new(index, ty))
513 }
514
515 pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
517 self.0.types[self.0.index]
518 .names
519 .iter()
520 .map(|name| name.deref())
521 }
522}
523
524impl PartialEq for Flags {
525 fn eq(&self, other: &Self) -> bool {
526 self.0.equivalent(&other.0, TypeChecker::flags_equal)
527 }
528}
529
530impl Eq for Flags {}
531
532#[derive(Clone, Debug)]
534pub struct FutureType(Handle<TypeFutureIndex>);
535
536impl FutureType {
537 pub(crate) fn from(index: TypeFutureIndex, ty: &InstanceType<'_>) -> Self {
538 FutureType(Handle::new(index, ty))
539 }
540
541 pub fn ty(&self) -> Option<Type> {
543 Some(Type::from(
544 self.0.types[self.0.index].payload.as_ref()?,
545 &self.0.instance(),
546 ))
547 }
548}
549
550impl PartialEq for FutureType {
551 fn eq(&self, other: &Self) -> bool {
552 self.0.equivalent(&other.0, TypeChecker::futures_equal)
553 }
554}
555
556impl Eq for FutureType {}
557
558#[derive(Clone, Debug)]
560pub struct StreamType(Handle<TypeStreamIndex>);
561
562impl StreamType {
563 pub(crate) fn from(index: TypeStreamIndex, ty: &InstanceType<'_>) -> Self {
564 StreamType(Handle::new(index, ty))
565 }
566
567 pub fn ty(&self) -> Option<Type> {
569 Some(Type::from(
570 self.0.types[self.0.index].payload.as_ref()?,
571 &self.0.instance(),
572 ))
573 }
574}
575
576impl PartialEq for StreamType {
577 fn eq(&self, other: &Self) -> bool {
578 self.0.equivalent(&other.0, TypeChecker::streams_equal)
579 }
580}
581
582impl Eq for StreamType {}
583
584#[derive(Clone, PartialEq, Eq, Debug)]
586#[expect(missing_docs, reason = "self-describing variants")]
587pub enum Type {
588 Bool,
589 S8,
590 U8,
591 S16,
592 U16,
593 S32,
594 U32,
595 S64,
596 U64,
597 Float32,
598 Float64,
599 Char,
600 String,
601 List(List),
602 Record(Record),
603 Tuple(Tuple),
604 Variant(Variant),
605 Enum(Enum),
606 Option(OptionType),
607 Result(ResultType),
608 Flags(Flags),
609 Own(ResourceType),
610 Borrow(ResourceType),
611 Future(FutureType),
612 Stream(StreamType),
613 ErrorContext,
614}
615
616impl Type {
617 pub fn unwrap_list(&self) -> &List {
623 if let Type::List(handle) = self {
624 &handle
625 } else {
626 panic!("attempted to unwrap a {} as a list", self.desc())
627 }
628 }
629
630 pub fn unwrap_record(&self) -> &Record {
636 if let Type::Record(handle) = self {
637 &handle
638 } else {
639 panic!("attempted to unwrap a {} as a record", self.desc())
640 }
641 }
642
643 pub fn unwrap_tuple(&self) -> &Tuple {
649 if let Type::Tuple(handle) = self {
650 &handle
651 } else {
652 panic!("attempted to unwrap a {} as a tuple", self.desc())
653 }
654 }
655
656 pub fn unwrap_variant(&self) -> &Variant {
662 if let Type::Variant(handle) = self {
663 &handle
664 } else {
665 panic!("attempted to unwrap a {} as a variant", self.desc())
666 }
667 }
668
669 pub fn unwrap_enum(&self) -> &Enum {
675 if let Type::Enum(handle) = self {
676 &handle
677 } else {
678 panic!("attempted to unwrap a {} as a enum", self.desc())
679 }
680 }
681
682 pub fn unwrap_option(&self) -> &OptionType {
688 if let Type::Option(handle) = self {
689 &handle
690 } else {
691 panic!("attempted to unwrap a {} as a option", self.desc())
692 }
693 }
694
695 pub fn unwrap_result(&self) -> &ResultType {
701 if let Type::Result(handle) = self {
702 &handle
703 } else {
704 panic!("attempted to unwrap a {} as a result", self.desc())
705 }
706 }
707
708 pub fn unwrap_flags(&self) -> &Flags {
714 if let Type::Flags(handle) = self {
715 &handle
716 } else {
717 panic!("attempted to unwrap a {} as a flags", self.desc())
718 }
719 }
720
721 pub fn unwrap_own(&self) -> &ResourceType {
727 match self {
728 Type::Own(ty) => ty,
729 _ => panic!("attempted to unwrap a {} as a own", self.desc()),
730 }
731 }
732
733 pub fn unwrap_borrow(&self) -> &ResourceType {
739 match self {
740 Type::Borrow(ty) => ty,
741 _ => panic!("attempted to unwrap a {} as a own", self.desc()),
742 }
743 }
744
745 pub(crate) fn from(ty: &InterfaceType, instance: &InstanceType<'_>) -> Self {
747 match ty {
748 InterfaceType::Bool => Type::Bool,
749 InterfaceType::S8 => Type::S8,
750 InterfaceType::U8 => Type::U8,
751 InterfaceType::S16 => Type::S16,
752 InterfaceType::U16 => Type::U16,
753 InterfaceType::S32 => Type::S32,
754 InterfaceType::U32 => Type::U32,
755 InterfaceType::S64 => Type::S64,
756 InterfaceType::U64 => Type::U64,
757 InterfaceType::Float32 => Type::Float32,
758 InterfaceType::Float64 => Type::Float64,
759 InterfaceType::Char => Type::Char,
760 InterfaceType::String => Type::String,
761 InterfaceType::List(index) => Type::List(List::from(*index, instance)),
762 InterfaceType::Record(index) => Type::Record(Record::from(*index, instance)),
763 InterfaceType::Tuple(index) => Type::Tuple(Tuple::from(*index, instance)),
764 InterfaceType::Variant(index) => Type::Variant(Variant::from(*index, instance)),
765 InterfaceType::Enum(index) => Type::Enum(Enum::from(*index, instance)),
766 InterfaceType::Option(index) => Type::Option(OptionType::from(*index, instance)),
767 InterfaceType::Result(index) => Type::Result(ResultType::from(*index, instance)),
768 InterfaceType::Flags(index) => Type::Flags(Flags::from(*index, instance)),
769 InterfaceType::Own(index) => Type::Own(instance.resource_type(*index)),
770 InterfaceType::Borrow(index) => Type::Borrow(instance.resource_type(*index)),
771 InterfaceType::Future(index) => Type::Future(instance.future_type(*index)),
772 InterfaceType::Stream(index) => Type::Stream(instance.stream_type(*index)),
773 InterfaceType::ErrorContext(_) => Type::ErrorContext,
774 }
775 }
776
777 fn desc(&self) -> &'static str {
778 match self {
779 Type::Bool => "bool",
780 Type::S8 => "s8",
781 Type::U8 => "u8",
782 Type::S16 => "s16",
783 Type::U16 => "u16",
784 Type::S32 => "s32",
785 Type::U32 => "u32",
786 Type::S64 => "s64",
787 Type::U64 => "u64",
788 Type::Float32 => "float32",
789 Type::Float64 => "float64",
790 Type::Char => "char",
791 Type::String => "string",
792 Type::List(_) => "list",
793 Type::Record(_) => "record",
794 Type::Tuple(_) => "tuple",
795 Type::Variant(_) => "variant",
796 Type::Enum(_) => "enum",
797 Type::Option(_) => "option",
798 Type::Result(_) => "result",
799 Type::Flags(_) => "flags",
800 Type::Own(_) => "own",
801 Type::Borrow(_) => "borrow",
802 Type::Future(_) => "future",
803 Type::Stream(_) => "stream",
804 Type::ErrorContext => "error-context",
805 }
806 }
807}
808
809#[derive(Clone, Debug)]
811pub struct ComponentFunc(Handle<TypeFuncIndex>);
812
813impl ComponentFunc {
814 pub(crate) fn from(index: TypeFuncIndex, ty: &InstanceType<'_>) -> Self {
815 Self(Handle::new(index, ty))
816 }
817
818 pub fn params(&self) -> impl ExactSizeIterator<Item = (&str, Type)> + '_ {
820 let ty = &self.0.types[self.0.index];
821 self.0.types[ty.params]
822 .types
823 .iter()
824 .zip(&ty.param_names)
825 .map(|(ty, name)| (name.as_str(), Type::from(ty, &self.0.instance())))
826 }
827
828 pub fn results(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
830 let results = self.0.types[self.0.index].results;
831 self.0.types[results]
832 .types
833 .iter()
834 .map(|ty| Type::from(ty, &self.0.instance()))
835 }
836
837 #[doc(hidden)]
838 pub fn typecheck<Params, Return>(&self, cx: &InstanceType) -> anyhow::Result<()>
839 where
840 Params: crate::component::ComponentNamedList + crate::component::Lower,
841 Return: crate::component::ComponentNamedList + crate::component::Lift,
842 {
843 let ty = &self.0.types[self.0.index];
844 Params::typecheck(&InterfaceType::Tuple(ty.params), cx)?;
845 Return::typecheck(&InterfaceType::Tuple(ty.results), cx)?;
846 Ok(())
847 }
848}
849
850#[derive(Clone, Debug)]
852pub struct Module(Handle<TypeModuleIndex>);
853
854impl Module {
855 pub(crate) fn from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self {
856 Self(Handle::new(index, ty))
857 }
858
859 pub fn imports<'a>(
861 &'a self,
862 engine: &'a Engine,
863 ) -> impl ExactSizeIterator<Item = ((&'a str, &'a str), ExternType)> + 'a {
864 self.0.types[self.0.index]
865 .imports
866 .iter()
867 .map(|((namespace, name), ty)| {
868 (
869 (namespace.as_str(), name.as_str()),
870 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
871 )
872 })
873 }
874
875 pub fn exports<'a>(
877 &'a self,
878 engine: &'a Engine,
879 ) -> impl ExactSizeIterator<Item = (&'a str, ExternType)> + 'a {
880 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
881 (
882 name.as_str(),
883 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
884 )
885 })
886 }
887}
888
889#[derive(Clone, Debug)]
891pub struct Component(Handle<TypeComponentIndex>);
892
893impl Component {
894 pub(crate) fn from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self {
895 Self(Handle::new(index, ty))
896 }
897
898 pub fn get_import(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
900 self.0.types[self.0.index]
901 .imports
902 .get(name)
903 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
904 }
905
906 pub fn imports<'a>(
908 &'a self,
909 engine: &'a Engine,
910 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
911 self.0.types[self.0.index].imports.iter().map(|(name, ty)| {
912 (
913 name.as_str(),
914 ComponentItem::from(engine, ty, &self.0.instance()),
915 )
916 })
917 }
918
919 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
921 self.0.types[self.0.index]
922 .exports
923 .get(name)
924 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
925 }
926
927 pub fn exports<'a>(
929 &'a self,
930 engine: &'a Engine,
931 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
932 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
933 (
934 name.as_str(),
935 ComponentItem::from(engine, ty, &self.0.instance()),
936 )
937 })
938 }
939
940 #[doc(hidden)]
941 pub fn instance_type(&self) -> InstanceType<'_> {
942 InstanceType {
943 types: &self.0.types,
944 resources: &self.0.resources,
945 }
946 }
947}
948
949#[derive(Clone, Debug)]
951pub struct ComponentInstance(Handle<TypeComponentInstanceIndex>);
952
953impl ComponentInstance {
954 pub(crate) fn from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self {
955 Self(Handle::new(index, ty))
956 }
957
958 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
960 self.0.types[self.0.index]
961 .exports
962 .get(name)
963 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
964 }
965
966 pub fn exports<'a>(
968 &'a self,
969 engine: &'a Engine,
970 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> {
971 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
972 (
973 name.as_str(),
974 ComponentItem::from(engine, ty, &self.0.instance()),
975 )
976 })
977 }
978}
979
980#[derive(Clone, Debug)]
982pub enum ComponentItem {
983 ComponentFunc(ComponentFunc),
985 CoreFunc(FuncType),
987 Module(Module),
989 Component(Component),
991 ComponentInstance(ComponentInstance),
993 Type(Type),
995 Resource(ResourceType),
997}
998
999impl ComponentItem {
1000 pub(crate) fn from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self {
1001 match def {
1002 TypeDef::Component(idx) => Self::Component(Component::from(*idx, ty)),
1003 TypeDef::ComponentInstance(idx) => {
1004 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1005 }
1006 TypeDef::ComponentFunc(idx) => Self::ComponentFunc(ComponentFunc::from(*idx, ty)),
1007 TypeDef::Interface(iface_ty) => Self::Type(Type::from(iface_ty, ty)),
1008 TypeDef::Module(idx) => Self::Module(Module::from(*idx, ty)),
1009 TypeDef::CoreFunc(idx) => {
1010 let subty = &ty.types[*idx];
1011 Self::CoreFunc(FuncType::from_wasm_func_type(
1012 engine,
1013 subty.is_final,
1014 subty.supertype,
1015 subty.unwrap_func().clone(),
1016 ))
1017 }
1018 TypeDef::Resource(idx) => match ty.types[*idx] {
1019 TypeResourceTable::Concrete {
1020 ty: resource_index, ..
1021 } => {
1022 let ty = match ty.resources.get(resource_index) {
1023 Some(ty) => *ty,
1026
1027 None => ResourceType::uninstantiated(&ty.types, resource_index),
1029 };
1030 Self::Resource(ty)
1031 }
1032 TypeResourceTable::Abstract(resource_index) => {
1033 Self::Resource(ResourceType::abstract_(&ty.types, resource_index))
1034 }
1035 },
1036 }
1037 }
1038 pub(crate) fn from_export(engine: &Engine, export: &Export, ty: &InstanceType<'_>) -> Self {
1039 match export {
1040 Export::Instance { ty: idx, .. } => {
1041 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1042 }
1043 Export::LiftedFunction { ty: idx, .. } => {
1044 Self::ComponentFunc(ComponentFunc::from(*idx, ty))
1045 }
1046 Export::ModuleStatic { ty: idx, .. } | Export::ModuleImport { ty: idx, .. } => {
1047 Self::Module(Module::from(*idx, ty))
1048 }
1049 Export::Type(idx) => Self::from(engine, idx, ty),
1050 }
1051 }
1052}