wasmtime/runtime/component/
types.rs

1//! This module defines the `Type` type, representing the dynamic form of a component interface type.
2
3use 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/// An owned and `'static` handle for type information in a component.
19///
20/// The components here are:
21///
22/// * `index` - a `TypeFooIndex` defined in the `wasmtime_environ` crate. This
23///   then points into the next field of...
24///
25/// * `types` - this is an allocation originally created from compilation and is
26///   stored in a compiled `Component`. This contains all types necessary and
27///   information about recursive structures and all other type information
28///   within the component. The above `index` points into this structure.
29///
30/// * `resources` - this is used to "close the loop" and represent a concrete
31///   instance type rather than an abstract component type. Instantiating a
32///   component with different resources produces different instance types but
33///   the same underlying component type, so this field serves the purpose to
34///   distinguish instance types from one another. This is runtime state created
35///   during instantiation and threaded through here.
36#[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
91/// Type checker between two `Handle`s
92struct 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/// A `list` interface type
253#[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    /// Retrieve the element type of this `list`.
270    pub fn ty(&self) -> Type {
271        Type::from(&self.0.types[self.0.index].element, &self.0.instance())
272    }
273}
274
275/// A field declaration belonging to a `record`
276#[derive(Debug)]
277pub struct Field<'a> {
278    /// The name of the field
279    pub name: &'a str,
280    /// The type of the field
281    pub ty: Type,
282}
283
284/// A `record` interface type
285#[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    /// Retrieve the fields of this `record` in declaration order.
294    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/// A `tuple` interface type
311#[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    /// Retrieve the types of the fields of this `tuple` in declaration order.
320    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
336/// A case declaration belonging to a `variant`
337pub struct Case<'a> {
338    /// The name of the case
339    pub name: &'a str,
340    /// The optional payload type of the case
341    pub ty: Option<Type>,
342}
343
344/// A `variant` interface type
345#[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    /// Retrieve the cases of this `variant` in declaration order.
354    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/// An `enum` interface type
374#[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    /// Retrieve the names of the cases of this `enum` in declaration order.
383    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/// An `option` interface type
400#[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    /// Retrieve the type parameter for this `option`.
409    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/// An `expected` interface type
423#[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    /// Retrieve the `ok` type parameter for this `result`.
432    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    /// Retrieve the `err` type parameter for this `result`.
440    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/// A `flags` interface type
457#[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    /// Retrieve the names of the flags of this `flags` type in declaration order.
466    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/// Represents a component model interface type
483#[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    /// Retrieve the inner [`List`] of a [`Type::List`].
513    ///
514    /// # Panics
515    ///
516    /// This will panic if `self` is not a [`Type::List`].
517    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    /// Retrieve the inner [`Record`] of a [`Type::Record`].
526    ///
527    /// # Panics
528    ///
529    /// This will panic if `self` is not a [`Type::Record`].
530    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    /// Retrieve the inner [`Tuple`] of a [`Type::Tuple`].
539    ///
540    /// # Panics
541    ///
542    /// This will panic if `self` is not a [`Type::Tuple`].
543    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    /// Retrieve the inner [`Variant`] of a [`Type::Variant`].
552    ///
553    /// # Panics
554    ///
555    /// This will panic if `self` is not a [`Type::Variant`].
556    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    /// Retrieve the inner [`Enum`] of a [`Type::Enum`].
565    ///
566    /// # Panics
567    ///
568    /// This will panic if `self` is not a [`Type::Enum`].
569    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    /// Retrieve the inner [`OptionType`] of a [`Type::Option`].
578    ///
579    /// # Panics
580    ///
581    /// This will panic if `self` is not a [`Type::Option`].
582    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    /// Retrieve the inner [`ResultType`] of a [`Type::Result`].
591    ///
592    /// # Panics
593    ///
594    /// This will panic if `self` is not a [`Type::Result`].
595    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    /// Retrieve the inner [`Flags`] of a [`Type::Flags`].
604    ///
605    /// # Panics
606    ///
607    /// This will panic if `self` is not a [`Type::Flags`].
608    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    /// Retrieve the inner [`ResourceType`] of a [`Type::Own`].
617    ///
618    /// # Panics
619    ///
620    /// This will panic if `self` is not a [`Type::Own`].
621    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    /// Retrieve the inner [`ResourceType`] of a [`Type::Borrow`].
629    ///
630    /// # Panics
631    ///
632    /// This will panic if `self` is not a [`Type::Borrow`].
633    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    /// Convert the specified `InterfaceType` to a `Type`.
641    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/// Component function type
702#[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    /// Iterates over types of function parameters and names.
711    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    /// Iterates over types of function results
721    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/// Core module type
731#[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    /// Iterates over imports of the module
740    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    /// Iterates over exports of the module
756    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/// Component type
770#[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    /// Returns import associated with `name`, if such exists in the component
779    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    /// Iterates over imports of the component
787    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    /// Returns export associated with `name`, if such exists in the component
800    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    /// Iterates over exports of the component
808    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/// Component instance type
822#[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    /// Returns export associated with `name`, if such exists in the component instance
831    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    /// Iterates over exports of the component instance
839    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/// Type of an item contained within the component
853#[derive(Clone, Debug)]
854pub enum ComponentItem {
855    /// Component function item
856    ComponentFunc(ComponentFunc),
857    /// Core function item
858    CoreFunc(FuncType),
859    /// Core module item
860    Module(Module),
861    /// Component item
862    Component(Component),
863    /// Component instance item
864    ComponentInstance(ComponentInstance),
865    /// Interface type item
866    Type(Type),
867    /// Resource item
868    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                    // This resource type was substituted by a linker for
894                    // example so it's replaced here.
895                    Some(ty) => *ty,
896
897                    // This resource type was not substituted.
898                    None => ResourceType::uninstantiated(&ty.types, resource_index),
899                };
900                Self::Resource(ty)
901            }
902        }
903    }
904}