1use crate::component::matching::InstanceType;
4use crate::{Engine, ExternType, FuncType};
5use std::fmt;
6use std::ops::Deref;
7use std::sync::Arc;
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 }
149 }
150
151 fn lists_equal(&self, l1: TypeListIndex, l2: TypeListIndex) -> bool {
152 let a = &self.a_types[l1];
153 let b = &self.b_types[l2];
154 self.interface_types_equal(a.element, b.element)
155 }
156
157 fn resources_equal(&self, o1: TypeResourceTableIndex, o2: TypeResourceTableIndex) -> bool {
158 let a = &self.a_types[o1];
159 let b = &self.b_types[o2];
160 self.a_resource[a.ty] == self.b_resource[b.ty]
161 }
162
163 fn records_equal(&self, r1: TypeRecordIndex, r2: TypeRecordIndex) -> bool {
164 let a = &self.a_types[r1];
165 let b = &self.b_types[r2];
166 if a.fields.len() != b.fields.len() {
167 return false;
168 }
169 a.fields
170 .iter()
171 .zip(b.fields.iter())
172 .all(|(a_field, b_field)| {
173 a_field.name == b_field.name && self.interface_types_equal(a_field.ty, b_field.ty)
174 })
175 }
176
177 fn variants_equal(&self, v1: TypeVariantIndex, v2: TypeVariantIndex) -> bool {
178 let a = &self.a_types[v1];
179 let b = &self.b_types[v2];
180 if a.cases.len() != b.cases.len() {
181 return false;
182 }
183 a.cases
184 .iter()
185 .zip(b.cases.iter())
186 .all(|((a_name, a_ty), (b_name, b_ty))| {
187 if a_name != b_name {
188 return false;
189 }
190 match (a_ty, b_ty) {
191 (Some(a_case_ty), Some(b_case_ty)) => {
192 self.interface_types_equal(*a_case_ty, *b_case_ty)
193 }
194 (None, None) => true,
195 _ => false,
196 }
197 })
198 }
199
200 fn results_equal(&self, r1: TypeResultIndex, r2: TypeResultIndex) -> bool {
201 let a = &self.a_types[r1];
202 let b = &self.b_types[r2];
203 let oks = match (a.ok, b.ok) {
204 (Some(ok1), Some(ok2)) => self.interface_types_equal(ok1, ok2),
205 (None, None) => true,
206 _ => false,
207 };
208 if !oks {
209 return false;
210 }
211 match (a.err, b.err) {
212 (Some(err1), Some(err2)) => self.interface_types_equal(err1, err2),
213 (None, None) => true,
214 _ => false,
215 }
216 }
217
218 fn options_equal(&self, o1: TypeOptionIndex, o2: TypeOptionIndex) -> bool {
219 let a = &self.a_types[o1];
220 let b = &self.b_types[o2];
221 self.interface_types_equal(a.ty, b.ty)
222 }
223
224 fn enums_equal(&self, e1: TypeEnumIndex, e2: TypeEnumIndex) -> bool {
225 let a = &self.a_types[e1];
226 let b = &self.b_types[e2];
227 a.names == b.names
228 }
229
230 fn tuples_equal(&self, t1: TypeTupleIndex, t2: TypeTupleIndex) -> bool {
231 let a = &self.a_types[t1];
232 let b = &self.b_types[t2];
233 if a.types.len() != b.types.len() {
234 return false;
235 }
236 a.types
237 .iter()
238 .zip(b.types.iter())
239 .all(|(&a, &b)| self.interface_types_equal(a, b))
240 }
241
242 fn flags_equal(&self, f1: TypeFlagsIndex, f2: TypeFlagsIndex) -> bool {
243 let a = &self.a_types[f1];
244 let b = &self.b_types[f2];
245 a.names == b.names
246 }
247}
248
249#[derive(Clone, Debug)]
251pub struct List(Handle<TypeListIndex>);
252
253impl PartialEq for List {
254 fn eq(&self, other: &Self) -> bool {
255 self.0.equivalent(&other.0, TypeChecker::lists_equal)
256 }
257}
258
259impl Eq for List {}
260
261impl List {
262 pub(crate) fn from(index: TypeListIndex, ty: &InstanceType<'_>) -> Self {
263 List(Handle::new(index, ty))
264 }
265
266 pub fn ty(&self) -> Type {
268 Type::from(&self.0.types[self.0.index].element, &self.0.instance())
269 }
270}
271
272#[derive(Debug)]
274pub struct Field<'a> {
275 pub name: &'a str,
277 pub ty: Type,
279}
280
281#[derive(Clone, Debug)]
283pub struct Record(Handle<TypeRecordIndex>);
284
285impl Record {
286 pub(crate) fn from(index: TypeRecordIndex, ty: &InstanceType<'_>) -> Self {
287 Record(Handle::new(index, ty))
288 }
289
290 pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> {
292 self.0.types[self.0.index].fields.iter().map(|field| Field {
293 name: &field.name,
294 ty: Type::from(&field.ty, &self.0.instance()),
295 })
296 }
297}
298
299impl PartialEq for Record {
300 fn eq(&self, other: &Self) -> bool {
301 self.0.equivalent(&other.0, TypeChecker::records_equal)
302 }
303}
304
305impl Eq for Record {}
306
307#[derive(Clone, Debug)]
309pub struct Tuple(Handle<TypeTupleIndex>);
310
311impl Tuple {
312 pub(crate) fn from(index: TypeTupleIndex, ty: &InstanceType<'_>) -> Self {
313 Tuple(Handle::new(index, ty))
314 }
315
316 pub fn types(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
318 self.0.types[self.0.index]
319 .types
320 .iter()
321 .map(|ty| Type::from(ty, &self.0.instance()))
322 }
323}
324
325impl PartialEq for Tuple {
326 fn eq(&self, other: &Self) -> bool {
327 self.0.equivalent(&other.0, TypeChecker::tuples_equal)
328 }
329}
330
331impl Eq for Tuple {}
332
333pub struct Case<'a> {
335 pub name: &'a str,
337 pub ty: Option<Type>,
339}
340
341#[derive(Clone, Debug)]
343pub struct Variant(Handle<TypeVariantIndex>);
344
345impl Variant {
346 pub(crate) fn from(index: TypeVariantIndex, ty: &InstanceType<'_>) -> Self {
347 Variant(Handle::new(index, ty))
348 }
349
350 pub fn cases(&self) -> impl ExactSizeIterator<Item = Case> {
352 self.0.types[self.0.index]
353 .cases
354 .iter()
355 .map(|(name, ty)| Case {
356 name: name,
357 ty: ty.as_ref().map(|ty| Type::from(ty, &self.0.instance())),
358 })
359 }
360}
361
362impl PartialEq for Variant {
363 fn eq(&self, other: &Self) -> bool {
364 self.0.equivalent(&other.0, TypeChecker::variants_equal)
365 }
366}
367
368impl Eq for Variant {}
369
370#[derive(Clone, Debug)]
372pub struct Enum(Handle<TypeEnumIndex>);
373
374impl Enum {
375 pub(crate) fn from(index: TypeEnumIndex, ty: &InstanceType<'_>) -> Self {
376 Enum(Handle::new(index, ty))
377 }
378
379 pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
381 self.0.types[self.0.index]
382 .names
383 .iter()
384 .map(|name| name.deref())
385 }
386}
387
388impl PartialEq for Enum {
389 fn eq(&self, other: &Self) -> bool {
390 self.0.equivalent(&other.0, TypeChecker::enums_equal)
391 }
392}
393
394impl Eq for Enum {}
395
396#[derive(Clone, Debug)]
398pub struct OptionType(Handle<TypeOptionIndex>);
399
400impl OptionType {
401 pub(crate) fn from(index: TypeOptionIndex, ty: &InstanceType<'_>) -> Self {
402 OptionType(Handle::new(index, ty))
403 }
404
405 pub fn ty(&self) -> Type {
407 Type::from(&self.0.types[self.0.index].ty, &self.0.instance())
408 }
409}
410
411impl PartialEq for OptionType {
412 fn eq(&self, other: &Self) -> bool {
413 self.0.equivalent(&other.0, TypeChecker::options_equal)
414 }
415}
416
417impl Eq for OptionType {}
418
419#[derive(Clone, Debug)]
421pub struct ResultType(Handle<TypeResultIndex>);
422
423impl ResultType {
424 pub(crate) fn from(index: TypeResultIndex, ty: &InstanceType<'_>) -> Self {
425 ResultType(Handle::new(index, ty))
426 }
427
428 pub fn ok(&self) -> Option<Type> {
430 Some(Type::from(
431 self.0.types[self.0.index].ok.as_ref()?,
432 &self.0.instance(),
433 ))
434 }
435
436 pub fn err(&self) -> Option<Type> {
438 Some(Type::from(
439 self.0.types[self.0.index].err.as_ref()?,
440 &self.0.instance(),
441 ))
442 }
443}
444
445impl PartialEq for ResultType {
446 fn eq(&self, other: &Self) -> bool {
447 self.0.equivalent(&other.0, TypeChecker::results_equal)
448 }
449}
450
451impl Eq for ResultType {}
452
453#[derive(Clone, Debug)]
455pub struct Flags(Handle<TypeFlagsIndex>);
456
457impl Flags {
458 pub(crate) fn from(index: TypeFlagsIndex, ty: &InstanceType<'_>) -> Self {
459 Flags(Handle::new(index, ty))
460 }
461
462 pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
464 self.0.types[self.0.index]
465 .names
466 .iter()
467 .map(|name| name.deref())
468 }
469}
470
471impl PartialEq for Flags {
472 fn eq(&self, other: &Self) -> bool {
473 self.0.equivalent(&other.0, TypeChecker::flags_equal)
474 }
475}
476
477impl Eq for Flags {}
478
479#[derive(Clone, PartialEq, Eq, Debug)]
481#[allow(missing_docs)]
482pub enum Type {
483 Bool,
484 S8,
485 U8,
486 S16,
487 U16,
488 S32,
489 U32,
490 S64,
491 U64,
492 Float32,
493 Float64,
494 Char,
495 String,
496 List(List),
497 Record(Record),
498 Tuple(Tuple),
499 Variant(Variant),
500 Enum(Enum),
501 Option(OptionType),
502 Result(ResultType),
503 Flags(Flags),
504 Own(ResourceType),
505 Borrow(ResourceType),
506}
507
508impl Type {
509 pub fn unwrap_list(&self) -> &List {
515 if let Type::List(handle) = self {
516 &handle
517 } else {
518 panic!("attempted to unwrap a {} as a list", self.desc())
519 }
520 }
521
522 pub fn unwrap_record(&self) -> &Record {
528 if let Type::Record(handle) = self {
529 &handle
530 } else {
531 panic!("attempted to unwrap a {} as a record", self.desc())
532 }
533 }
534
535 pub fn unwrap_tuple(&self) -> &Tuple {
541 if let Type::Tuple(handle) = self {
542 &handle
543 } else {
544 panic!("attempted to unwrap a {} as a tuple", self.desc())
545 }
546 }
547
548 pub fn unwrap_variant(&self) -> &Variant {
554 if let Type::Variant(handle) = self {
555 &handle
556 } else {
557 panic!("attempted to unwrap a {} as a variant", self.desc())
558 }
559 }
560
561 pub fn unwrap_enum(&self) -> &Enum {
567 if let Type::Enum(handle) = self {
568 &handle
569 } else {
570 panic!("attempted to unwrap a {} as a enum", self.desc())
571 }
572 }
573
574 pub fn unwrap_option(&self) -> &OptionType {
580 if let Type::Option(handle) = self {
581 &handle
582 } else {
583 panic!("attempted to unwrap a {} as a option", self.desc())
584 }
585 }
586
587 pub fn unwrap_result(&self) -> &ResultType {
593 if let Type::Result(handle) = self {
594 &handle
595 } else {
596 panic!("attempted to unwrap a {} as a result", self.desc())
597 }
598 }
599
600 pub fn unwrap_flags(&self) -> &Flags {
606 if let Type::Flags(handle) = self {
607 &handle
608 } else {
609 panic!("attempted to unwrap a {} as a flags", self.desc())
610 }
611 }
612
613 pub fn unwrap_own(&self) -> &ResourceType {
619 match self {
620 Type::Own(ty) => ty,
621 _ => panic!("attempted to unwrap a {} as a own", self.desc()),
622 }
623 }
624
625 pub fn unwrap_borrow(&self) -> &ResourceType {
631 match self {
632 Type::Borrow(ty) => ty,
633 _ => panic!("attempted to unwrap a {} as a own", self.desc()),
634 }
635 }
636
637 pub(crate) fn from(ty: &InterfaceType, instance: &InstanceType<'_>) -> Self {
639 match ty {
640 InterfaceType::Bool => Type::Bool,
641 InterfaceType::S8 => Type::S8,
642 InterfaceType::U8 => Type::U8,
643 InterfaceType::S16 => Type::S16,
644 InterfaceType::U16 => Type::U16,
645 InterfaceType::S32 => Type::S32,
646 InterfaceType::U32 => Type::U32,
647 InterfaceType::S64 => Type::S64,
648 InterfaceType::U64 => Type::U64,
649 InterfaceType::Float32 => Type::Float32,
650 InterfaceType::Float64 => Type::Float64,
651 InterfaceType::Char => Type::Char,
652 InterfaceType::String => Type::String,
653 InterfaceType::List(index) => Type::List(List::from(*index, instance)),
654 InterfaceType::Record(index) => Type::Record(Record::from(*index, instance)),
655 InterfaceType::Tuple(index) => Type::Tuple(Tuple::from(*index, instance)),
656 InterfaceType::Variant(index) => Type::Variant(Variant::from(*index, instance)),
657 InterfaceType::Enum(index) => Type::Enum(Enum::from(*index, instance)),
658 InterfaceType::Option(index) => Type::Option(OptionType::from(*index, instance)),
659 InterfaceType::Result(index) => Type::Result(ResultType::from(*index, instance)),
660 InterfaceType::Flags(index) => Type::Flags(Flags::from(*index, instance)),
661 InterfaceType::Own(index) => Type::Own(instance.resource_type(*index)),
662 InterfaceType::Borrow(index) => Type::Borrow(instance.resource_type(*index)),
663 }
664 }
665
666 fn desc(&self) -> &'static str {
667 match self {
668 Type::Bool => "bool",
669 Type::S8 => "s8",
670 Type::U8 => "u8",
671 Type::S16 => "s16",
672 Type::U16 => "u16",
673 Type::S32 => "s32",
674 Type::U32 => "u32",
675 Type::S64 => "s64",
676 Type::U64 => "u64",
677 Type::Float32 => "float32",
678 Type::Float64 => "float64",
679 Type::Char => "char",
680 Type::String => "string",
681 Type::List(_) => "list",
682 Type::Record(_) => "record",
683 Type::Tuple(_) => "tuple",
684 Type::Variant(_) => "variant",
685 Type::Enum(_) => "enum",
686 Type::Option(_) => "option",
687 Type::Result(_) => "result",
688 Type::Flags(_) => "flags",
689 Type::Own(_) => "own",
690 Type::Borrow(_) => "borrow",
691 }
692 }
693}
694
695#[derive(Clone, Debug)]
697pub struct ComponentFunc(Handle<TypeFuncIndex>);
698
699impl ComponentFunc {
700 pub(crate) fn from(index: TypeFuncIndex, ty: &InstanceType<'_>) -> Self {
701 Self(Handle::new(index, ty))
702 }
703
704 pub fn params(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
706 let params = self.0.types[self.0.index].params;
707 self.0.types[params]
708 .types
709 .iter()
710 .map(|ty| Type::from(ty, &self.0.instance()))
711 }
712
713 pub fn results(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
715 let results = self.0.types[self.0.index].results;
716 self.0.types[results]
717 .types
718 .iter()
719 .map(|ty| Type::from(ty, &self.0.instance()))
720 }
721}
722
723#[derive(Clone, Debug)]
725pub struct Module(Handle<TypeModuleIndex>);
726
727impl Module {
728 pub(crate) fn from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self {
729 Self(Handle::new(index, ty))
730 }
731
732 pub fn imports<'a>(
734 &'a self,
735 engine: &'a Engine,
736 ) -> impl ExactSizeIterator<Item = ((&str, &str), ExternType)> + 'a {
737 self.0.types[self.0.index]
738 .imports
739 .iter()
740 .map(|((namespace, name), ty)| {
741 (
742 (namespace.as_str(), name.as_str()),
743 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
744 )
745 })
746 }
747
748 pub fn exports<'a>(
750 &'a self,
751 engine: &'a Engine,
752 ) -> impl ExactSizeIterator<Item = (&str, ExternType)> + 'a {
753 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
754 (
755 name.as_str(),
756 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
757 )
758 })
759 }
760}
761
762#[derive(Clone, Debug)]
764pub struct Component(Handle<TypeComponentIndex>);
765
766impl Component {
767 pub(crate) fn from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self {
768 Self(Handle::new(index, ty))
769 }
770
771 pub fn get_import(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
773 self.0.types[self.0.index]
774 .imports
775 .get(name)
776 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
777 }
778
779 pub fn imports<'a>(
781 &'a self,
782 engine: &'a Engine,
783 ) -> impl ExactSizeIterator<Item = (&str, ComponentItem)> + 'a {
784 self.0.types[self.0.index].imports.iter().map(|(name, ty)| {
785 (
786 name.as_str(),
787 ComponentItem::from(engine, ty, &self.0.instance()),
788 )
789 })
790 }
791
792 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
794 self.0.types[self.0.index]
795 .exports
796 .get(name)
797 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
798 }
799
800 pub fn exports<'a>(
802 &'a self,
803 engine: &'a Engine,
804 ) -> impl ExactSizeIterator<Item = (&str, ComponentItem)> + 'a {
805 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
806 (
807 name.as_str(),
808 ComponentItem::from(engine, ty, &self.0.instance()),
809 )
810 })
811 }
812}
813
814#[derive(Clone, Debug)]
816pub struct ComponentInstance(Handle<TypeComponentInstanceIndex>);
817
818impl ComponentInstance {
819 pub(crate) fn from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self {
820 Self(Handle::new(index, ty))
821 }
822
823 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
825 self.0.types[self.0.index]
826 .exports
827 .get(name)
828 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
829 }
830
831 pub fn exports<'a>(
833 &'a self,
834 engine: &'a Engine,
835 ) -> impl ExactSizeIterator<Item = (&str, ComponentItem)> {
836 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
837 (
838 name.as_str(),
839 ComponentItem::from(engine, ty, &self.0.instance()),
840 )
841 })
842 }
843}
844
845#[derive(Clone, Debug)]
847pub enum ComponentItem {
848 ComponentFunc(ComponentFunc),
850 CoreFunc(FuncType),
852 Module(Module),
854 Component(Component),
856 ComponentInstance(ComponentInstance),
858 Type(Type),
860 Resource(ResourceType),
862}
863
864impl ComponentItem {
865 pub(crate) fn from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self {
866 match def {
867 TypeDef::Component(idx) => Self::Component(Component::from(*idx, ty)),
868 TypeDef::ComponentInstance(idx) => {
869 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
870 }
871 TypeDef::ComponentFunc(idx) => Self::ComponentFunc(ComponentFunc::from(*idx, ty)),
872 TypeDef::Interface(iface_ty) => Self::Type(Type::from(iface_ty, ty)),
873 TypeDef::Module(idx) => Self::Module(Module::from(*idx, ty)),
874 TypeDef::CoreFunc(idx) => Self::CoreFunc(FuncType::from_wasm_func_type(
875 engine,
876 ty.types[*idx].clone(),
877 )),
878 TypeDef::Resource(idx) => {
879 let resource_index = ty.types[*idx].ty;
880 let ty = match ty.resources.get(resource_index) {
881 Some(ty) => *ty,
884
885 None => ResourceType::uninstantiated(&ty.types, resource_index),
887 };
888 Self::Resource(ty)
889 }
890 }
891 }
892}