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, 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 let a = &self.a_types[o1];
170 let b = &self.b_types[o2];
171 self.a_resource[a.ty] == self.b_resource[b.ty]
172 }
173
174 fn records_equal(&self, r1: TypeRecordIndex, r2: TypeRecordIndex) -> bool {
175 let a = &self.a_types[r1];
176 let b = &self.b_types[r2];
177 if a.fields.len() != b.fields.len() {
178 return false;
179 }
180 a.fields
181 .iter()
182 .zip(b.fields.iter())
183 .all(|(a_field, b_field)| {
184 a_field.name == b_field.name && self.interface_types_equal(a_field.ty, b_field.ty)
185 })
186 }
187
188 fn variants_equal(&self, v1: TypeVariantIndex, v2: TypeVariantIndex) -> bool {
189 let a = &self.a_types[v1];
190 let b = &self.b_types[v2];
191 if a.cases.len() != b.cases.len() {
192 return false;
193 }
194 a.cases
195 .iter()
196 .zip(b.cases.iter())
197 .all(|((a_name, a_ty), (b_name, b_ty))| {
198 if a_name != b_name {
199 return false;
200 }
201 match (a_ty, b_ty) {
202 (Some(a_case_ty), Some(b_case_ty)) => {
203 self.interface_types_equal(*a_case_ty, *b_case_ty)
204 }
205 (None, None) => true,
206 _ => false,
207 }
208 })
209 }
210
211 fn results_equal(&self, r1: TypeResultIndex, r2: TypeResultIndex) -> bool {
212 let a = &self.a_types[r1];
213 let b = &self.b_types[r2];
214 let oks = match (a.ok, b.ok) {
215 (Some(ok1), Some(ok2)) => self.interface_types_equal(ok1, ok2),
216 (None, None) => true,
217 _ => false,
218 };
219 if !oks {
220 return false;
221 }
222 match (a.err, b.err) {
223 (Some(err1), Some(err2)) => self.interface_types_equal(err1, err2),
224 (None, None) => true,
225 _ => false,
226 }
227 }
228
229 fn options_equal(&self, o1: TypeOptionIndex, o2: TypeOptionIndex) -> bool {
230 let a = &self.a_types[o1];
231 let b = &self.b_types[o2];
232 self.interface_types_equal(a.ty, b.ty)
233 }
234
235 fn enums_equal(&self, e1: TypeEnumIndex, e2: TypeEnumIndex) -> bool {
236 let a = &self.a_types[e1];
237 let b = &self.b_types[e2];
238 a.names == b.names
239 }
240
241 fn tuples_equal(&self, t1: TypeTupleIndex, t2: TypeTupleIndex) -> bool {
242 let a = &self.a_types[t1];
243 let b = &self.b_types[t2];
244 if a.types.len() != b.types.len() {
245 return false;
246 }
247 a.types
248 .iter()
249 .zip(b.types.iter())
250 .all(|(&a, &b)| self.interface_types_equal(a, b))
251 }
252
253 fn flags_equal(&self, f1: TypeFlagsIndex, f2: TypeFlagsIndex) -> bool {
254 let a = &self.a_types[f1];
255 let b = &self.b_types[f2];
256 a.names == b.names
257 }
258
259 fn future_table_types_equal(&self, t1: TypeFutureTableIndex, t2: TypeFutureTableIndex) -> bool {
260 self.futures_equal(self.a_types[t1].ty, self.b_types[t2].ty)
261 }
262
263 fn futures_equal(&self, t1: TypeFutureIndex, t2: TypeFutureIndex) -> bool {
264 let a = &self.a_types[t1];
265 let b = &self.b_types[t2];
266 match (a.payload, b.payload) {
267 (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
268 (None, None) => true,
269 _ => false,
270 }
271 }
272
273 fn stream_table_types_equal(&self, t1: TypeStreamTableIndex, t2: TypeStreamTableIndex) -> bool {
274 self.streams_equal(self.a_types[t1].ty, self.b_types[t2].ty)
275 }
276
277 fn streams_equal(&self, t1: TypeStreamIndex, t2: TypeStreamIndex) -> 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
288#[derive(Clone, Debug)]
290pub struct List(Handle<TypeListIndex>);
291
292impl PartialEq for List {
293 fn eq(&self, other: &Self) -> bool {
294 self.0.equivalent(&other.0, TypeChecker::lists_equal)
295 }
296}
297
298impl Eq for List {}
299
300impl List {
301 pub(crate) fn from(index: TypeListIndex, ty: &InstanceType<'_>) -> Self {
302 List(Handle::new(index, ty))
303 }
304
305 pub fn ty(&self) -> Type {
307 Type::from(&self.0.types[self.0.index].element, &self.0.instance())
308 }
309}
310
311#[derive(Debug)]
313pub struct Field<'a> {
314 pub name: &'a str,
316 pub ty: Type,
318}
319
320#[derive(Clone, Debug)]
322pub struct Record(Handle<TypeRecordIndex>);
323
324impl Record {
325 pub(crate) fn from(index: TypeRecordIndex, ty: &InstanceType<'_>) -> Self {
326 Record(Handle::new(index, ty))
327 }
328
329 pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> {
331 self.0.types[self.0.index].fields.iter().map(|field| Field {
332 name: &field.name,
333 ty: Type::from(&field.ty, &self.0.instance()),
334 })
335 }
336}
337
338impl PartialEq for Record {
339 fn eq(&self, other: &Self) -> bool {
340 self.0.equivalent(&other.0, TypeChecker::records_equal)
341 }
342}
343
344impl Eq for Record {}
345
346#[derive(Clone, Debug)]
348pub struct Tuple(Handle<TypeTupleIndex>);
349
350impl Tuple {
351 pub(crate) fn from(index: TypeTupleIndex, ty: &InstanceType<'_>) -> Self {
352 Tuple(Handle::new(index, ty))
353 }
354
355 pub fn types(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
357 self.0.types[self.0.index]
358 .types
359 .iter()
360 .map(|ty| Type::from(ty, &self.0.instance()))
361 }
362}
363
364impl PartialEq for Tuple {
365 fn eq(&self, other: &Self) -> bool {
366 self.0.equivalent(&other.0, TypeChecker::tuples_equal)
367 }
368}
369
370impl Eq for Tuple {}
371
372pub struct Case<'a> {
374 pub name: &'a str,
376 pub ty: Option<Type>,
378}
379
380#[derive(Clone, Debug)]
382pub struct Variant(Handle<TypeVariantIndex>);
383
384impl Variant {
385 pub(crate) fn from(index: TypeVariantIndex, ty: &InstanceType<'_>) -> Self {
386 Variant(Handle::new(index, ty))
387 }
388
389 pub fn cases(&self) -> impl ExactSizeIterator<Item = Case<'_>> {
391 self.0.types[self.0.index]
392 .cases
393 .iter()
394 .map(|(name, ty)| Case {
395 name,
396 ty: ty.as_ref().map(|ty| Type::from(ty, &self.0.instance())),
397 })
398 }
399}
400
401impl PartialEq for Variant {
402 fn eq(&self, other: &Self) -> bool {
403 self.0.equivalent(&other.0, TypeChecker::variants_equal)
404 }
405}
406
407impl Eq for Variant {}
408
409#[derive(Clone, Debug)]
411pub struct Enum(Handle<TypeEnumIndex>);
412
413impl Enum {
414 pub(crate) fn from(index: TypeEnumIndex, ty: &InstanceType<'_>) -> Self {
415 Enum(Handle::new(index, ty))
416 }
417
418 pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
420 self.0.types[self.0.index]
421 .names
422 .iter()
423 .map(|name| name.deref())
424 }
425}
426
427impl PartialEq for Enum {
428 fn eq(&self, other: &Self) -> bool {
429 self.0.equivalent(&other.0, TypeChecker::enums_equal)
430 }
431}
432
433impl Eq for Enum {}
434
435#[derive(Clone, Debug)]
437pub struct OptionType(Handle<TypeOptionIndex>);
438
439impl OptionType {
440 pub(crate) fn from(index: TypeOptionIndex, ty: &InstanceType<'_>) -> Self {
441 OptionType(Handle::new(index, ty))
442 }
443
444 pub fn ty(&self) -> Type {
446 Type::from(&self.0.types[self.0.index].ty, &self.0.instance())
447 }
448}
449
450impl PartialEq for OptionType {
451 fn eq(&self, other: &Self) -> bool {
452 self.0.equivalent(&other.0, TypeChecker::options_equal)
453 }
454}
455
456impl Eq for OptionType {}
457
458#[derive(Clone, Debug)]
460pub struct ResultType(Handle<TypeResultIndex>);
461
462impl ResultType {
463 pub(crate) fn from(index: TypeResultIndex, ty: &InstanceType<'_>) -> Self {
464 ResultType(Handle::new(index, ty))
465 }
466
467 pub fn ok(&self) -> Option<Type> {
469 Some(Type::from(
470 self.0.types[self.0.index].ok.as_ref()?,
471 &self.0.instance(),
472 ))
473 }
474
475 pub fn err(&self) -> Option<Type> {
477 Some(Type::from(
478 self.0.types[self.0.index].err.as_ref()?,
479 &self.0.instance(),
480 ))
481 }
482}
483
484impl PartialEq for ResultType {
485 fn eq(&self, other: &Self) -> bool {
486 self.0.equivalent(&other.0, TypeChecker::results_equal)
487 }
488}
489
490impl Eq for ResultType {}
491
492#[derive(Clone, Debug)]
494pub struct Flags(Handle<TypeFlagsIndex>);
495
496impl Flags {
497 pub(crate) fn from(index: TypeFlagsIndex, ty: &InstanceType<'_>) -> Self {
498 Flags(Handle::new(index, ty))
499 }
500
501 pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
503 self.0.types[self.0.index]
504 .names
505 .iter()
506 .map(|name| name.deref())
507 }
508}
509
510impl PartialEq for Flags {
511 fn eq(&self, other: &Self) -> bool {
512 self.0.equivalent(&other.0, TypeChecker::flags_equal)
513 }
514}
515
516impl Eq for Flags {}
517
518#[derive(Clone, Debug)]
520pub struct FutureType(Handle<TypeFutureIndex>);
521
522impl FutureType {
523 pub(crate) fn from(index: TypeFutureIndex, ty: &InstanceType<'_>) -> Self {
524 FutureType(Handle::new(index, ty))
525 }
526
527 pub fn ty(&self) -> Option<Type> {
529 Some(Type::from(
530 self.0.types[self.0.index].payload.as_ref()?,
531 &self.0.instance(),
532 ))
533 }
534}
535
536impl PartialEq for FutureType {
537 fn eq(&self, other: &Self) -> bool {
538 self.0.equivalent(&other.0, TypeChecker::futures_equal)
539 }
540}
541
542impl Eq for FutureType {}
543
544#[derive(Clone, Debug)]
546pub struct StreamType(Handle<TypeStreamIndex>);
547
548impl StreamType {
549 pub(crate) fn from(index: TypeStreamIndex, ty: &InstanceType<'_>) -> Self {
550 StreamType(Handle::new(index, ty))
551 }
552
553 pub fn ty(&self) -> Option<Type> {
555 Some(Type::from(
556 self.0.types[self.0.index].payload.as_ref()?,
557 &self.0.instance(),
558 ))
559 }
560}
561
562impl PartialEq for StreamType {
563 fn eq(&self, other: &Self) -> bool {
564 self.0.equivalent(&other.0, TypeChecker::streams_equal)
565 }
566}
567
568impl Eq for StreamType {}
569
570#[derive(Clone, PartialEq, Eq, Debug)]
572#[allow(missing_docs)]
573pub enum Type {
574 Bool,
575 S8,
576 U8,
577 S16,
578 U16,
579 S32,
580 U32,
581 S64,
582 U64,
583 Float32,
584 Float64,
585 Char,
586 String,
587 List(List),
588 Record(Record),
589 Tuple(Tuple),
590 Variant(Variant),
591 Enum(Enum),
592 Option(OptionType),
593 Result(ResultType),
594 Flags(Flags),
595 Own(ResourceType),
596 Borrow(ResourceType),
597 Future(FutureType),
598 Stream(StreamType),
599 ErrorContext,
600}
601
602impl Type {
603 pub fn unwrap_list(&self) -> &List {
609 if let Type::List(handle) = self {
610 &handle
611 } else {
612 panic!("attempted to unwrap a {} as a list", self.desc())
613 }
614 }
615
616 pub fn unwrap_record(&self) -> &Record {
622 if let Type::Record(handle) = self {
623 &handle
624 } else {
625 panic!("attempted to unwrap a {} as a record", self.desc())
626 }
627 }
628
629 pub fn unwrap_tuple(&self) -> &Tuple {
635 if let Type::Tuple(handle) = self {
636 &handle
637 } else {
638 panic!("attempted to unwrap a {} as a tuple", self.desc())
639 }
640 }
641
642 pub fn unwrap_variant(&self) -> &Variant {
648 if let Type::Variant(handle) = self {
649 &handle
650 } else {
651 panic!("attempted to unwrap a {} as a variant", self.desc())
652 }
653 }
654
655 pub fn unwrap_enum(&self) -> &Enum {
661 if let Type::Enum(handle) = self {
662 &handle
663 } else {
664 panic!("attempted to unwrap a {} as a enum", self.desc())
665 }
666 }
667
668 pub fn unwrap_option(&self) -> &OptionType {
674 if let Type::Option(handle) = self {
675 &handle
676 } else {
677 panic!("attempted to unwrap a {} as a option", self.desc())
678 }
679 }
680
681 pub fn unwrap_result(&self) -> &ResultType {
687 if let Type::Result(handle) = self {
688 &handle
689 } else {
690 panic!("attempted to unwrap a {} as a result", self.desc())
691 }
692 }
693
694 pub fn unwrap_flags(&self) -> &Flags {
700 if let Type::Flags(handle) = self {
701 &handle
702 } else {
703 panic!("attempted to unwrap a {} as a flags", self.desc())
704 }
705 }
706
707 pub fn unwrap_own(&self) -> &ResourceType {
713 match self {
714 Type::Own(ty) => ty,
715 _ => panic!("attempted to unwrap a {} as a own", self.desc()),
716 }
717 }
718
719 pub fn unwrap_borrow(&self) -> &ResourceType {
725 match self {
726 Type::Borrow(ty) => ty,
727 _ => panic!("attempted to unwrap a {} as a own", self.desc()),
728 }
729 }
730
731 pub(crate) fn from(ty: &InterfaceType, instance: &InstanceType<'_>) -> Self {
733 match ty {
734 InterfaceType::Bool => Type::Bool,
735 InterfaceType::S8 => Type::S8,
736 InterfaceType::U8 => Type::U8,
737 InterfaceType::S16 => Type::S16,
738 InterfaceType::U16 => Type::U16,
739 InterfaceType::S32 => Type::S32,
740 InterfaceType::U32 => Type::U32,
741 InterfaceType::S64 => Type::S64,
742 InterfaceType::U64 => Type::U64,
743 InterfaceType::Float32 => Type::Float32,
744 InterfaceType::Float64 => Type::Float64,
745 InterfaceType::Char => Type::Char,
746 InterfaceType::String => Type::String,
747 InterfaceType::List(index) => Type::List(List::from(*index, instance)),
748 InterfaceType::Record(index) => Type::Record(Record::from(*index, instance)),
749 InterfaceType::Tuple(index) => Type::Tuple(Tuple::from(*index, instance)),
750 InterfaceType::Variant(index) => Type::Variant(Variant::from(*index, instance)),
751 InterfaceType::Enum(index) => Type::Enum(Enum::from(*index, instance)),
752 InterfaceType::Option(index) => Type::Option(OptionType::from(*index, instance)),
753 InterfaceType::Result(index) => Type::Result(ResultType::from(*index, instance)),
754 InterfaceType::Flags(index) => Type::Flags(Flags::from(*index, instance)),
755 InterfaceType::Own(index) => Type::Own(instance.resource_type(*index)),
756 InterfaceType::Borrow(index) => Type::Borrow(instance.resource_type(*index)),
757 InterfaceType::Future(index) => Type::Future(instance.future_type(*index)),
758 InterfaceType::Stream(index) => Type::Stream(instance.stream_type(*index)),
759 InterfaceType::ErrorContext(_) => Type::ErrorContext,
760 }
761 }
762
763 fn desc(&self) -> &'static str {
764 match self {
765 Type::Bool => "bool",
766 Type::S8 => "s8",
767 Type::U8 => "u8",
768 Type::S16 => "s16",
769 Type::U16 => "u16",
770 Type::S32 => "s32",
771 Type::U32 => "u32",
772 Type::S64 => "s64",
773 Type::U64 => "u64",
774 Type::Float32 => "float32",
775 Type::Float64 => "float64",
776 Type::Char => "char",
777 Type::String => "string",
778 Type::List(_) => "list",
779 Type::Record(_) => "record",
780 Type::Tuple(_) => "tuple",
781 Type::Variant(_) => "variant",
782 Type::Enum(_) => "enum",
783 Type::Option(_) => "option",
784 Type::Result(_) => "result",
785 Type::Flags(_) => "flags",
786 Type::Own(_) => "own",
787 Type::Borrow(_) => "borrow",
788 Type::Future(_) => "future",
789 Type::Stream(_) => "stream",
790 Type::ErrorContext => "error-context",
791 }
792 }
793}
794
795#[derive(Clone, Debug)]
797pub struct ComponentFunc(Handle<TypeFuncIndex>);
798
799impl ComponentFunc {
800 pub(crate) fn from(index: TypeFuncIndex, ty: &InstanceType<'_>) -> Self {
801 Self(Handle::new(index, ty))
802 }
803
804 pub fn params(&self) -> impl ExactSizeIterator<Item = (&str, Type)> + '_ {
806 let ty = &self.0.types[self.0.index];
807 self.0.types[ty.params]
808 .types
809 .iter()
810 .zip(&ty.param_names)
811 .map(|(ty, name)| (name.as_str(), Type::from(ty, &self.0.instance())))
812 }
813
814 pub fn results(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
816 let results = self.0.types[self.0.index].results;
817 self.0.types[results]
818 .types
819 .iter()
820 .map(|ty| Type::from(ty, &self.0.instance()))
821 }
822
823 #[doc(hidden)]
824 pub fn typecheck<Params, Return>(&self, cx: &InstanceType) -> anyhow::Result<()>
825 where
826 Params: crate::component::ComponentNamedList + crate::component::Lower,
827 Return: crate::component::ComponentNamedList + crate::component::Lift,
828 {
829 let ty = &self.0.types[self.0.index];
830 Params::typecheck(&InterfaceType::Tuple(ty.params), cx)?;
831 Return::typecheck(&InterfaceType::Tuple(ty.results), cx)?;
832 Ok(())
833 }
834}
835
836#[derive(Clone, Debug)]
838pub struct Module(Handle<TypeModuleIndex>);
839
840impl Module {
841 pub(crate) fn from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self {
842 Self(Handle::new(index, ty))
843 }
844
845 pub fn imports<'a>(
847 &'a self,
848 engine: &'a Engine,
849 ) -> impl ExactSizeIterator<Item = ((&'a str, &'a str), ExternType)> + 'a {
850 self.0.types[self.0.index]
851 .imports
852 .iter()
853 .map(|((namespace, name), ty)| {
854 (
855 (namespace.as_str(), name.as_str()),
856 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
857 )
858 })
859 }
860
861 pub fn exports<'a>(
863 &'a self,
864 engine: &'a Engine,
865 ) -> impl ExactSizeIterator<Item = (&'a str, ExternType)> + 'a {
866 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
867 (
868 name.as_str(),
869 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
870 )
871 })
872 }
873}
874
875#[derive(Clone, Debug)]
877pub struct Component(Handle<TypeComponentIndex>);
878
879impl Component {
880 pub(crate) fn from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self {
881 Self(Handle::new(index, ty))
882 }
883
884 pub fn get_import(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
886 self.0.types[self.0.index]
887 .imports
888 .get(name)
889 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
890 }
891
892 pub fn imports<'a>(
894 &'a self,
895 engine: &'a Engine,
896 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
897 self.0.types[self.0.index].imports.iter().map(|(name, ty)| {
898 (
899 name.as_str(),
900 ComponentItem::from(engine, ty, &self.0.instance()),
901 )
902 })
903 }
904
905 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
907 self.0.types[self.0.index]
908 .exports
909 .get(name)
910 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
911 }
912
913 pub fn exports<'a>(
915 &'a self,
916 engine: &'a Engine,
917 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
918 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
919 (
920 name.as_str(),
921 ComponentItem::from(engine, ty, &self.0.instance()),
922 )
923 })
924 }
925
926 #[doc(hidden)]
927 pub fn instance_type(&self) -> InstanceType<'_> {
928 InstanceType {
929 types: &self.0.types,
930 resources: &self.0.resources,
931 }
932 }
933}
934
935#[derive(Clone, Debug)]
937pub struct ComponentInstance(Handle<TypeComponentInstanceIndex>);
938
939impl ComponentInstance {
940 pub(crate) fn from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self {
941 Self(Handle::new(index, ty))
942 }
943
944 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
946 self.0.types[self.0.index]
947 .exports
948 .get(name)
949 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
950 }
951
952 pub fn exports<'a>(
954 &'a self,
955 engine: &'a Engine,
956 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> {
957 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
958 (
959 name.as_str(),
960 ComponentItem::from(engine, ty, &self.0.instance()),
961 )
962 })
963 }
964}
965
966#[derive(Clone, Debug)]
968pub enum ComponentItem {
969 ComponentFunc(ComponentFunc),
971 CoreFunc(FuncType),
973 Module(Module),
975 Component(Component),
977 ComponentInstance(ComponentInstance),
979 Type(Type),
981 Resource(ResourceType),
983}
984
985impl ComponentItem {
986 pub(crate) fn from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self {
987 match def {
988 TypeDef::Component(idx) => Self::Component(Component::from(*idx, ty)),
989 TypeDef::ComponentInstance(idx) => {
990 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
991 }
992 TypeDef::ComponentFunc(idx) => Self::ComponentFunc(ComponentFunc::from(*idx, ty)),
993 TypeDef::Interface(iface_ty) => Self::Type(Type::from(iface_ty, ty)),
994 TypeDef::Module(idx) => Self::Module(Module::from(*idx, ty)),
995 TypeDef::CoreFunc(idx) => {
996 let subty = &ty.types[*idx];
997 Self::CoreFunc(FuncType::from_wasm_func_type(
998 engine,
999 subty.is_final,
1000 subty.supertype,
1001 subty.unwrap_func().clone(),
1002 ))
1003 }
1004 TypeDef::Resource(idx) => {
1005 let resource_index = ty.types[*idx].ty;
1006 let ty = match ty.resources.get(resource_index) {
1007 Some(ty) => *ty,
1010
1011 None => ResourceType::uninstantiated(&ty.types, resource_index),
1013 };
1014 Self::Resource(ty)
1015 }
1016 }
1017 }
1018 pub(crate) fn from_export(engine: &Engine, export: &Export, ty: &InstanceType<'_>) -> Self {
1019 match export {
1020 Export::Instance { ty: idx, .. } => {
1021 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1022 }
1023 Export::LiftedFunction { ty: idx, .. } => {
1024 Self::ComponentFunc(ComponentFunc::from(*idx, ty))
1025 }
1026 Export::ModuleStatic { ty: idx, .. } | Export::ModuleImport { ty: idx, .. } => {
1027 Self::Module(Module::from(*idx, ty))
1028 }
1029 Export::Type(idx) => Self::from(engine, idx, ty),
1030 }
1031 }
1032}