1use crate::component::matching::InstanceType;
4use crate::{Engine, ExternType, FuncType};
5use alloc::sync::Arc;
6use core::fmt;
7use core::ops::Deref;
8use wasmtime_environ::component::{
9 ComponentTypes, InterfaceType, ResourceIndex, TypeComponentIndex, TypeComponentInstanceIndex,
10 TypeDef, TypeEnumIndex, TypeFlagsIndex, TypeFuncIndex, TypeListIndex, TypeModuleIndex,
11 TypeOptionIndex, TypeRecordIndex, TypeResourceTableIndex, TypeResultIndex, TypeTupleIndex,
12 TypeVariantIndex,
13};
14use wasmtime_environ::PrimaryMap;
15
16pub use crate::component::resources::ResourceType;
17
18#[derive(Clone)]
37struct Handle<T> {
38 index: T,
39 types: Arc<ComponentTypes>,
40 resources: Arc<PrimaryMap<ResourceIndex, ResourceType>>,
41}
42
43impl<T> Handle<T> {
44 fn new(index: T, ty: &InstanceType<'_>) -> Handle<T> {
45 Handle {
46 index,
47 types: ty.types.clone(),
48 resources: ty.resources.clone(),
49 }
50 }
51
52 fn instance(&self) -> InstanceType<'_> {
53 InstanceType {
54 types: &self.types,
55 resources: &self.resources,
56 }
57 }
58
59 fn equivalent<'a>(
60 &'a self,
61 other: &'a Self,
62 type_check: fn(&TypeChecker<'a>, T, T) -> bool,
63 ) -> bool
64 where
65 T: PartialEq + Copy,
66 {
67 (self.index == other.index
68 && Arc::ptr_eq(&self.types, &other.types)
69 && Arc::ptr_eq(&self.resources, &other.resources))
70 || type_check(
71 &TypeChecker {
72 a_types: &self.types,
73 b_types: &other.types,
74 a_resource: &self.resources,
75 b_resource: &other.resources,
76 },
77 self.index,
78 other.index,
79 )
80 }
81}
82
83impl<T: fmt::Debug> fmt::Debug for Handle<T> {
84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85 f.debug_struct("Handle")
86 .field("index", &self.index)
87 .finish()
88 }
89}
90
91struct TypeChecker<'a> {
93 a_types: &'a ComponentTypes,
94 a_resource: &'a PrimaryMap<ResourceIndex, ResourceType>,
95 b_types: &'a ComponentTypes,
96 b_resource: &'a PrimaryMap<ResourceIndex, ResourceType>,
97}
98
99impl TypeChecker<'_> {
100 fn interface_types_equal(&self, a: InterfaceType, b: InterfaceType) -> bool {
101 match (a, b) {
102 (InterfaceType::Own(o1), InterfaceType::Own(o2)) => self.resources_equal(o1, o2),
103 (InterfaceType::Own(_), _) => false,
104 (InterfaceType::Borrow(b1), InterfaceType::Borrow(b2)) => self.resources_equal(b1, b2),
105 (InterfaceType::Borrow(_), _) => false,
106 (InterfaceType::List(l1), InterfaceType::List(l2)) => self.lists_equal(l1, l2),
107 (InterfaceType::List(_), _) => false,
108 (InterfaceType::Record(r1), InterfaceType::Record(r2)) => self.records_equal(r1, r2),
109 (InterfaceType::Record(_), _) => false,
110 (InterfaceType::Variant(v1), InterfaceType::Variant(v2)) => self.variants_equal(v1, v2),
111 (InterfaceType::Variant(_), _) => false,
112 (InterfaceType::Result(r1), InterfaceType::Result(r2)) => self.results_equal(r1, r2),
113 (InterfaceType::Result(_), _) => false,
114 (InterfaceType::Option(o1), InterfaceType::Option(o2)) => self.options_equal(o1, o2),
115 (InterfaceType::Option(_), _) => false,
116 (InterfaceType::Enum(e1), InterfaceType::Enum(e2)) => self.enums_equal(e1, e2),
117 (InterfaceType::Enum(_), _) => false,
118 (InterfaceType::Tuple(t1), InterfaceType::Tuple(t2)) => self.tuples_equal(t1, t2),
119 (InterfaceType::Tuple(_), _) => false,
120 (InterfaceType::Flags(f1), InterfaceType::Flags(f2)) => self.flags_equal(f1, f2),
121 (InterfaceType::Flags(_), _) => false,
122 (InterfaceType::Bool, InterfaceType::Bool) => true,
123 (InterfaceType::Bool, _) => false,
124 (InterfaceType::U8, InterfaceType::U8) => true,
125 (InterfaceType::U8, _) => false,
126 (InterfaceType::U16, InterfaceType::U16) => true,
127 (InterfaceType::U16, _) => false,
128 (InterfaceType::U32, InterfaceType::U32) => true,
129 (InterfaceType::U32, _) => false,
130 (InterfaceType::U64, InterfaceType::U64) => true,
131 (InterfaceType::U64, _) => false,
132 (InterfaceType::S8, InterfaceType::S8) => true,
133 (InterfaceType::S8, _) => false,
134 (InterfaceType::S16, InterfaceType::S16) => true,
135 (InterfaceType::S16, _) => false,
136 (InterfaceType::S32, InterfaceType::S32) => true,
137 (InterfaceType::S32, _) => false,
138 (InterfaceType::S64, InterfaceType::S64) => true,
139 (InterfaceType::S64, _) => false,
140 (InterfaceType::Float32, InterfaceType::Float32) => true,
141 (InterfaceType::Float32, _) => false,
142 (InterfaceType::Float64, InterfaceType::Float64) => true,
143 (InterfaceType::Float64, _) => false,
144 (InterfaceType::String, InterfaceType::String) => true,
145 (InterfaceType::String, _) => false,
146 (InterfaceType::Char, InterfaceType::Char) => true,
147 (InterfaceType::Char, _) => false,
148 (InterfaceType::Future(_), _)
149 | (InterfaceType::Stream(_), _)
150 | (InterfaceType::ErrorContext(_), _) => todo!(),
151 }
152 }
153
154 fn lists_equal(&self, l1: TypeListIndex, l2: TypeListIndex) -> bool {
155 let a = &self.a_types[l1];
156 let b = &self.b_types[l2];
157 self.interface_types_equal(a.element, b.element)
158 }
159
160 fn resources_equal(&self, o1: TypeResourceTableIndex, o2: TypeResourceTableIndex) -> bool {
161 let a = &self.a_types[o1];
162 let b = &self.b_types[o2];
163 self.a_resource[a.ty] == self.b_resource[b.ty]
164 }
165
166 fn records_equal(&self, r1: TypeRecordIndex, r2: TypeRecordIndex) -> bool {
167 let a = &self.a_types[r1];
168 let b = &self.b_types[r2];
169 if a.fields.len() != b.fields.len() {
170 return false;
171 }
172 a.fields
173 .iter()
174 .zip(b.fields.iter())
175 .all(|(a_field, b_field)| {
176 a_field.name == b_field.name && self.interface_types_equal(a_field.ty, b_field.ty)
177 })
178 }
179
180 fn variants_equal(&self, v1: TypeVariantIndex, v2: TypeVariantIndex) -> bool {
181 let a = &self.a_types[v1];
182 let b = &self.b_types[v2];
183 if a.cases.len() != b.cases.len() {
184 return false;
185 }
186 a.cases
187 .iter()
188 .zip(b.cases.iter())
189 .all(|((a_name, a_ty), (b_name, b_ty))| {
190 if a_name != b_name {
191 return false;
192 }
193 match (a_ty, b_ty) {
194 (Some(a_case_ty), Some(b_case_ty)) => {
195 self.interface_types_equal(*a_case_ty, *b_case_ty)
196 }
197 (None, None) => true,
198 _ => false,
199 }
200 })
201 }
202
203 fn results_equal(&self, r1: TypeResultIndex, r2: TypeResultIndex) -> bool {
204 let a = &self.a_types[r1];
205 let b = &self.b_types[r2];
206 let oks = match (a.ok, b.ok) {
207 (Some(ok1), Some(ok2)) => self.interface_types_equal(ok1, ok2),
208 (None, None) => true,
209 _ => false,
210 };
211 if !oks {
212 return false;
213 }
214 match (a.err, b.err) {
215 (Some(err1), Some(err2)) => self.interface_types_equal(err1, err2),
216 (None, None) => true,
217 _ => false,
218 }
219 }
220
221 fn options_equal(&self, o1: TypeOptionIndex, o2: TypeOptionIndex) -> bool {
222 let a = &self.a_types[o1];
223 let b = &self.b_types[o2];
224 self.interface_types_equal(a.ty, b.ty)
225 }
226
227 fn enums_equal(&self, e1: TypeEnumIndex, e2: TypeEnumIndex) -> bool {
228 let a = &self.a_types[e1];
229 let b = &self.b_types[e2];
230 a.names == b.names
231 }
232
233 fn tuples_equal(&self, t1: TypeTupleIndex, t2: TypeTupleIndex) -> bool {
234 let a = &self.a_types[t1];
235 let b = &self.b_types[t2];
236 if a.types.len() != b.types.len() {
237 return false;
238 }
239 a.types
240 .iter()
241 .zip(b.types.iter())
242 .all(|(&a, &b)| self.interface_types_equal(a, b))
243 }
244
245 fn flags_equal(&self, f1: TypeFlagsIndex, f2: TypeFlagsIndex) -> bool {
246 let a = &self.a_types[f1];
247 let b = &self.b_types[f2];
248 a.names == b.names
249 }
250}
251
252#[derive(Clone, Debug)]
254pub struct List(Handle<TypeListIndex>);
255
256impl PartialEq for List {
257 fn eq(&self, other: &Self) -> bool {
258 self.0.equivalent(&other.0, TypeChecker::lists_equal)
259 }
260}
261
262impl Eq for List {}
263
264impl List {
265 pub(crate) fn from(index: TypeListIndex, ty: &InstanceType<'_>) -> Self {
266 List(Handle::new(index, ty))
267 }
268
269 pub fn ty(&self) -> Type {
271 Type::from(&self.0.types[self.0.index].element, &self.0.instance())
272 }
273}
274
275#[derive(Debug)]
277pub struct Field<'a> {
278 pub name: &'a str,
280 pub ty: Type,
282}
283
284#[derive(Clone, Debug)]
286pub struct Record(Handle<TypeRecordIndex>);
287
288impl Record {
289 pub(crate) fn from(index: TypeRecordIndex, ty: &InstanceType<'_>) -> Self {
290 Record(Handle::new(index, ty))
291 }
292
293 pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> {
295 self.0.types[self.0.index].fields.iter().map(|field| Field {
296 name: &field.name,
297 ty: Type::from(&field.ty, &self.0.instance()),
298 })
299 }
300}
301
302impl PartialEq for Record {
303 fn eq(&self, other: &Self) -> bool {
304 self.0.equivalent(&other.0, TypeChecker::records_equal)
305 }
306}
307
308impl Eq for Record {}
309
310#[derive(Clone, Debug)]
312pub struct Tuple(Handle<TypeTupleIndex>);
313
314impl Tuple {
315 pub(crate) fn from(index: TypeTupleIndex, ty: &InstanceType<'_>) -> Self {
316 Tuple(Handle::new(index, ty))
317 }
318
319 pub fn types(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
321 self.0.types[self.0.index]
322 .types
323 .iter()
324 .map(|ty| Type::from(ty, &self.0.instance()))
325 }
326}
327
328impl PartialEq for Tuple {
329 fn eq(&self, other: &Self) -> bool {
330 self.0.equivalent(&other.0, TypeChecker::tuples_equal)
331 }
332}
333
334impl Eq for Tuple {}
335
336pub struct Case<'a> {
338 pub name: &'a str,
340 pub ty: Option<Type>,
342}
343
344#[derive(Clone, Debug)]
346pub struct Variant(Handle<TypeVariantIndex>);
347
348impl Variant {
349 pub(crate) fn from(index: TypeVariantIndex, ty: &InstanceType<'_>) -> Self {
350 Variant(Handle::new(index, ty))
351 }
352
353 pub fn cases(&self) -> impl ExactSizeIterator<Item = Case> {
355 self.0.types[self.0.index]
356 .cases
357 .iter()
358 .map(|(name, ty)| Case {
359 name: name,
360 ty: ty.as_ref().map(|ty| Type::from(ty, &self.0.instance())),
361 })
362 }
363}
364
365impl PartialEq for Variant {
366 fn eq(&self, other: &Self) -> bool {
367 self.0.equivalent(&other.0, TypeChecker::variants_equal)
368 }
369}
370
371impl Eq for Variant {}
372
373#[derive(Clone, Debug)]
375pub struct Enum(Handle<TypeEnumIndex>);
376
377impl Enum {
378 pub(crate) fn from(index: TypeEnumIndex, ty: &InstanceType<'_>) -> Self {
379 Enum(Handle::new(index, ty))
380 }
381
382 pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
384 self.0.types[self.0.index]
385 .names
386 .iter()
387 .map(|name| name.deref())
388 }
389}
390
391impl PartialEq for Enum {
392 fn eq(&self, other: &Self) -> bool {
393 self.0.equivalent(&other.0, TypeChecker::enums_equal)
394 }
395}
396
397impl Eq for Enum {}
398
399#[derive(Clone, Debug)]
401pub struct OptionType(Handle<TypeOptionIndex>);
402
403impl OptionType {
404 pub(crate) fn from(index: TypeOptionIndex, ty: &InstanceType<'_>) -> Self {
405 OptionType(Handle::new(index, ty))
406 }
407
408 pub fn ty(&self) -> Type {
410 Type::from(&self.0.types[self.0.index].ty, &self.0.instance())
411 }
412}
413
414impl PartialEq for OptionType {
415 fn eq(&self, other: &Self) -> bool {
416 self.0.equivalent(&other.0, TypeChecker::options_equal)
417 }
418}
419
420impl Eq for OptionType {}
421
422#[derive(Clone, Debug)]
424pub struct ResultType(Handle<TypeResultIndex>);
425
426impl ResultType {
427 pub(crate) fn from(index: TypeResultIndex, ty: &InstanceType<'_>) -> Self {
428 ResultType(Handle::new(index, ty))
429 }
430
431 pub fn ok(&self) -> Option<Type> {
433 Some(Type::from(
434 self.0.types[self.0.index].ok.as_ref()?,
435 &self.0.instance(),
436 ))
437 }
438
439 pub fn err(&self) -> Option<Type> {
441 Some(Type::from(
442 self.0.types[self.0.index].err.as_ref()?,
443 &self.0.instance(),
444 ))
445 }
446}
447
448impl PartialEq for ResultType {
449 fn eq(&self, other: &Self) -> bool {
450 self.0.equivalent(&other.0, TypeChecker::results_equal)
451 }
452}
453
454impl Eq for ResultType {}
455
456#[derive(Clone, Debug)]
458pub struct Flags(Handle<TypeFlagsIndex>);
459
460impl Flags {
461 pub(crate) fn from(index: TypeFlagsIndex, ty: &InstanceType<'_>) -> Self {
462 Flags(Handle::new(index, ty))
463 }
464
465 pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
467 self.0.types[self.0.index]
468 .names
469 .iter()
470 .map(|name| name.deref())
471 }
472}
473
474impl PartialEq for Flags {
475 fn eq(&self, other: &Self) -> bool {
476 self.0.equivalent(&other.0, TypeChecker::flags_equal)
477 }
478}
479
480impl Eq for Flags {}
481
482#[derive(Clone, PartialEq, Eq, Debug)]
484#[allow(missing_docs)]
485pub enum Type {
486 Bool,
487 S8,
488 U8,
489 S16,
490 U16,
491 S32,
492 U32,
493 S64,
494 U64,
495 Float32,
496 Float64,
497 Char,
498 String,
499 List(List),
500 Record(Record),
501 Tuple(Tuple),
502 Variant(Variant),
503 Enum(Enum),
504 Option(OptionType),
505 Result(ResultType),
506 Flags(Flags),
507 Own(ResourceType),
508 Borrow(ResourceType),
509}
510
511impl Type {
512 pub fn unwrap_list(&self) -> &List {
518 if let Type::List(handle) = self {
519 &handle
520 } else {
521 panic!("attempted to unwrap a {} as a list", self.desc())
522 }
523 }
524
525 pub fn unwrap_record(&self) -> &Record {
531 if let Type::Record(handle) = self {
532 &handle
533 } else {
534 panic!("attempted to unwrap a {} as a record", self.desc())
535 }
536 }
537
538 pub fn unwrap_tuple(&self) -> &Tuple {
544 if let Type::Tuple(handle) = self {
545 &handle
546 } else {
547 panic!("attempted to unwrap a {} as a tuple", self.desc())
548 }
549 }
550
551 pub fn unwrap_variant(&self) -> &Variant {
557 if let Type::Variant(handle) = self {
558 &handle
559 } else {
560 panic!("attempted to unwrap a {} as a variant", self.desc())
561 }
562 }
563
564 pub fn unwrap_enum(&self) -> &Enum {
570 if let Type::Enum(handle) = self {
571 &handle
572 } else {
573 panic!("attempted to unwrap a {} as a enum", self.desc())
574 }
575 }
576
577 pub fn unwrap_option(&self) -> &OptionType {
583 if let Type::Option(handle) = self {
584 &handle
585 } else {
586 panic!("attempted to unwrap a {} as a option", self.desc())
587 }
588 }
589
590 pub fn unwrap_result(&self) -> &ResultType {
596 if let Type::Result(handle) = self {
597 &handle
598 } else {
599 panic!("attempted to unwrap a {} as a result", self.desc())
600 }
601 }
602
603 pub fn unwrap_flags(&self) -> &Flags {
609 if let Type::Flags(handle) = self {
610 &handle
611 } else {
612 panic!("attempted to unwrap a {} as a flags", self.desc())
613 }
614 }
615
616 pub fn unwrap_own(&self) -> &ResourceType {
622 match self {
623 Type::Own(ty) => ty,
624 _ => panic!("attempted to unwrap a {} as a own", self.desc()),
625 }
626 }
627
628 pub fn unwrap_borrow(&self) -> &ResourceType {
634 match self {
635 Type::Borrow(ty) => ty,
636 _ => panic!("attempted to unwrap a {} as a own", self.desc()),
637 }
638 }
639
640 pub(crate) fn from(ty: &InterfaceType, instance: &InstanceType<'_>) -> Self {
642 match ty {
643 InterfaceType::Bool => Type::Bool,
644 InterfaceType::S8 => Type::S8,
645 InterfaceType::U8 => Type::U8,
646 InterfaceType::S16 => Type::S16,
647 InterfaceType::U16 => Type::U16,
648 InterfaceType::S32 => Type::S32,
649 InterfaceType::U32 => Type::U32,
650 InterfaceType::S64 => Type::S64,
651 InterfaceType::U64 => Type::U64,
652 InterfaceType::Float32 => Type::Float32,
653 InterfaceType::Float64 => Type::Float64,
654 InterfaceType::Char => Type::Char,
655 InterfaceType::String => Type::String,
656 InterfaceType::List(index) => Type::List(List::from(*index, instance)),
657 InterfaceType::Record(index) => Type::Record(Record::from(*index, instance)),
658 InterfaceType::Tuple(index) => Type::Tuple(Tuple::from(*index, instance)),
659 InterfaceType::Variant(index) => Type::Variant(Variant::from(*index, instance)),
660 InterfaceType::Enum(index) => Type::Enum(Enum::from(*index, instance)),
661 InterfaceType::Option(index) => Type::Option(OptionType::from(*index, instance)),
662 InterfaceType::Result(index) => Type::Result(ResultType::from(*index, instance)),
663 InterfaceType::Flags(index) => Type::Flags(Flags::from(*index, instance)),
664 InterfaceType::Own(index) => Type::Own(instance.resource_type(*index)),
665 InterfaceType::Borrow(index) => Type::Borrow(instance.resource_type(*index)),
666 InterfaceType::Future(_)
667 | InterfaceType::Stream(_)
668 | InterfaceType::ErrorContext(_) => todo!(),
669 }
670 }
671
672 fn desc(&self) -> &'static str {
673 match self {
674 Type::Bool => "bool",
675 Type::S8 => "s8",
676 Type::U8 => "u8",
677 Type::S16 => "s16",
678 Type::U16 => "u16",
679 Type::S32 => "s32",
680 Type::U32 => "u32",
681 Type::S64 => "s64",
682 Type::U64 => "u64",
683 Type::Float32 => "float32",
684 Type::Float64 => "float64",
685 Type::Char => "char",
686 Type::String => "string",
687 Type::List(_) => "list",
688 Type::Record(_) => "record",
689 Type::Tuple(_) => "tuple",
690 Type::Variant(_) => "variant",
691 Type::Enum(_) => "enum",
692 Type::Option(_) => "option",
693 Type::Result(_) => "result",
694 Type::Flags(_) => "flags",
695 Type::Own(_) => "own",
696 Type::Borrow(_) => "borrow",
697 }
698 }
699}
700
701#[derive(Clone, Debug)]
703pub struct ComponentFunc(Handle<TypeFuncIndex>);
704
705impl ComponentFunc {
706 pub(crate) fn from(index: TypeFuncIndex, ty: &InstanceType<'_>) -> Self {
707 Self(Handle::new(index, ty))
708 }
709
710 pub fn params(&self) -> impl ExactSizeIterator<Item = (&str, Type)> + '_ {
712 let ty = &self.0.types[self.0.index];
713 self.0.types[ty.params]
714 .types
715 .iter()
716 .zip(&ty.param_names)
717 .map(|(ty, name)| (name.as_str(), Type::from(ty, &self.0.instance())))
718 }
719
720 pub fn results(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
722 let results = self.0.types[self.0.index].results;
723 self.0.types[results]
724 .types
725 .iter()
726 .map(|ty| Type::from(ty, &self.0.instance()))
727 }
728}
729
730#[derive(Clone, Debug)]
732pub struct Module(Handle<TypeModuleIndex>);
733
734impl Module {
735 pub(crate) fn from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self {
736 Self(Handle::new(index, ty))
737 }
738
739 pub fn imports<'a>(
741 &'a self,
742 engine: &'a Engine,
743 ) -> impl ExactSizeIterator<Item = ((&'a str, &'a str), ExternType)> + 'a {
744 self.0.types[self.0.index]
745 .imports
746 .iter()
747 .map(|((namespace, name), ty)| {
748 (
749 (namespace.as_str(), name.as_str()),
750 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
751 )
752 })
753 }
754
755 pub fn exports<'a>(
757 &'a self,
758 engine: &'a Engine,
759 ) -> impl ExactSizeIterator<Item = (&'a str, ExternType)> + 'a {
760 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
761 (
762 name.as_str(),
763 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
764 )
765 })
766 }
767}
768
769#[derive(Clone, Debug)]
771pub struct Component(Handle<TypeComponentIndex>);
772
773impl Component {
774 pub(crate) fn from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self {
775 Self(Handle::new(index, ty))
776 }
777
778 pub fn get_import(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
780 self.0.types[self.0.index]
781 .imports
782 .get(name)
783 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
784 }
785
786 pub fn imports<'a>(
788 &'a self,
789 engine: &'a Engine,
790 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
791 self.0.types[self.0.index].imports.iter().map(|(name, ty)| {
792 (
793 name.as_str(),
794 ComponentItem::from(engine, ty, &self.0.instance()),
795 )
796 })
797 }
798
799 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
801 self.0.types[self.0.index]
802 .exports
803 .get(name)
804 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
805 }
806
807 pub fn exports<'a>(
809 &'a self,
810 engine: &'a Engine,
811 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
812 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
813 (
814 name.as_str(),
815 ComponentItem::from(engine, ty, &self.0.instance()),
816 )
817 })
818 }
819}
820
821#[derive(Clone, Debug)]
823pub struct ComponentInstance(Handle<TypeComponentInstanceIndex>);
824
825impl ComponentInstance {
826 pub(crate) fn from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self {
827 Self(Handle::new(index, ty))
828 }
829
830 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
832 self.0.types[self.0.index]
833 .exports
834 .get(name)
835 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
836 }
837
838 pub fn exports<'a>(
840 &'a self,
841 engine: &'a Engine,
842 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> {
843 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
844 (
845 name.as_str(),
846 ComponentItem::from(engine, ty, &self.0.instance()),
847 )
848 })
849 }
850}
851
852#[derive(Clone, Debug)]
854pub enum ComponentItem {
855 ComponentFunc(ComponentFunc),
857 CoreFunc(FuncType),
859 Module(Module),
861 Component(Component),
863 ComponentInstance(ComponentInstance),
865 Type(Type),
867 Resource(ResourceType),
869}
870
871impl ComponentItem {
872 pub(crate) fn from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self {
873 match def {
874 TypeDef::Component(idx) => Self::Component(Component::from(*idx, ty)),
875 TypeDef::ComponentInstance(idx) => {
876 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
877 }
878 TypeDef::ComponentFunc(idx) => Self::ComponentFunc(ComponentFunc::from(*idx, ty)),
879 TypeDef::Interface(iface_ty) => Self::Type(Type::from(iface_ty, ty)),
880 TypeDef::Module(idx) => Self::Module(Module::from(*idx, ty)),
881 TypeDef::CoreFunc(idx) => {
882 let subty = &ty.types[*idx];
883 Self::CoreFunc(FuncType::from_wasm_func_type(
884 engine,
885 subty.is_final,
886 subty.supertype,
887 subty.unwrap_func().clone(),
888 ))
889 }
890 TypeDef::Resource(idx) => {
891 let resource_index = ty.types[*idx].ty;
892 let ty = match ty.resources.get(resource_index) {
893 Some(ty) => *ty,
896
897 None => ResourceType::uninstantiated(&ty.types, resource_index),
899 };
900 Self::Resource(ty)
901 }
902 }
903 }
904}