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, 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/// 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    #[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/// Core module type
743#[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    /// Iterates over imports of the module
752    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    /// Iterates over exports of the module
768    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/// Component type
782#[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    /// Returns import associated with `name`, if such exists in the component
791    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    /// Iterates over imports of the component
799    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    /// Returns export associated with `name`, if such exists in the component
812    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    /// Iterates over exports of the component
820    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/// Component instance type
842#[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    /// Returns export associated with `name`, if such exists in the component instance
851    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    /// Iterates over exports of the component instance
859    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/// Type of an item contained within the component
873#[derive(Clone, Debug)]
874pub enum ComponentItem {
875    /// Component function item
876    ComponentFunc(ComponentFunc),
877    /// Core function item
878    CoreFunc(FuncType),
879    /// Core module item
880    Module(Module),
881    /// Component item
882    Component(Component),
883    /// Component instance item
884    ComponentInstance(ComponentInstance),
885    /// Interface type item
886    Type(Type),
887    /// Resource item
888    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                    // This resource type was substituted by a linker for
914                    // example so it's replaced here.
915                    Some(ty) => *ty,
916
917                    // This resource type was not substituted.
918                    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}