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, Export, InterfaceType, ResourceIndex, TypeComponentIndex,
10 TypeComponentInstanceIndex, TypeDef, TypeEnumIndex, TypeFlagsIndex, TypeFuncIndex,
11 TypeListIndex, TypeModuleIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTableIndex,
12 TypeResultIndex, TypeTupleIndex, 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 #[doc(hidden)]
730 pub fn typecheck<Params, Return>(&self, cx: &InstanceType) -> anyhow::Result<()>
731 where
732 Params: crate::component::ComponentNamedList + crate::component::Lower,
733 Return: crate::component::ComponentNamedList + crate::component::Lift,
734 {
735 let ty = &self.0.types[self.0.index];
736 Params::typecheck(&InterfaceType::Tuple(ty.params), cx)?;
737 Return::typecheck(&InterfaceType::Tuple(ty.results), cx)?;
738 Ok(())
739 }
740}
741
742#[derive(Clone, Debug)]
744pub struct Module(Handle<TypeModuleIndex>);
745
746impl Module {
747 pub(crate) fn from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self {
748 Self(Handle::new(index, ty))
749 }
750
751 pub fn imports<'a>(
753 &'a self,
754 engine: &'a Engine,
755 ) -> impl ExactSizeIterator<Item = ((&'a str, &'a str), ExternType)> + 'a {
756 self.0.types[self.0.index]
757 .imports
758 .iter()
759 .map(|((namespace, name), ty)| {
760 (
761 (namespace.as_str(), name.as_str()),
762 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
763 )
764 })
765 }
766
767 pub fn exports<'a>(
769 &'a self,
770 engine: &'a Engine,
771 ) -> impl ExactSizeIterator<Item = (&'a str, ExternType)> + 'a {
772 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
773 (
774 name.as_str(),
775 ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
776 )
777 })
778 }
779}
780
781#[derive(Clone, Debug)]
783pub struct Component(Handle<TypeComponentIndex>);
784
785impl Component {
786 pub(crate) fn from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self {
787 Self(Handle::new(index, ty))
788 }
789
790 pub fn get_import(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
792 self.0.types[self.0.index]
793 .imports
794 .get(name)
795 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
796 }
797
798 pub fn imports<'a>(
800 &'a self,
801 engine: &'a Engine,
802 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
803 self.0.types[self.0.index].imports.iter().map(|(name, ty)| {
804 (
805 name.as_str(),
806 ComponentItem::from(engine, ty, &self.0.instance()),
807 )
808 })
809 }
810
811 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
813 self.0.types[self.0.index]
814 .exports
815 .get(name)
816 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
817 }
818
819 pub fn exports<'a>(
821 &'a self,
822 engine: &'a Engine,
823 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
824 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
825 (
826 name.as_str(),
827 ComponentItem::from(engine, ty, &self.0.instance()),
828 )
829 })
830 }
831
832 #[doc(hidden)]
833 pub fn instance_type(&self) -> InstanceType<'_> {
834 InstanceType {
835 types: &self.0.types,
836 resources: &self.0.resources,
837 }
838 }
839}
840
841#[derive(Clone, Debug)]
843pub struct ComponentInstance(Handle<TypeComponentInstanceIndex>);
844
845impl ComponentInstance {
846 pub(crate) fn from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self {
847 Self(Handle::new(index, ty))
848 }
849
850 pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
852 self.0.types[self.0.index]
853 .exports
854 .get(name)
855 .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
856 }
857
858 pub fn exports<'a>(
860 &'a self,
861 engine: &'a Engine,
862 ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> {
863 self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
864 (
865 name.as_str(),
866 ComponentItem::from(engine, ty, &self.0.instance()),
867 )
868 })
869 }
870}
871
872#[derive(Clone, Debug)]
874pub enum ComponentItem {
875 ComponentFunc(ComponentFunc),
877 CoreFunc(FuncType),
879 Module(Module),
881 Component(Component),
883 ComponentInstance(ComponentInstance),
885 Type(Type),
887 Resource(ResourceType),
889}
890
891impl ComponentItem {
892 pub(crate) fn from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self {
893 match def {
894 TypeDef::Component(idx) => Self::Component(Component::from(*idx, ty)),
895 TypeDef::ComponentInstance(idx) => {
896 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
897 }
898 TypeDef::ComponentFunc(idx) => Self::ComponentFunc(ComponentFunc::from(*idx, ty)),
899 TypeDef::Interface(iface_ty) => Self::Type(Type::from(iface_ty, ty)),
900 TypeDef::Module(idx) => Self::Module(Module::from(*idx, ty)),
901 TypeDef::CoreFunc(idx) => {
902 let subty = &ty.types[*idx];
903 Self::CoreFunc(FuncType::from_wasm_func_type(
904 engine,
905 subty.is_final,
906 subty.supertype,
907 subty.unwrap_func().clone(),
908 ))
909 }
910 TypeDef::Resource(idx) => {
911 let resource_index = ty.types[*idx].ty;
912 let ty = match ty.resources.get(resource_index) {
913 Some(ty) => *ty,
916
917 None => ResourceType::uninstantiated(&ty.types, resource_index),
919 };
920 Self::Resource(ty)
921 }
922 }
923 }
924 pub(crate) fn from_export(engine: &Engine, export: &Export, ty: &InstanceType<'_>) -> Self {
925 match export {
926 Export::Instance { ty: idx, .. } => {
927 Self::ComponentInstance(ComponentInstance::from(*idx, ty))
928 }
929 Export::LiftedFunction { ty: idx, .. } => {
930 Self::ComponentFunc(ComponentFunc::from(*idx, ty))
931 }
932 Export::ModuleStatic { ty: idx, .. } | Export::ModuleImport { ty: idx, .. } => {
933 Self::Module(Module::from(*idx, ty))
934 }
935 Export::Type(idx) => Self::from(engine, idx, ty),
936 }
937 }
938}