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::PrimaryMap;
9use wasmtime_environ::component::{
10    ComponentTypes, Export, InterfaceType, ResourceIndex, TypeComponentIndex,
11    TypeComponentInstanceIndex, TypeDef, TypeEnumIndex, TypeFlagsIndex, TypeFuncIndex,
12    TypeFutureIndex, TypeFutureTableIndex, TypeListIndex, TypeModuleIndex, TypeOptionIndex,
13    TypeRecordIndex, TypeResourceTableIndex, TypeResultIndex, TypeStreamIndex,
14    TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex,
15};
16
17pub use crate::component::resources::ResourceType;
18
19/// An owned and `'static` handle for type information in a component.
20///
21/// The components here are:
22///
23/// * `index` - a `TypeFooIndex` defined in the `wasmtime_environ` crate. This
24///   then points into the next field of...
25///
26/// * `types` - this is an allocation originally created from compilation and is
27///   stored in a compiled `Component`. This contains all types necessary and
28///   information about recursive structures and all other type information
29///   within the component. The above `index` points into this structure.
30///
31/// * `resources` - this is used to "close the loop" and represent a concrete
32///   instance type rather than an abstract component type. Instantiating a
33///   component with different resources produces different instance types but
34///   the same underlying component type, so this field serves the purpose to
35///   distinguish instance types from one another. This is runtime state created
36///   during instantiation and threaded through here.
37#[derive(Clone)]
38struct Handle<T> {
39    index: T,
40    types: Arc<ComponentTypes>,
41    resources: Arc<PrimaryMap<ResourceIndex, ResourceType>>,
42}
43
44impl<T> Handle<T> {
45    fn new(index: T, ty: &InstanceType<'_>) -> Handle<T> {
46        Handle {
47            index,
48            types: ty.types.clone(),
49            resources: ty.resources.clone(),
50        }
51    }
52
53    fn instance(&self) -> InstanceType<'_> {
54        InstanceType {
55            types: &self.types,
56            resources: &self.resources,
57        }
58    }
59
60    fn equivalent<'a>(
61        &'a self,
62        other: &'a Self,
63        type_check: fn(&TypeChecker<'a>, T, T) -> bool,
64    ) -> bool
65    where
66        T: PartialEq + Copy,
67    {
68        (self.index == other.index
69            && Arc::ptr_eq(&self.types, &other.types)
70            && Arc::ptr_eq(&self.resources, &other.resources))
71            || type_check(
72                &TypeChecker {
73                    a_types: &self.types,
74                    b_types: &other.types,
75                    a_resource: &self.resources,
76                    b_resource: &other.resources,
77                },
78                self.index,
79                other.index,
80            )
81    }
82}
83
84impl<T: fmt::Debug> fmt::Debug for Handle<T> {
85    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
86        f.debug_struct("Handle")
87            .field("index", &self.index)
88            .finish()
89    }
90}
91
92/// Type checker between two `Handle`s
93struct TypeChecker<'a> {
94    a_types: &'a ComponentTypes,
95    a_resource: &'a PrimaryMap<ResourceIndex, ResourceType>,
96    b_types: &'a ComponentTypes,
97    b_resource: &'a PrimaryMap<ResourceIndex, ResourceType>,
98}
99
100impl TypeChecker<'_> {
101    fn interface_types_equal(&self, a: InterfaceType, b: InterfaceType) -> bool {
102        match (a, b) {
103            (InterfaceType::Own(o1), InterfaceType::Own(o2)) => self.resources_equal(o1, o2),
104            (InterfaceType::Own(_), _) => false,
105            (InterfaceType::Borrow(b1), InterfaceType::Borrow(b2)) => self.resources_equal(b1, b2),
106            (InterfaceType::Borrow(_), _) => false,
107            (InterfaceType::List(l1), InterfaceType::List(l2)) => self.lists_equal(l1, l2),
108            (InterfaceType::List(_), _) => false,
109            (InterfaceType::Record(r1), InterfaceType::Record(r2)) => self.records_equal(r1, r2),
110            (InterfaceType::Record(_), _) => false,
111            (InterfaceType::Variant(v1), InterfaceType::Variant(v2)) => self.variants_equal(v1, v2),
112            (InterfaceType::Variant(_), _) => false,
113            (InterfaceType::Result(r1), InterfaceType::Result(r2)) => self.results_equal(r1, r2),
114            (InterfaceType::Result(_), _) => false,
115            (InterfaceType::Option(o1), InterfaceType::Option(o2)) => self.options_equal(o1, o2),
116            (InterfaceType::Option(_), _) => false,
117            (InterfaceType::Enum(e1), InterfaceType::Enum(e2)) => self.enums_equal(e1, e2),
118            (InterfaceType::Enum(_), _) => false,
119            (InterfaceType::Tuple(t1), InterfaceType::Tuple(t2)) => self.tuples_equal(t1, t2),
120            (InterfaceType::Tuple(_), _) => false,
121            (InterfaceType::Flags(f1), InterfaceType::Flags(f2)) => self.flags_equal(f1, f2),
122            (InterfaceType::Flags(_), _) => false,
123            (InterfaceType::Bool, InterfaceType::Bool) => true,
124            (InterfaceType::Bool, _) => false,
125            (InterfaceType::U8, InterfaceType::U8) => true,
126            (InterfaceType::U8, _) => false,
127            (InterfaceType::U16, InterfaceType::U16) => true,
128            (InterfaceType::U16, _) => false,
129            (InterfaceType::U32, InterfaceType::U32) => true,
130            (InterfaceType::U32, _) => false,
131            (InterfaceType::U64, InterfaceType::U64) => true,
132            (InterfaceType::U64, _) => false,
133            (InterfaceType::S8, InterfaceType::S8) => true,
134            (InterfaceType::S8, _) => false,
135            (InterfaceType::S16, InterfaceType::S16) => true,
136            (InterfaceType::S16, _) => false,
137            (InterfaceType::S32, InterfaceType::S32) => true,
138            (InterfaceType::S32, _) => false,
139            (InterfaceType::S64, InterfaceType::S64) => true,
140            (InterfaceType::S64, _) => false,
141            (InterfaceType::Float32, InterfaceType::Float32) => true,
142            (InterfaceType::Float32, _) => false,
143            (InterfaceType::Float64, InterfaceType::Float64) => true,
144            (InterfaceType::Float64, _) => false,
145            (InterfaceType::String, InterfaceType::String) => true,
146            (InterfaceType::String, _) => false,
147            (InterfaceType::Char, InterfaceType::Char) => true,
148            (InterfaceType::Char, _) => false,
149            (InterfaceType::Future(t1), InterfaceType::Future(t2)) => {
150                self.future_table_types_equal(t1, t2)
151            }
152            (InterfaceType::Future(_), _) => false,
153            (InterfaceType::Stream(t1), InterfaceType::Stream(t2)) => {
154                self.stream_table_types_equal(t1, t2)
155            }
156            (InterfaceType::Stream(_), _) => false,
157            (InterfaceType::ErrorContext(_), InterfaceType::ErrorContext(_)) => true,
158            (InterfaceType::ErrorContext(_), _) => false,
159        }
160    }
161
162    fn lists_equal(&self, l1: TypeListIndex, l2: TypeListIndex) -> bool {
163        let a = &self.a_types[l1];
164        let b = &self.b_types[l2];
165        self.interface_types_equal(a.element, b.element)
166    }
167
168    fn resources_equal(&self, o1: TypeResourceTableIndex, o2: TypeResourceTableIndex) -> bool {
169        let a = &self.a_types[o1];
170        let b = &self.b_types[o2];
171        self.a_resource[a.ty] == self.b_resource[b.ty]
172    }
173
174    fn records_equal(&self, r1: TypeRecordIndex, r2: TypeRecordIndex) -> bool {
175        let a = &self.a_types[r1];
176        let b = &self.b_types[r2];
177        if a.fields.len() != b.fields.len() {
178            return false;
179        }
180        a.fields
181            .iter()
182            .zip(b.fields.iter())
183            .all(|(a_field, b_field)| {
184                a_field.name == b_field.name && self.interface_types_equal(a_field.ty, b_field.ty)
185            })
186    }
187
188    fn variants_equal(&self, v1: TypeVariantIndex, v2: TypeVariantIndex) -> bool {
189        let a = &self.a_types[v1];
190        let b = &self.b_types[v2];
191        if a.cases.len() != b.cases.len() {
192            return false;
193        }
194        a.cases
195            .iter()
196            .zip(b.cases.iter())
197            .all(|((a_name, a_ty), (b_name, b_ty))| {
198                if a_name != b_name {
199                    return false;
200                }
201                match (a_ty, b_ty) {
202                    (Some(a_case_ty), Some(b_case_ty)) => {
203                        self.interface_types_equal(*a_case_ty, *b_case_ty)
204                    }
205                    (None, None) => true,
206                    _ => false,
207                }
208            })
209    }
210
211    fn results_equal(&self, r1: TypeResultIndex, r2: TypeResultIndex) -> bool {
212        let a = &self.a_types[r1];
213        let b = &self.b_types[r2];
214        let oks = match (a.ok, b.ok) {
215            (Some(ok1), Some(ok2)) => self.interface_types_equal(ok1, ok2),
216            (None, None) => true,
217            _ => false,
218        };
219        if !oks {
220            return false;
221        }
222        match (a.err, b.err) {
223            (Some(err1), Some(err2)) => self.interface_types_equal(err1, err2),
224            (None, None) => true,
225            _ => false,
226        }
227    }
228
229    fn options_equal(&self, o1: TypeOptionIndex, o2: TypeOptionIndex) -> bool {
230        let a = &self.a_types[o1];
231        let b = &self.b_types[o2];
232        self.interface_types_equal(a.ty, b.ty)
233    }
234
235    fn enums_equal(&self, e1: TypeEnumIndex, e2: TypeEnumIndex) -> bool {
236        let a = &self.a_types[e1];
237        let b = &self.b_types[e2];
238        a.names == b.names
239    }
240
241    fn tuples_equal(&self, t1: TypeTupleIndex, t2: TypeTupleIndex) -> bool {
242        let a = &self.a_types[t1];
243        let b = &self.b_types[t2];
244        if a.types.len() != b.types.len() {
245            return false;
246        }
247        a.types
248            .iter()
249            .zip(b.types.iter())
250            .all(|(&a, &b)| self.interface_types_equal(a, b))
251    }
252
253    fn flags_equal(&self, f1: TypeFlagsIndex, f2: TypeFlagsIndex) -> bool {
254        let a = &self.a_types[f1];
255        let b = &self.b_types[f2];
256        a.names == b.names
257    }
258
259    fn future_table_types_equal(&self, t1: TypeFutureTableIndex, t2: TypeFutureTableIndex) -> bool {
260        self.futures_equal(self.a_types[t1].ty, self.b_types[t2].ty)
261    }
262
263    fn futures_equal(&self, t1: TypeFutureIndex, t2: TypeFutureIndex) -> bool {
264        let a = &self.a_types[t1];
265        let b = &self.b_types[t2];
266        match (a.payload, b.payload) {
267            (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
268            (None, None) => true,
269            _ => false,
270        }
271    }
272
273    fn stream_table_types_equal(&self, t1: TypeStreamTableIndex, t2: TypeStreamTableIndex) -> bool {
274        self.streams_equal(self.a_types[t1].ty, self.b_types[t2].ty)
275    }
276
277    fn streams_equal(&self, t1: TypeStreamIndex, t2: TypeStreamIndex) -> bool {
278        let a = &self.a_types[t1];
279        let b = &self.b_types[t2];
280        match (a.payload, b.payload) {
281            (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
282            (None, None) => true,
283            _ => false,
284        }
285    }
286}
287
288/// A `list` interface type
289#[derive(Clone, Debug)]
290pub struct List(Handle<TypeListIndex>);
291
292impl PartialEq for List {
293    fn eq(&self, other: &Self) -> bool {
294        self.0.equivalent(&other.0, TypeChecker::lists_equal)
295    }
296}
297
298impl Eq for List {}
299
300impl List {
301    pub(crate) fn from(index: TypeListIndex, ty: &InstanceType<'_>) -> Self {
302        List(Handle::new(index, ty))
303    }
304
305    /// Retrieve the element type of this `list`.
306    pub fn ty(&self) -> Type {
307        Type::from(&self.0.types[self.0.index].element, &self.0.instance())
308    }
309}
310
311/// A field declaration belonging to a `record`
312#[derive(Debug)]
313pub struct Field<'a> {
314    /// The name of the field
315    pub name: &'a str,
316    /// The type of the field
317    pub ty: Type,
318}
319
320/// A `record` interface type
321#[derive(Clone, Debug)]
322pub struct Record(Handle<TypeRecordIndex>);
323
324impl Record {
325    pub(crate) fn from(index: TypeRecordIndex, ty: &InstanceType<'_>) -> Self {
326        Record(Handle::new(index, ty))
327    }
328
329    /// Retrieve the fields of this `record` in declaration order.
330    pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> {
331        self.0.types[self.0.index].fields.iter().map(|field| Field {
332            name: &field.name,
333            ty: Type::from(&field.ty, &self.0.instance()),
334        })
335    }
336}
337
338impl PartialEq for Record {
339    fn eq(&self, other: &Self) -> bool {
340        self.0.equivalent(&other.0, TypeChecker::records_equal)
341    }
342}
343
344impl Eq for Record {}
345
346/// A `tuple` interface type
347#[derive(Clone, Debug)]
348pub struct Tuple(Handle<TypeTupleIndex>);
349
350impl Tuple {
351    pub(crate) fn from(index: TypeTupleIndex, ty: &InstanceType<'_>) -> Self {
352        Tuple(Handle::new(index, ty))
353    }
354
355    /// Retrieve the types of the fields of this `tuple` in declaration order.
356    pub fn types(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
357        self.0.types[self.0.index]
358            .types
359            .iter()
360            .map(|ty| Type::from(ty, &self.0.instance()))
361    }
362}
363
364impl PartialEq for Tuple {
365    fn eq(&self, other: &Self) -> bool {
366        self.0.equivalent(&other.0, TypeChecker::tuples_equal)
367    }
368}
369
370impl Eq for Tuple {}
371
372/// A case declaration belonging to a `variant`
373pub struct Case<'a> {
374    /// The name of the case
375    pub name: &'a str,
376    /// The optional payload type of the case
377    pub ty: Option<Type>,
378}
379
380/// A `variant` interface type
381#[derive(Clone, Debug)]
382pub struct Variant(Handle<TypeVariantIndex>);
383
384impl Variant {
385    pub(crate) fn from(index: TypeVariantIndex, ty: &InstanceType<'_>) -> Self {
386        Variant(Handle::new(index, ty))
387    }
388
389    /// Retrieve the cases of this `variant` in declaration order.
390    pub fn cases(&self) -> impl ExactSizeIterator<Item = Case<'_>> {
391        self.0.types[self.0.index]
392            .cases
393            .iter()
394            .map(|(name, ty)| Case {
395                name,
396                ty: ty.as_ref().map(|ty| Type::from(ty, &self.0.instance())),
397            })
398    }
399}
400
401impl PartialEq for Variant {
402    fn eq(&self, other: &Self) -> bool {
403        self.0.equivalent(&other.0, TypeChecker::variants_equal)
404    }
405}
406
407impl Eq for Variant {}
408
409/// An `enum` interface type
410#[derive(Clone, Debug)]
411pub struct Enum(Handle<TypeEnumIndex>);
412
413impl Enum {
414    pub(crate) fn from(index: TypeEnumIndex, ty: &InstanceType<'_>) -> Self {
415        Enum(Handle::new(index, ty))
416    }
417
418    /// Retrieve the names of the cases of this `enum` in declaration order.
419    pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
420        self.0.types[self.0.index]
421            .names
422            .iter()
423            .map(|name| name.deref())
424    }
425}
426
427impl PartialEq for Enum {
428    fn eq(&self, other: &Self) -> bool {
429        self.0.equivalent(&other.0, TypeChecker::enums_equal)
430    }
431}
432
433impl Eq for Enum {}
434
435/// An `option` interface type
436#[derive(Clone, Debug)]
437pub struct OptionType(Handle<TypeOptionIndex>);
438
439impl OptionType {
440    pub(crate) fn from(index: TypeOptionIndex, ty: &InstanceType<'_>) -> Self {
441        OptionType(Handle::new(index, ty))
442    }
443
444    /// Retrieve the type parameter for this `option`.
445    pub fn ty(&self) -> Type {
446        Type::from(&self.0.types[self.0.index].ty, &self.0.instance())
447    }
448}
449
450impl PartialEq for OptionType {
451    fn eq(&self, other: &Self) -> bool {
452        self.0.equivalent(&other.0, TypeChecker::options_equal)
453    }
454}
455
456impl Eq for OptionType {}
457
458/// A `result` interface type
459#[derive(Clone, Debug)]
460pub struct ResultType(Handle<TypeResultIndex>);
461
462impl ResultType {
463    pub(crate) fn from(index: TypeResultIndex, ty: &InstanceType<'_>) -> Self {
464        ResultType(Handle::new(index, ty))
465    }
466
467    /// Retrieve the `ok` type parameter for this `result`.
468    pub fn ok(&self) -> Option<Type> {
469        Some(Type::from(
470            self.0.types[self.0.index].ok.as_ref()?,
471            &self.0.instance(),
472        ))
473    }
474
475    /// Retrieve the `err` type parameter for this `result`.
476    pub fn err(&self) -> Option<Type> {
477        Some(Type::from(
478            self.0.types[self.0.index].err.as_ref()?,
479            &self.0.instance(),
480        ))
481    }
482}
483
484impl PartialEq for ResultType {
485    fn eq(&self, other: &Self) -> bool {
486        self.0.equivalent(&other.0, TypeChecker::results_equal)
487    }
488}
489
490impl Eq for ResultType {}
491
492/// A `flags` interface type
493#[derive(Clone, Debug)]
494pub struct Flags(Handle<TypeFlagsIndex>);
495
496impl Flags {
497    pub(crate) fn from(index: TypeFlagsIndex, ty: &InstanceType<'_>) -> Self {
498        Flags(Handle::new(index, ty))
499    }
500
501    /// Retrieve the names of the flags of this `flags` type in declaration order.
502    pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
503        self.0.types[self.0.index]
504            .names
505            .iter()
506            .map(|name| name.deref())
507    }
508}
509
510impl PartialEq for Flags {
511    fn eq(&self, other: &Self) -> bool {
512        self.0.equivalent(&other.0, TypeChecker::flags_equal)
513    }
514}
515
516impl Eq for Flags {}
517
518/// An `future` interface type
519#[derive(Clone, Debug)]
520pub struct FutureType(Handle<TypeFutureIndex>);
521
522impl FutureType {
523    pub(crate) fn from(index: TypeFutureIndex, ty: &InstanceType<'_>) -> Self {
524        FutureType(Handle::new(index, ty))
525    }
526
527    /// Retrieve the type parameter for this `future`.
528    pub fn ty(&self) -> Option<Type> {
529        Some(Type::from(
530            self.0.types[self.0.index].payload.as_ref()?,
531            &self.0.instance(),
532        ))
533    }
534}
535
536impl PartialEq for FutureType {
537    fn eq(&self, other: &Self) -> bool {
538        self.0.equivalent(&other.0, TypeChecker::futures_equal)
539    }
540}
541
542impl Eq for FutureType {}
543
544/// An `stream` interface type
545#[derive(Clone, Debug)]
546pub struct StreamType(Handle<TypeStreamIndex>);
547
548impl StreamType {
549    pub(crate) fn from(index: TypeStreamIndex, ty: &InstanceType<'_>) -> Self {
550        StreamType(Handle::new(index, ty))
551    }
552
553    /// Retrieve the type parameter for this `stream`.
554    pub fn ty(&self) -> Option<Type> {
555        Some(Type::from(
556            self.0.types[self.0.index].payload.as_ref()?,
557            &self.0.instance(),
558        ))
559    }
560}
561
562impl PartialEq for StreamType {
563    fn eq(&self, other: &Self) -> bool {
564        self.0.equivalent(&other.0, TypeChecker::streams_equal)
565    }
566}
567
568impl Eq for StreamType {}
569
570/// Represents a component model interface type
571#[derive(Clone, PartialEq, Eq, Debug)]
572#[allow(missing_docs)]
573pub enum Type {
574    Bool,
575    S8,
576    U8,
577    S16,
578    U16,
579    S32,
580    U32,
581    S64,
582    U64,
583    Float32,
584    Float64,
585    Char,
586    String,
587    List(List),
588    Record(Record),
589    Tuple(Tuple),
590    Variant(Variant),
591    Enum(Enum),
592    Option(OptionType),
593    Result(ResultType),
594    Flags(Flags),
595    Own(ResourceType),
596    Borrow(ResourceType),
597    Future(FutureType),
598    Stream(StreamType),
599    ErrorContext,
600}
601
602impl Type {
603    /// Retrieve the inner [`List`] of a [`Type::List`].
604    ///
605    /// # Panics
606    ///
607    /// This will panic if `self` is not a [`Type::List`].
608    pub fn unwrap_list(&self) -> &List {
609        if let Type::List(handle) = self {
610            &handle
611        } else {
612            panic!("attempted to unwrap a {} as a list", self.desc())
613        }
614    }
615
616    /// Retrieve the inner [`Record`] of a [`Type::Record`].
617    ///
618    /// # Panics
619    ///
620    /// This will panic if `self` is not a [`Type::Record`].
621    pub fn unwrap_record(&self) -> &Record {
622        if let Type::Record(handle) = self {
623            &handle
624        } else {
625            panic!("attempted to unwrap a {} as a record", self.desc())
626        }
627    }
628
629    /// Retrieve the inner [`Tuple`] of a [`Type::Tuple`].
630    ///
631    /// # Panics
632    ///
633    /// This will panic if `self` is not a [`Type::Tuple`].
634    pub fn unwrap_tuple(&self) -> &Tuple {
635        if let Type::Tuple(handle) = self {
636            &handle
637        } else {
638            panic!("attempted to unwrap a {} as a tuple", self.desc())
639        }
640    }
641
642    /// Retrieve the inner [`Variant`] of a [`Type::Variant`].
643    ///
644    /// # Panics
645    ///
646    /// This will panic if `self` is not a [`Type::Variant`].
647    pub fn unwrap_variant(&self) -> &Variant {
648        if let Type::Variant(handle) = self {
649            &handle
650        } else {
651            panic!("attempted to unwrap a {} as a variant", self.desc())
652        }
653    }
654
655    /// Retrieve the inner [`Enum`] of a [`Type::Enum`].
656    ///
657    /// # Panics
658    ///
659    /// This will panic if `self` is not a [`Type::Enum`].
660    pub fn unwrap_enum(&self) -> &Enum {
661        if let Type::Enum(handle) = self {
662            &handle
663        } else {
664            panic!("attempted to unwrap a {} as a enum", self.desc())
665        }
666    }
667
668    /// Retrieve the inner [`OptionType`] of a [`Type::Option`].
669    ///
670    /// # Panics
671    ///
672    /// This will panic if `self` is not a [`Type::Option`].
673    pub fn unwrap_option(&self) -> &OptionType {
674        if let Type::Option(handle) = self {
675            &handle
676        } else {
677            panic!("attempted to unwrap a {} as a option", self.desc())
678        }
679    }
680
681    /// Retrieve the inner [`ResultType`] of a [`Type::Result`].
682    ///
683    /// # Panics
684    ///
685    /// This will panic if `self` is not a [`Type::Result`].
686    pub fn unwrap_result(&self) -> &ResultType {
687        if let Type::Result(handle) = self {
688            &handle
689        } else {
690            panic!("attempted to unwrap a {} as a result", self.desc())
691        }
692    }
693
694    /// Retrieve the inner [`Flags`] of a [`Type::Flags`].
695    ///
696    /// # Panics
697    ///
698    /// This will panic if `self` is not a [`Type::Flags`].
699    pub fn unwrap_flags(&self) -> &Flags {
700        if let Type::Flags(handle) = self {
701            &handle
702        } else {
703            panic!("attempted to unwrap a {} as a flags", self.desc())
704        }
705    }
706
707    /// Retrieve the inner [`ResourceType`] of a [`Type::Own`].
708    ///
709    /// # Panics
710    ///
711    /// This will panic if `self` is not a [`Type::Own`].
712    pub fn unwrap_own(&self) -> &ResourceType {
713        match self {
714            Type::Own(ty) => ty,
715            _ => panic!("attempted to unwrap a {} as a own", self.desc()),
716        }
717    }
718
719    /// Retrieve the inner [`ResourceType`] of a [`Type::Borrow`].
720    ///
721    /// # Panics
722    ///
723    /// This will panic if `self` is not a [`Type::Borrow`].
724    pub fn unwrap_borrow(&self) -> &ResourceType {
725        match self {
726            Type::Borrow(ty) => ty,
727            _ => panic!("attempted to unwrap a {} as a own", self.desc()),
728        }
729    }
730
731    /// Convert the specified `InterfaceType` to a `Type`.
732    pub(crate) fn from(ty: &InterfaceType, instance: &InstanceType<'_>) -> Self {
733        match ty {
734            InterfaceType::Bool => Type::Bool,
735            InterfaceType::S8 => Type::S8,
736            InterfaceType::U8 => Type::U8,
737            InterfaceType::S16 => Type::S16,
738            InterfaceType::U16 => Type::U16,
739            InterfaceType::S32 => Type::S32,
740            InterfaceType::U32 => Type::U32,
741            InterfaceType::S64 => Type::S64,
742            InterfaceType::U64 => Type::U64,
743            InterfaceType::Float32 => Type::Float32,
744            InterfaceType::Float64 => Type::Float64,
745            InterfaceType::Char => Type::Char,
746            InterfaceType::String => Type::String,
747            InterfaceType::List(index) => Type::List(List::from(*index, instance)),
748            InterfaceType::Record(index) => Type::Record(Record::from(*index, instance)),
749            InterfaceType::Tuple(index) => Type::Tuple(Tuple::from(*index, instance)),
750            InterfaceType::Variant(index) => Type::Variant(Variant::from(*index, instance)),
751            InterfaceType::Enum(index) => Type::Enum(Enum::from(*index, instance)),
752            InterfaceType::Option(index) => Type::Option(OptionType::from(*index, instance)),
753            InterfaceType::Result(index) => Type::Result(ResultType::from(*index, instance)),
754            InterfaceType::Flags(index) => Type::Flags(Flags::from(*index, instance)),
755            InterfaceType::Own(index) => Type::Own(instance.resource_type(*index)),
756            InterfaceType::Borrow(index) => Type::Borrow(instance.resource_type(*index)),
757            InterfaceType::Future(index) => Type::Future(instance.future_type(*index)),
758            InterfaceType::Stream(index) => Type::Stream(instance.stream_type(*index)),
759            InterfaceType::ErrorContext(_) => Type::ErrorContext,
760        }
761    }
762
763    fn desc(&self) -> &'static str {
764        match self {
765            Type::Bool => "bool",
766            Type::S8 => "s8",
767            Type::U8 => "u8",
768            Type::S16 => "s16",
769            Type::U16 => "u16",
770            Type::S32 => "s32",
771            Type::U32 => "u32",
772            Type::S64 => "s64",
773            Type::U64 => "u64",
774            Type::Float32 => "float32",
775            Type::Float64 => "float64",
776            Type::Char => "char",
777            Type::String => "string",
778            Type::List(_) => "list",
779            Type::Record(_) => "record",
780            Type::Tuple(_) => "tuple",
781            Type::Variant(_) => "variant",
782            Type::Enum(_) => "enum",
783            Type::Option(_) => "option",
784            Type::Result(_) => "result",
785            Type::Flags(_) => "flags",
786            Type::Own(_) => "own",
787            Type::Borrow(_) => "borrow",
788            Type::Future(_) => "future",
789            Type::Stream(_) => "stream",
790            Type::ErrorContext => "error-context",
791        }
792    }
793}
794
795/// Component function type
796#[derive(Clone, Debug)]
797pub struct ComponentFunc(Handle<TypeFuncIndex>);
798
799impl ComponentFunc {
800    pub(crate) fn from(index: TypeFuncIndex, ty: &InstanceType<'_>) -> Self {
801        Self(Handle::new(index, ty))
802    }
803
804    /// Iterates over types of function parameters and names.
805    pub fn params(&self) -> impl ExactSizeIterator<Item = (&str, Type)> + '_ {
806        let ty = &self.0.types[self.0.index];
807        self.0.types[ty.params]
808            .types
809            .iter()
810            .zip(&ty.param_names)
811            .map(|(ty, name)| (name.as_str(), Type::from(ty, &self.0.instance())))
812    }
813
814    /// Iterates over types of function results
815    pub fn results(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
816        let results = self.0.types[self.0.index].results;
817        self.0.types[results]
818            .types
819            .iter()
820            .map(|ty| Type::from(ty, &self.0.instance()))
821    }
822
823    #[doc(hidden)]
824    pub fn typecheck<Params, Return>(&self, cx: &InstanceType) -> anyhow::Result<()>
825    where
826        Params: crate::component::ComponentNamedList + crate::component::Lower,
827        Return: crate::component::ComponentNamedList + crate::component::Lift,
828    {
829        let ty = &self.0.types[self.0.index];
830        Params::typecheck(&InterfaceType::Tuple(ty.params), cx)?;
831        Return::typecheck(&InterfaceType::Tuple(ty.results), cx)?;
832        Ok(())
833    }
834}
835
836/// Core module type
837#[derive(Clone, Debug)]
838pub struct Module(Handle<TypeModuleIndex>);
839
840impl Module {
841    pub(crate) fn from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self {
842        Self(Handle::new(index, ty))
843    }
844
845    /// Iterates over imports of the module
846    pub fn imports<'a>(
847        &'a self,
848        engine: &'a Engine,
849    ) -> impl ExactSizeIterator<Item = ((&'a str, &'a str), ExternType)> + 'a {
850        self.0.types[self.0.index]
851            .imports
852            .iter()
853            .map(|((namespace, name), ty)| {
854                (
855                    (namespace.as_str(), name.as_str()),
856                    ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
857                )
858            })
859    }
860
861    /// Iterates over exports of the module
862    pub fn exports<'a>(
863        &'a self,
864        engine: &'a Engine,
865    ) -> impl ExactSizeIterator<Item = (&'a str, ExternType)> + 'a {
866        self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
867            (
868                name.as_str(),
869                ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
870            )
871        })
872    }
873}
874
875/// Component type
876#[derive(Clone, Debug)]
877pub struct Component(Handle<TypeComponentIndex>);
878
879impl Component {
880    pub(crate) fn from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self {
881        Self(Handle::new(index, ty))
882    }
883
884    /// Returns import associated with `name`, if such exists in the component
885    pub fn get_import(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
886        self.0.types[self.0.index]
887            .imports
888            .get(name)
889            .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
890    }
891
892    /// Iterates over imports of the component
893    pub fn imports<'a>(
894        &'a self,
895        engine: &'a Engine,
896    ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
897        self.0.types[self.0.index].imports.iter().map(|(name, ty)| {
898            (
899                name.as_str(),
900                ComponentItem::from(engine, ty, &self.0.instance()),
901            )
902        })
903    }
904
905    /// Returns export associated with `name`, if such exists in the component
906    pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
907        self.0.types[self.0.index]
908            .exports
909            .get(name)
910            .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
911    }
912
913    /// Iterates over exports of the component
914    pub fn exports<'a>(
915        &'a self,
916        engine: &'a Engine,
917    ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> + 'a {
918        self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
919            (
920                name.as_str(),
921                ComponentItem::from(engine, ty, &self.0.instance()),
922            )
923        })
924    }
925
926    #[doc(hidden)]
927    pub fn instance_type(&self) -> InstanceType<'_> {
928        InstanceType {
929            types: &self.0.types,
930            resources: &self.0.resources,
931        }
932    }
933}
934
935/// Component instance type
936#[derive(Clone, Debug)]
937pub struct ComponentInstance(Handle<TypeComponentInstanceIndex>);
938
939impl ComponentInstance {
940    pub(crate) fn from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self {
941        Self(Handle::new(index, ty))
942    }
943
944    /// Returns export associated with `name`, if such exists in the component instance
945    pub fn get_export(&self, engine: &Engine, name: &str) -> Option<ComponentItem> {
946        self.0.types[self.0.index]
947            .exports
948            .get(name)
949            .map(|ty| ComponentItem::from(engine, ty, &self.0.instance()))
950    }
951
952    /// Iterates over exports of the component instance
953    pub fn exports<'a>(
954        &'a self,
955        engine: &'a Engine,
956    ) -> impl ExactSizeIterator<Item = (&'a str, ComponentItem)> {
957        self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
958            (
959                name.as_str(),
960                ComponentItem::from(engine, ty, &self.0.instance()),
961            )
962        })
963    }
964}
965
966/// Type of an item contained within the component
967#[derive(Clone, Debug)]
968pub enum ComponentItem {
969    /// Component function item
970    ComponentFunc(ComponentFunc),
971    /// Core function item
972    CoreFunc(FuncType),
973    /// Core module item
974    Module(Module),
975    /// Component item
976    Component(Component),
977    /// Component instance item
978    ComponentInstance(ComponentInstance),
979    /// Interface type item
980    Type(Type),
981    /// Resource item
982    Resource(ResourceType),
983}
984
985impl ComponentItem {
986    pub(crate) fn from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self {
987        match def {
988            TypeDef::Component(idx) => Self::Component(Component::from(*idx, ty)),
989            TypeDef::ComponentInstance(idx) => {
990                Self::ComponentInstance(ComponentInstance::from(*idx, ty))
991            }
992            TypeDef::ComponentFunc(idx) => Self::ComponentFunc(ComponentFunc::from(*idx, ty)),
993            TypeDef::Interface(iface_ty) => Self::Type(Type::from(iface_ty, ty)),
994            TypeDef::Module(idx) => Self::Module(Module::from(*idx, ty)),
995            TypeDef::CoreFunc(idx) => {
996                let subty = &ty.types[*idx];
997                Self::CoreFunc(FuncType::from_wasm_func_type(
998                    engine,
999                    subty.is_final,
1000                    subty.supertype,
1001                    subty.unwrap_func().clone(),
1002                ))
1003            }
1004            TypeDef::Resource(idx) => {
1005                let resource_index = ty.types[*idx].ty;
1006                let ty = match ty.resources.get(resource_index) {
1007                    // This resource type was substituted by a linker for
1008                    // example so it's replaced here.
1009                    Some(ty) => *ty,
1010
1011                    // This resource type was not substituted.
1012                    None => ResourceType::uninstantiated(&ty.types, resource_index),
1013                };
1014                Self::Resource(ty)
1015            }
1016        }
1017    }
1018    pub(crate) fn from_export(engine: &Engine, export: &Export, ty: &InstanceType<'_>) -> Self {
1019        match export {
1020            Export::Instance { ty: idx, .. } => {
1021                Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1022            }
1023            Export::LiftedFunction { ty: idx, .. } => {
1024                Self::ComponentFunc(ComponentFunc::from(*idx, ty))
1025            }
1026            Export::ModuleStatic { ty: idx, .. } | Export::ModuleImport { ty: idx, .. } => {
1027                Self::Module(Module::from(*idx, ty))
1028            }
1029            Export::Type(idx) => Self::from(engine, idx, ty),
1030        }
1031    }
1032}