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