Skip to main content

wasmtime/runtime/component/
types.rs

1//! This module defines the `Type` type, representing the dynamic form of a component interface type.
2
3#[cfg(feature = "component-model-async")]
4use crate::component::ComponentType;
5use crate::component::matching::InstanceType;
6use crate::component::{ResourceAny, Val};
7use crate::{AsContextMut, Engine, ExternType, FuncType, StoreContextMut, prelude::*};
8use alloc::sync::Arc;
9use core::fmt;
10use core::ops::Deref;
11use wasmtime_environ::PanicOnOom as _;
12use wasmtime_environ::component::{
13    ComponentTypes, Export, InterfaceType, ResourceIndex, TypeComponentIndex,
14    TypeComponentInstanceIndex, TypeDef, TypeEnumIndex, TypeFixedLengthListIndex, TypeFlagsIndex,
15    TypeFuncIndex, TypeFutureIndex, TypeFutureTableIndex, TypeListIndex, TypeMapIndex,
16    TypeModuleIndex, TypeOptionIndex, TypeRecordIndex, TypeResourceTable, TypeResourceTableIndex,
17    TypeResultIndex, TypeStreamIndex, TypeStreamTableIndex, TypeTupleIndex, TypeVariantIndex,
18    alternate_lookup_key,
19};
20
21pub use crate::component::resources::ResourceType;
22
23/// An owned and `'static` handle for type information in a component.
24///
25/// The components here are:
26///
27/// * `index` - a `TypeFooIndex` defined in the `wasmtime_environ` crate. This
28///   then points into the next field of...
29///
30/// * `types` - this is an allocation originally created from compilation and is
31///   stored in a compiled `Component`. This contains all types necessary and
32///   information about recursive structures and all other type information
33///   within the component. The above `index` points into this structure.
34///
35/// * `resources` - this is used to "close the loop" and represent a concrete
36///   instance type rather than an abstract component type. Instantiating a
37///   component with different resources produces different instance types but
38///   the same underlying component type, so this field serves the purpose to
39///   distinguish instance types from one another. This is runtime state created
40///   during instantiation and threaded through here. Note that if this field
41///   is `None` then this represents an abstract uninstantiated component type.
42#[derive(Clone)]
43struct Handle<T> {
44    index: T,
45    types: Arc<ComponentTypes>,
46    resources: Option<Arc<TryPrimaryMap<ResourceIndex, ResourceType>>>,
47}
48
49impl<T> Handle<T> {
50    fn new(index: T, ty: &InstanceType<'_>) -> Handle<T> {
51        Handle {
52            index,
53            types: ty.types.clone(),
54            resources: ty.resources.cloned(),
55        }
56    }
57
58    fn instance(&self) -> InstanceType<'_> {
59        InstanceType {
60            types: &self.types,
61            resources: self.resources.as_ref(),
62        }
63    }
64
65    fn equivalent<'a>(
66        &'a self,
67        other: &'a Self,
68        type_check: fn(&TypeChecker<'a>, T, T) -> bool,
69    ) -> bool
70    where
71        T: PartialEq + Copy,
72    {
73        (self.index == other.index
74            && Arc::ptr_eq(&self.types, &other.types)
75            && match (&self.resources, &other.resources) {
76                (Some(a), Some(b)) => Arc::ptr_eq(a, b),
77                (None, None) => true,
78                _ => false,
79            })
80            || type_check(
81                &TypeChecker {
82                    a_types: &self.types,
83                    b_types: &other.types,
84                    a_resource: self.resources.as_deref(),
85                    b_resource: other.resources.as_deref(),
86                },
87                self.index,
88                other.index,
89            )
90    }
91}
92
93impl<T: fmt::Debug> fmt::Debug for Handle<T> {
94    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95        f.debug_struct("Handle")
96            .field("index", &self.index)
97            .finish()
98    }
99}
100
101/// Type checker between two `Handle`s
102struct TypeChecker<'a> {
103    a_types: &'a ComponentTypes,
104    a_resource: Option<&'a TryPrimaryMap<ResourceIndex, ResourceType>>,
105    b_types: &'a ComponentTypes,
106    b_resource: Option<&'a TryPrimaryMap<ResourceIndex, ResourceType>>,
107}
108
109impl TypeChecker<'_> {
110    fn interface_types_equal(&self, a: InterfaceType, b: InterfaceType) -> bool {
111        match (a, b) {
112            (InterfaceType::Own(o1), InterfaceType::Own(o2)) => self.resources_equal(o1, o2),
113            (InterfaceType::Own(_), _) => false,
114            (InterfaceType::Borrow(b1), InterfaceType::Borrow(b2)) => self.resources_equal(b1, b2),
115            (InterfaceType::Borrow(_), _) => false,
116            (InterfaceType::List(l1), InterfaceType::List(l2)) => self.lists_equal(l1, l2),
117            (InterfaceType::List(_), _) => false,
118            (InterfaceType::Map(m1), InterfaceType::Map(m2)) => self.maps_equal(m1, m2),
119            (InterfaceType::Map(_), _) => false,
120            (InterfaceType::Record(r1), InterfaceType::Record(r2)) => self.records_equal(r1, r2),
121            (InterfaceType::Record(_), _) => false,
122            (InterfaceType::Variant(v1), InterfaceType::Variant(v2)) => self.variants_equal(v1, v2),
123            (InterfaceType::Variant(_), _) => false,
124            (InterfaceType::Result(r1), InterfaceType::Result(r2)) => self.results_equal(r1, r2),
125            (InterfaceType::Result(_), _) => false,
126            (InterfaceType::Option(o1), InterfaceType::Option(o2)) => self.options_equal(o1, o2),
127            (InterfaceType::Option(_), _) => false,
128            (InterfaceType::Enum(e1), InterfaceType::Enum(e2)) => self.enums_equal(e1, e2),
129            (InterfaceType::Enum(_), _) => false,
130            (InterfaceType::Tuple(t1), InterfaceType::Tuple(t2)) => self.tuples_equal(t1, t2),
131            (InterfaceType::Tuple(_), _) => false,
132            (InterfaceType::Flags(f1), InterfaceType::Flags(f2)) => self.flags_equal(f1, f2),
133            (InterfaceType::Flags(_), _) => false,
134            (InterfaceType::Bool, InterfaceType::Bool) => true,
135            (InterfaceType::Bool, _) => false,
136            (InterfaceType::U8, InterfaceType::U8) => true,
137            (InterfaceType::U8, _) => false,
138            (InterfaceType::U16, InterfaceType::U16) => true,
139            (InterfaceType::U16, _) => false,
140            (InterfaceType::U32, InterfaceType::U32) => true,
141            (InterfaceType::U32, _) => false,
142            (InterfaceType::U64, InterfaceType::U64) => true,
143            (InterfaceType::U64, _) => false,
144            (InterfaceType::S8, InterfaceType::S8) => true,
145            (InterfaceType::S8, _) => false,
146            (InterfaceType::S16, InterfaceType::S16) => true,
147            (InterfaceType::S16, _) => false,
148            (InterfaceType::S32, InterfaceType::S32) => true,
149            (InterfaceType::S32, _) => false,
150            (InterfaceType::S64, InterfaceType::S64) => true,
151            (InterfaceType::S64, _) => false,
152            (InterfaceType::Float32, InterfaceType::Float32) => true,
153            (InterfaceType::Float32, _) => false,
154            (InterfaceType::Float64, InterfaceType::Float64) => true,
155            (InterfaceType::Float64, _) => false,
156            (InterfaceType::String, InterfaceType::String) => true,
157            (InterfaceType::String, _) => false,
158            (InterfaceType::Char, InterfaceType::Char) => true,
159            (InterfaceType::Char, _) => false,
160            (InterfaceType::Future(t1), InterfaceType::Future(t2)) => {
161                self.future_table_types_equal(t1, t2)
162            }
163            (InterfaceType::Future(_), _) => false,
164            (InterfaceType::Stream(t1), InterfaceType::Stream(t2)) => {
165                self.stream_table_types_equal(t1, t2)
166            }
167            (InterfaceType::Stream(_), _) => false,
168            (InterfaceType::ErrorContext(_), InterfaceType::ErrorContext(_)) => true,
169            (InterfaceType::ErrorContext(_), _) => false,
170            (InterfaceType::FixedLengthList(t1), InterfaceType::FixedLengthList(t2)) => {
171                self.fixed_length_lists_equal(t1, t2)
172            }
173            (InterfaceType::FixedLengthList(_), _) => false,
174        }
175    }
176
177    fn lists_equal(&self, l1: TypeListIndex, l2: TypeListIndex) -> bool {
178        let a = &self.a_types[l1];
179        let b = &self.b_types[l2];
180        self.interface_types_equal(a.element, b.element)
181    }
182
183    fn maps_equal(&self, m1: TypeMapIndex, m2: TypeMapIndex) -> bool {
184        let a = &self.a_types[m1];
185        let b = &self.b_types[m2];
186        self.interface_types_equal(a.key, b.key) && self.interface_types_equal(a.value, b.value)
187    }
188
189    fn fixed_length_lists_equal(
190        &self,
191        l1: wasmtime_environ::component::TypeFixedLengthListIndex,
192        l2: wasmtime_environ::component::TypeFixedLengthListIndex,
193    ) -> bool {
194        let a = &self.a_types[l1];
195        let b = &self.b_types[l2];
196        if a.size != b.size {
197            return false;
198        }
199        self.interface_types_equal(a.element, b.element)
200    }
201
202    fn resources_equal(&self, o1: TypeResourceTableIndex, o2: TypeResourceTableIndex) -> bool {
203        match (&self.a_types[o1], &self.b_types[o2]) {
204            // Concrete resource types are the same if they map back to the
205            // exact same `ResourceType` at runtime, so look them up in resource
206            // type tables and compare the types themselves.
207            (
208                TypeResourceTable::Concrete { ty: a, .. },
209                TypeResourceTable::Concrete { ty: b, .. },
210            ) => self.a_resource.unwrap()[*a] == self.b_resource.unwrap()[*b],
211            (TypeResourceTable::Concrete { .. }, _) => false,
212
213            // Abstract resource types are only the same if they have the same
214            // index and come from the exact same component.
215            (TypeResourceTable::Abstract(a), TypeResourceTable::Abstract(b)) => {
216                core::ptr::eq(self.a_types, self.b_types) && a == b
217            }
218            (TypeResourceTable::Abstract(_), _) => false,
219        }
220    }
221
222    fn records_equal(&self, r1: TypeRecordIndex, r2: TypeRecordIndex) -> bool {
223        let a = &self.a_types[r1];
224        let b = &self.b_types[r2];
225        if a.fields.len() != b.fields.len() {
226            return false;
227        }
228        a.fields
229            .iter()
230            .zip(b.fields.iter())
231            .all(|(a_field, b_field)| {
232                a_field.name == b_field.name && self.interface_types_equal(a_field.ty, b_field.ty)
233            })
234    }
235
236    fn variants_equal(&self, v1: TypeVariantIndex, v2: TypeVariantIndex) -> bool {
237        let a = &self.a_types[v1];
238        let b = &self.b_types[v2];
239        if a.cases.len() != b.cases.len() {
240            return false;
241        }
242        a.cases
243            .iter()
244            .zip(b.cases.iter())
245            .all(|((a_name, a_ty), (b_name, b_ty))| {
246                if a_name != b_name {
247                    return false;
248                }
249                match (a_ty, b_ty) {
250                    (Some(a_case_ty), Some(b_case_ty)) => {
251                        self.interface_types_equal(*a_case_ty, *b_case_ty)
252                    }
253                    (None, None) => true,
254                    _ => false,
255                }
256            })
257    }
258
259    fn results_equal(&self, r1: TypeResultIndex, r2: TypeResultIndex) -> bool {
260        let a = &self.a_types[r1];
261        let b = &self.b_types[r2];
262        let oks = match (a.ok, b.ok) {
263            (Some(ok1), Some(ok2)) => self.interface_types_equal(ok1, ok2),
264            (None, None) => true,
265            _ => false,
266        };
267        if !oks {
268            return false;
269        }
270        match (a.err, b.err) {
271            (Some(err1), Some(err2)) => self.interface_types_equal(err1, err2),
272            (None, None) => true,
273            _ => false,
274        }
275    }
276
277    fn options_equal(&self, o1: TypeOptionIndex, o2: TypeOptionIndex) -> bool {
278        let a = &self.a_types[o1];
279        let b = &self.b_types[o2];
280        self.interface_types_equal(a.ty, b.ty)
281    }
282
283    fn enums_equal(&self, e1: TypeEnumIndex, e2: TypeEnumIndex) -> bool {
284        let a = &self.a_types[e1];
285        let b = &self.b_types[e2];
286        a.names == b.names
287    }
288
289    fn tuples_equal(&self, t1: TypeTupleIndex, t2: TypeTupleIndex) -> bool {
290        let a = &self.a_types[t1];
291        let b = &self.b_types[t2];
292        if a.types.len() != b.types.len() {
293            return false;
294        }
295        a.types
296            .iter()
297            .zip(b.types.iter())
298            .all(|(&a, &b)| self.interface_types_equal(a, b))
299    }
300
301    fn flags_equal(&self, f1: TypeFlagsIndex, f2: TypeFlagsIndex) -> bool {
302        let a = &self.a_types[f1];
303        let b = &self.b_types[f2];
304        a.names == b.names
305    }
306
307    fn future_table_types_equal(&self, t1: TypeFutureTableIndex, t2: TypeFutureTableIndex) -> bool {
308        self.futures_equal(self.a_types[t1].ty, self.b_types[t2].ty)
309    }
310
311    fn futures_equal(&self, t1: TypeFutureIndex, t2: TypeFutureIndex) -> bool {
312        let a = &self.a_types[t1];
313        let b = &self.b_types[t2];
314        match (a.payload, b.payload) {
315            (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
316            (None, None) => true,
317            _ => false,
318        }
319    }
320
321    fn stream_table_types_equal(&self, t1: TypeStreamTableIndex, t2: TypeStreamTableIndex) -> bool {
322        self.streams_equal(self.a_types[t1].ty, self.b_types[t2].ty)
323    }
324
325    fn streams_equal(&self, t1: TypeStreamIndex, t2: TypeStreamIndex) -> bool {
326        let a = &self.a_types[t1];
327        let b = &self.b_types[t2];
328        match (a.payload, b.payload) {
329            (Some(t1), Some(t2)) => self.interface_types_equal(t1, t2),
330            (None, None) => true,
331            _ => false,
332        }
333    }
334}
335
336/// A `list` interface type
337#[derive(Clone, Debug)]
338pub struct List(Handle<TypeListIndex>);
339
340impl PartialEq for List {
341    fn eq(&self, other: &Self) -> bool {
342        self.0.equivalent(&other.0, TypeChecker::lists_equal)
343    }
344}
345
346impl Eq for List {}
347
348impl List {
349    pub(crate) fn from(index: TypeListIndex, ty: &InstanceType<'_>) -> Self {
350        List(Handle::new(index, ty))
351    }
352
353    /// Retrieve the element type of this `list`.
354    pub fn ty(&self) -> Type {
355        Type::from(&self.0.types[self.0.index].element, &self.0.instance())
356    }
357}
358
359/// A `map` interface type
360#[derive(Clone, Debug)]
361pub struct Map(Handle<TypeMapIndex>);
362
363impl PartialEq for Map {
364    fn eq(&self, other: &Self) -> bool {
365        self.0.equivalent(&other.0, TypeChecker::maps_equal)
366    }
367}
368
369impl Eq for Map {}
370
371impl Map {
372    pub(crate) fn from(index: TypeMapIndex, ty: &InstanceType<'_>) -> Self {
373        Map(Handle::new(index, ty))
374    }
375
376    /// Retrieve the key type of this `map`.
377    pub fn key(&self) -> Type {
378        Type::from(&self.0.types[self.0.index].key, &self.0.instance())
379    }
380
381    /// Retrieve the value type of this `map`.
382    pub fn value(&self) -> Type {
383        Type::from(&self.0.types[self.0.index].value, &self.0.instance())
384    }
385}
386/// A `list` interface type
387#[derive(Clone, Debug)]
388pub struct FixedLengthList(Handle<TypeFixedLengthListIndex>);
389
390impl PartialEq for FixedLengthList {
391    fn eq(&self, other: &Self) -> bool {
392        self.0
393            .equivalent(&other.0, TypeChecker::fixed_length_lists_equal)
394    }
395}
396
397impl Eq for FixedLengthList {}
398
399impl FixedLengthList {
400    pub(crate) fn from(index: TypeFixedLengthListIndex, ty: &InstanceType<'_>) -> Self {
401        FixedLengthList(Handle::new(index, ty))
402    }
403
404    /// Retrieve the element type of this `list`.
405    pub fn ty(&self) -> Type {
406        Type::from(&self.0.types[self.0.index].element, &self.0.instance())
407    }
408
409    /// Retrieve the length of this `list`.
410    pub fn len(&self) -> u32 {
411        self.0.types[self.0.index].size
412    }
413}
414
415/// A field declaration belonging to a `record`
416#[derive(Debug)]
417pub struct Field<'a> {
418    /// The name of the field
419    pub name: &'a str,
420    /// The type of the field
421    pub ty: Type,
422}
423
424/// A `record` interface type
425#[derive(Clone, Debug)]
426pub struct Record(Handle<TypeRecordIndex>);
427
428impl Record {
429    pub(crate) fn from(index: TypeRecordIndex, ty: &InstanceType<'_>) -> Self {
430        Record(Handle::new(index, ty))
431    }
432
433    /// Retrieve the fields of this `record` in declaration order.
434    pub fn fields(&self) -> impl ExactSizeIterator<Item = Field<'_>> {
435        self.0.types[self.0.index].fields.iter().map(|field| Field {
436            name: &field.name,
437            ty: Type::from(&field.ty, &self.0.instance()),
438        })
439    }
440}
441
442impl PartialEq for Record {
443    fn eq(&self, other: &Self) -> bool {
444        self.0.equivalent(&other.0, TypeChecker::records_equal)
445    }
446}
447
448impl Eq for Record {}
449
450/// A `tuple` interface type
451#[derive(Clone, Debug)]
452pub struct Tuple(Handle<TypeTupleIndex>);
453
454impl Tuple {
455    pub(crate) fn from(index: TypeTupleIndex, ty: &InstanceType<'_>) -> Self {
456        Tuple(Handle::new(index, ty))
457    }
458
459    /// Retrieve the types of the fields of this `tuple` in declaration order.
460    pub fn types(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
461        self.0.types[self.0.index]
462            .types
463            .iter()
464            .map(|ty| Type::from(ty, &self.0.instance()))
465    }
466}
467
468impl PartialEq for Tuple {
469    fn eq(&self, other: &Self) -> bool {
470        self.0.equivalent(&other.0, TypeChecker::tuples_equal)
471    }
472}
473
474impl Eq for Tuple {}
475
476/// A case declaration belonging to a `variant`
477pub struct Case<'a> {
478    /// The name of the case
479    pub name: &'a str,
480    /// The optional payload type of the case
481    pub ty: Option<Type>,
482}
483
484/// A `variant` interface type
485#[derive(Clone, Debug)]
486pub struct Variant(Handle<TypeVariantIndex>);
487
488impl Variant {
489    pub(crate) fn from(index: TypeVariantIndex, ty: &InstanceType<'_>) -> Self {
490        Variant(Handle::new(index, ty))
491    }
492
493    /// Retrieve the cases of this `variant` in declaration order.
494    pub fn cases(&self) -> impl ExactSizeIterator<Item = Case<'_>> {
495        self.0.types[self.0.index]
496            .cases
497            .iter()
498            .map(|(name, ty)| Case {
499                name,
500                ty: ty.as_ref().map(|ty| Type::from(ty, &self.0.instance())),
501            })
502    }
503}
504
505impl PartialEq for Variant {
506    fn eq(&self, other: &Self) -> bool {
507        self.0.equivalent(&other.0, TypeChecker::variants_equal)
508    }
509}
510
511impl Eq for Variant {}
512
513/// An `enum` interface type
514#[derive(Clone, Debug)]
515pub struct Enum(Handle<TypeEnumIndex>);
516
517impl Enum {
518    pub(crate) fn from(index: TypeEnumIndex, ty: &InstanceType<'_>) -> Self {
519        Enum(Handle::new(index, ty))
520    }
521
522    /// Retrieve the names of the cases of this `enum` in declaration order.
523    pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
524        self.0.types[self.0.index]
525            .names
526            .iter()
527            .map(|name| name.deref())
528    }
529}
530
531impl PartialEq for Enum {
532    fn eq(&self, other: &Self) -> bool {
533        self.0.equivalent(&other.0, TypeChecker::enums_equal)
534    }
535}
536
537impl Eq for Enum {}
538
539/// An `option` interface type
540#[derive(Clone, Debug)]
541pub struct OptionType(Handle<TypeOptionIndex>);
542
543impl OptionType {
544    pub(crate) fn from(index: TypeOptionIndex, ty: &InstanceType<'_>) -> Self {
545        OptionType(Handle::new(index, ty))
546    }
547
548    /// Retrieve the type parameter for this `option`.
549    pub fn ty(&self) -> Type {
550        Type::from(&self.0.types[self.0.index].ty, &self.0.instance())
551    }
552}
553
554impl PartialEq for OptionType {
555    fn eq(&self, other: &Self) -> bool {
556        self.0.equivalent(&other.0, TypeChecker::options_equal)
557    }
558}
559
560impl Eq for OptionType {}
561
562/// A `result` interface type
563#[derive(Clone, Debug)]
564pub struct ResultType(Handle<TypeResultIndex>);
565
566impl ResultType {
567    pub(crate) fn from(index: TypeResultIndex, ty: &InstanceType<'_>) -> Self {
568        ResultType(Handle::new(index, ty))
569    }
570
571    /// Retrieve the `ok` type parameter for this `result`.
572    pub fn ok(&self) -> Option<Type> {
573        Some(Type::from(
574            self.0.types[self.0.index].ok.as_ref()?,
575            &self.0.instance(),
576        ))
577    }
578
579    /// Retrieve the `err` type parameter for this `result`.
580    pub fn err(&self) -> Option<Type> {
581        Some(Type::from(
582            self.0.types[self.0.index].err.as_ref()?,
583            &self.0.instance(),
584        ))
585    }
586}
587
588impl PartialEq for ResultType {
589    fn eq(&self, other: &Self) -> bool {
590        self.0.equivalent(&other.0, TypeChecker::results_equal)
591    }
592}
593
594impl Eq for ResultType {}
595
596/// A `flags` interface type
597#[derive(Clone, Debug)]
598pub struct Flags(Handle<TypeFlagsIndex>);
599
600impl Flags {
601    pub(crate) fn from(index: TypeFlagsIndex, ty: &InstanceType<'_>) -> Self {
602        Flags(Handle::new(index, ty))
603    }
604
605    /// Retrieve the names of the flags of this `flags` type in declaration order.
606    pub fn names(&self) -> impl ExactSizeIterator<Item = &str> {
607        self.0.types[self.0.index]
608            .names
609            .iter()
610            .map(|name| name.deref())
611    }
612}
613
614impl PartialEq for Flags {
615    fn eq(&self, other: &Self) -> bool {
616        self.0.equivalent(&other.0, TypeChecker::flags_equal)
617    }
618}
619
620impl Eq for Flags {}
621
622#[cfg(feature = "component-model-async")]
623pub(crate) fn typecheck_payload<T>(
624    payload: Option<&InterfaceType>,
625    types: &InstanceType<'_>,
626) -> crate::Result<()>
627where
628    T: ComponentType,
629{
630    match payload {
631        Some(a) => T::typecheck(a, types),
632        None => {
633            if T::IS_RUST_UNIT_TYPE {
634                Ok(())
635            } else {
636                crate::bail!("future payload types differ")
637            }
638        }
639    }
640}
641
642/// An `future` interface type
643#[derive(Clone, Debug)]
644pub struct FutureType(Handle<TypeFutureIndex>);
645
646impl FutureType {
647    pub(crate) fn from(index: TypeFutureIndex, ty: &InstanceType<'_>) -> Self {
648        FutureType(Handle::new(index, ty))
649    }
650
651    /// Retrieve the type parameter for this `future`.
652    pub fn ty(&self) -> Option<Type> {
653        Some(Type::from(
654            self.0.types[self.0.index].payload.as_ref()?,
655            &self.0.instance(),
656        ))
657    }
658
659    #[cfg(feature = "component-model-async")]
660    pub(crate) fn equivalent_payload_guest(
661        &self,
662        ty: &InstanceType<'_>,
663        payload: Option<&InterfaceType>,
664    ) -> bool {
665        let my_payload = self.0.types[self.0.index].payload.as_ref();
666        match (my_payload, payload) {
667            (Some(a), Some(b)) => TypeChecker {
668                a_types: &self.0.types,
669                a_resource: self.0.resources.as_deref(),
670                b_types: ty.types,
671                b_resource: ty.resources.map(|p| &**p),
672            }
673            .interface_types_equal(*a, *b),
674            (None, None) => true,
675            (Some(_), None) | (None, Some(_)) => false,
676        }
677    }
678
679    #[cfg(feature = "component-model-async")]
680    pub(crate) fn equivalent_payload_host<T>(&self) -> crate::Result<()>
681    where
682        T: ComponentType,
683    {
684        typecheck_payload::<T>(
685            self.0.types[self.0.index].payload.as_ref(),
686            &self.0.instance(),
687        )
688    }
689}
690
691impl PartialEq for FutureType {
692    fn eq(&self, other: &Self) -> bool {
693        self.0.equivalent(&other.0, TypeChecker::futures_equal)
694    }
695}
696
697impl Eq for FutureType {}
698
699/// An `stream` interface type
700#[derive(Clone, Debug)]
701pub struct StreamType(Handle<TypeStreamIndex>);
702
703impl StreamType {
704    pub(crate) fn from(index: TypeStreamIndex, ty: &InstanceType<'_>) -> Self {
705        StreamType(Handle::new(index, ty))
706    }
707
708    /// Retrieve the type parameter for this `stream`.
709    pub fn ty(&self) -> Option<Type> {
710        Some(Type::from(
711            self.0.types[self.0.index].payload.as_ref()?,
712            &self.0.instance(),
713        ))
714    }
715
716    #[cfg(feature = "component-model-async")]
717    pub(crate) fn equivalent_payload_guest(
718        &self,
719        ty: &InstanceType<'_>,
720        payload: Option<&InterfaceType>,
721    ) -> bool {
722        let my_payload = self.0.types[self.0.index].payload.as_ref();
723        match (my_payload, payload) {
724            (Some(a), Some(b)) => TypeChecker {
725                a_types: &self.0.types,
726                a_resource: self.0.resources.as_deref(),
727                b_types: ty.types,
728                b_resource: ty.resources.map(|p| &**p),
729            }
730            .interface_types_equal(*a, *b),
731            (None, None) => true,
732            (Some(_), None) | (None, Some(_)) => false,
733        }
734    }
735
736    #[cfg(feature = "component-model-async")]
737    pub(crate) fn equivalent_payload_host<T>(&self) -> crate::Result<()>
738    where
739        T: ComponentType,
740    {
741        typecheck_payload::<T>(
742            self.0.types[self.0.index].payload.as_ref(),
743            &self.0.instance(),
744        )
745    }
746}
747
748impl PartialEq for StreamType {
749    fn eq(&self, other: &Self) -> bool {
750        self.0.equivalent(&other.0, TypeChecker::streams_equal)
751    }
752}
753
754impl Eq for StreamType {}
755
756/// Represents a component model interface type
757#[derive(Clone, PartialEq, Eq, Debug)]
758#[expect(missing_docs, reason = "self-describing variants")]
759pub enum Type {
760    Bool,
761    S8,
762    U8,
763    S16,
764    U16,
765    S32,
766    U32,
767    S64,
768    U64,
769    Float32,
770    Float64,
771    Char,
772    String,
773    List(List),
774    Map(Map),
775    Record(Record),
776    Tuple(Tuple),
777    Variant(Variant),
778    Enum(Enum),
779    Option(OptionType),
780    Result(ResultType),
781    Flags(Flags),
782    Own(ResourceType),
783    Borrow(ResourceType),
784    Future(FutureType),
785    Stream(StreamType),
786    ErrorContext,
787    FixedLengthList(FixedLengthList),
788}
789
790impl Type {
791    /// Retrieve the inner [`List`] of a [`Type::List`].
792    ///
793    /// # Panics
794    ///
795    /// This will panic if `self` is not a [`Type::List`].
796    pub fn unwrap_list(&self) -> &List {
797        if let Type::List(handle) = self {
798            &handle
799        } else {
800            panic!("attempted to unwrap a {} as a list", self.desc())
801        }
802    }
803
804    /// Retrieve the inner [`Map`] of a [`Type::Map`].
805    ///
806    /// # Panics
807    ///
808    /// This will panic if `self` is not a [`Type::Map`].
809    pub fn unwrap_map(&self) -> &Map {
810        if let Type::Map(handle) = self {
811            &handle
812        } else {
813            panic!("attempted to unwrap a {} as a map", self.desc())
814        }
815    }
816
817    /// Retrieve the inner [`Record`] of a [`Type::Record`].
818    ///
819    /// # Panics
820    ///
821    /// This will panic if `self` is not a [`Type::Record`].
822    pub fn unwrap_record(&self) -> &Record {
823        if let Type::Record(handle) = self {
824            &handle
825        } else {
826            panic!("attempted to unwrap a {} as a record", self.desc())
827        }
828    }
829
830    /// Retrieve the inner [`Tuple`] of a [`Type::Tuple`].
831    ///
832    /// # Panics
833    ///
834    /// This will panic if `self` is not a [`Type::Tuple`].
835    pub fn unwrap_tuple(&self) -> &Tuple {
836        if let Type::Tuple(handle) = self {
837            &handle
838        } else {
839            panic!("attempted to unwrap a {} as a tuple", self.desc())
840        }
841    }
842
843    /// Retrieve the inner [`Variant`] of a [`Type::Variant`].
844    ///
845    /// # Panics
846    ///
847    /// This will panic if `self` is not a [`Type::Variant`].
848    pub fn unwrap_variant(&self) -> &Variant {
849        if let Type::Variant(handle) = self {
850            &handle
851        } else {
852            panic!("attempted to unwrap a {} as a variant", self.desc())
853        }
854    }
855
856    /// Retrieve the inner [`Enum`] of a [`Type::Enum`].
857    ///
858    /// # Panics
859    ///
860    /// This will panic if `self` is not a [`Type::Enum`].
861    pub fn unwrap_enum(&self) -> &Enum {
862        if let Type::Enum(handle) = self {
863            &handle
864        } else {
865            panic!("attempted to unwrap a {} as a enum", self.desc())
866        }
867    }
868
869    /// Retrieve the inner [`OptionType`] of a [`Type::Option`].
870    ///
871    /// # Panics
872    ///
873    /// This will panic if `self` is not a [`Type::Option`].
874    pub fn unwrap_option(&self) -> &OptionType {
875        if let Type::Option(handle) = self {
876            &handle
877        } else {
878            panic!("attempted to unwrap a {} as a option", self.desc())
879        }
880    }
881
882    /// Retrieve the inner [`ResultType`] of a [`Type::Result`].
883    ///
884    /// # Panics
885    ///
886    /// This will panic if `self` is not a [`Type::Result`].
887    pub fn unwrap_result(&self) -> &ResultType {
888        if let Type::Result(handle) = self {
889            &handle
890        } else {
891            panic!("attempted to unwrap a {} as a result", self.desc())
892        }
893    }
894
895    /// Retrieve the inner [`Flags`] of a [`Type::Flags`].
896    ///
897    /// # Panics
898    ///
899    /// This will panic if `self` is not a [`Type::Flags`].
900    pub fn unwrap_flags(&self) -> &Flags {
901        if let Type::Flags(handle) = self {
902            &handle
903        } else {
904            panic!("attempted to unwrap a {} as a flags", self.desc())
905        }
906    }
907
908    /// Retrieve the inner [`ResourceType`] of a [`Type::Own`].
909    ///
910    /// # Panics
911    ///
912    /// This will panic if `self` is not a [`Type::Own`].
913    pub fn unwrap_own(&self) -> &ResourceType {
914        match self {
915            Type::Own(ty) => ty,
916            _ => panic!("attempted to unwrap a {} as a own", self.desc()),
917        }
918    }
919
920    /// Retrieve the inner [`ResourceType`] of a [`Type::Borrow`].
921    ///
922    /// # Panics
923    ///
924    /// This will panic if `self` is not a [`Type::Borrow`].
925    pub fn unwrap_borrow(&self) -> &ResourceType {
926        match self {
927            Type::Borrow(ty) => ty,
928            _ => panic!("attempted to unwrap a {} as a own", self.desc()),
929        }
930    }
931
932    /// Convert the specified `InterfaceType` to a `Type`.
933    pub(crate) fn from(ty: &InterfaceType, instance: &InstanceType<'_>) -> Self {
934        match ty {
935            InterfaceType::Bool => Type::Bool,
936            InterfaceType::S8 => Type::S8,
937            InterfaceType::U8 => Type::U8,
938            InterfaceType::S16 => Type::S16,
939            InterfaceType::U16 => Type::U16,
940            InterfaceType::S32 => Type::S32,
941            InterfaceType::U32 => Type::U32,
942            InterfaceType::S64 => Type::S64,
943            InterfaceType::U64 => Type::U64,
944            InterfaceType::Float32 => Type::Float32,
945            InterfaceType::Float64 => Type::Float64,
946            InterfaceType::Char => Type::Char,
947            InterfaceType::String => Type::String,
948            InterfaceType::List(index) => Type::List(List::from(*index, instance)),
949            InterfaceType::Map(index) => Type::Map(Map::from(*index, instance)),
950            InterfaceType::Record(index) => Type::Record(Record::from(*index, instance)),
951            InterfaceType::Tuple(index) => Type::Tuple(Tuple::from(*index, instance)),
952            InterfaceType::Variant(index) => Type::Variant(Variant::from(*index, instance)),
953            InterfaceType::Enum(index) => Type::Enum(Enum::from(*index, instance)),
954            InterfaceType::Option(index) => Type::Option(OptionType::from(*index, instance)),
955            InterfaceType::Result(index) => Type::Result(ResultType::from(*index, instance)),
956            InterfaceType::Flags(index) => Type::Flags(Flags::from(*index, instance)),
957            InterfaceType::Own(index) => Type::Own(instance.resource_type(*index)),
958            InterfaceType::Borrow(index) => Type::Borrow(instance.resource_type(*index)),
959            InterfaceType::Future(index) => Type::Future(instance.future_type(*index)),
960            InterfaceType::Stream(index) => Type::Stream(instance.stream_type(*index)),
961            InterfaceType::ErrorContext(_) => Type::ErrorContext,
962            InterfaceType::FixedLengthList(index) => {
963                Type::FixedLengthList(FixedLengthList::from(*index, instance))
964            }
965        }
966    }
967
968    /// Construct a default value of this type, if one exists.
969    ///
970    /// Defaults are the "empty" or "zero" value of each type: zero for the
971    /// numerics, the empty `string`/`list`, `none` for `option`, `ok` for
972    /// `result`, no flags set, and the first case of a `variant` or `enum`.
973    ///
974    /// An `own` or `borrow` of a host-defined resource defaults to a fresh
975    /// handle in `store`, with an arbitrary representation and no destructor.
976    /// Nothing can be done with such a handle beyond passing it back to the
977    /// component that the resource was defined for.
978    ///
979    /// # Errors
980    ///
981    /// Returns an error for an `own` or `borrow` of a guest-defined resource,
982    /// whose representation belongs to the guest and so cannot be conjured by
983    /// the host.
984    ///
985    /// Returns an error for `future`, `stream`, and `error-context`, as there
986    /// is currently no way to synthesize these without statically knowing
987    /// their payload type.
988    ///
989    /// An aggregate containing any of the above is an error for the same
990    /// reason.
991    ///
992    /// This function will return an [`OutOfMemory`][crate::OutOfMemory] error
993    /// when memory allocation fails. See the `OutOfMemory` type's
994    /// documentation for details on Wasmtime's out-of-memory handling.
995    pub fn default_value(&self, mut store: impl AsContextMut) -> Result<Val> {
996        self.default_value_impl(store.as_context_mut())
997    }
998
999    /// Recursive implementation of `default_value`.
1000    fn default_value_impl<T>(&self, mut store: StoreContextMut<'_, T>) -> Result<Val> {
1001        Ok(match self {
1002            Type::Bool => Val::Bool(false),
1003            Type::S8 => Val::S8(0),
1004            Type::U8 => Val::U8(0),
1005            Type::S16 => Val::S16(0),
1006            Type::U16 => Val::U16(0),
1007            Type::S32 => Val::S32(0),
1008            Type::U32 => Val::U32(0),
1009            Type::S64 => Val::S64(0),
1010            Type::U64 => Val::U64(0),
1011            Type::Float32 => Val::Float32(0.0),
1012            Type::Float64 => Val::Float64(0.0),
1013            Type::Char => Val::Char('\0'),
1014            Type::String => Val::String(String::new()),
1015
1016            // These never visit their payload types.
1017            Type::List(_) => Val::List(Vec::new()),
1018            Type::Map(_) => Val::Map(Vec::new()),
1019            Type::Option(_) => Val::Option(None),
1020            Type::Flags(_) => Val::Flags(Vec::new()),
1021
1022            Type::Enum(e) => {
1023                let name = e.names().next().ok_or_else(|| {
1024                    format_err!("no default value exists for an `enum` with no cases")
1025                })?;
1026                Val::Enum(name.to_string())
1027            }
1028
1029            Type::Record(record) => {
1030                let mut fields = TryVec::with_capacity(record.fields().len())?;
1031                for field in record.fields() {
1032                    let val = field.ty.default_value_impl(store.as_context_mut())?;
1033                    fields.push((field.name.to_string(), val))?;
1034                }
1035                Val::Record(fields.into())
1036            }
1037
1038            Type::Tuple(tuple) => {
1039                let mut vals = TryVec::with_capacity(tuple.types().len())?;
1040                for ty in tuple.types() {
1041                    vals.push(ty.default_value_impl(store.as_context_mut())?)?;
1042                }
1043                Val::Tuple(vals.into())
1044            }
1045
1046            Type::Variant(variant) => {
1047                let case = variant.cases().next().ok_or_else(|| {
1048                    format_err!("no default value exists for a `variant` with no cases")
1049                })?;
1050                let payload = match &case.ty {
1051                    Some(ty) => Some(Box::new(ty.default_value_impl(store.as_context_mut())?)),
1052                    None => None,
1053                };
1054                Val::Variant(case.name.to_string(), payload)
1055            }
1056
1057            Type::Result(result) => Val::Result(Ok(match result.ok() {
1058                Some(ty) => Some(Box::new(ty.default_value_impl(store.as_context_mut())?)),
1059                None => None,
1060            })),
1061
1062            Type::FixedLengthList(list) => {
1063                // Every element has the same type, so one value is cloned.
1064                let element = list.ty().default_value_impl(store.as_context_mut())?;
1065                let len = usize::try_from(list.len())?;
1066                let mut vals = TryVec::with_capacity(len)?;
1067                for _ in 0..len {
1068                    vals.push(element.clone())?;
1069                }
1070                Val::FixedLengthList(vals.into())
1071            }
1072
1073            // The `rep` is arbitrary and never dereferenced: there is no
1074            // destructor, and the handle is opaque to everything but the
1075            // component that defines the resource.
1076            Type::Own(ty) | Type::Borrow(ty) => {
1077                Val::Resource(ResourceAny::new_own_dynamic(*ty, 0, &mut store)?)
1078            }
1079
1080            Type::Future(_) | Type::Stream(_) | Type::ErrorContext => {
1081                bail!("no default value exists for type `{}`", self.desc())
1082            }
1083        })
1084    }
1085
1086    fn desc(&self) -> &'static str {
1087        match self {
1088            Type::Bool => "bool",
1089            Type::S8 => "s8",
1090            Type::U8 => "u8",
1091            Type::S16 => "s16",
1092            Type::U16 => "u16",
1093            Type::S32 => "s32",
1094            Type::U32 => "u32",
1095            Type::S64 => "s64",
1096            Type::U64 => "u64",
1097            Type::Float32 => "float32",
1098            Type::Float64 => "float64",
1099            Type::Char => "char",
1100            Type::String => "string",
1101            Type::List(_) => "list",
1102            Type::Map(_) => "map",
1103            Type::Record(_) => "record",
1104            Type::Tuple(_) => "tuple",
1105            Type::Variant(_) => "variant",
1106            Type::Enum(_) => "enum",
1107            Type::Option(_) => "option",
1108            Type::Result(_) => "result",
1109            Type::Flags(_) => "flags",
1110            Type::Own(_) => "own",
1111            Type::Borrow(_) => "borrow",
1112            Type::Future(_) => "future",
1113            Type::Stream(_) => "stream",
1114            Type::ErrorContext => "error-context",
1115            Type::FixedLengthList(_) => "list<_, N>",
1116        }
1117    }
1118}
1119
1120/// Component function type
1121#[derive(Clone, Debug)]
1122pub struct ComponentFunc(Handle<TypeFuncIndex>);
1123
1124impl ComponentFunc {
1125    pub(crate) fn from(index: TypeFuncIndex, ty: &InstanceType<'_>) -> Self {
1126        Self(Handle::new(index, ty))
1127    }
1128
1129    /// Returns whether this is an async function
1130    pub fn async_(&self) -> bool {
1131        self.0.types[self.0.index].async_
1132    }
1133
1134    /// Iterates over types of function parameters and names.
1135    pub fn params(&self) -> impl ExactSizeIterator<Item = (&str, Type)> + '_ {
1136        let ty = &self.0.types[self.0.index];
1137        self.0.types[ty.params]
1138            .types
1139            .iter()
1140            .zip(&ty.param_names)
1141            .map(|(ty, name)| (name.as_str(), Type::from(ty, &self.0.instance())))
1142    }
1143
1144    /// Iterates over types of function results
1145    pub fn results(&self) -> impl ExactSizeIterator<Item = Type> + '_ {
1146        let results = self.0.types[self.0.index].results;
1147        self.0.types[results]
1148            .types
1149            .iter()
1150            .map(|ty| Type::from(ty, &self.0.instance()))
1151    }
1152
1153    #[doc(hidden)]
1154    pub fn typecheck<Params, Return>(&self, cx: &InstanceType) -> crate::Result<()>
1155    where
1156        Params: crate::component::ComponentNamedList + crate::component::Lower,
1157        Return: crate::component::ComponentNamedList + crate::component::Lift,
1158    {
1159        let ty = &self.0.types[self.0.index];
1160        Params::typecheck(&InterfaceType::Tuple(ty.params), cx)?;
1161        Return::typecheck(&InterfaceType::Tuple(ty.results), cx)?;
1162        Ok(())
1163    }
1164}
1165
1166/// Core module type
1167#[derive(Clone, Debug)]
1168pub struct Module(Handle<TypeModuleIndex>);
1169
1170impl Module {
1171    pub(crate) fn from(index: TypeModuleIndex, ty: &InstanceType<'_>) -> Self {
1172        Self(Handle::new(index, ty))
1173    }
1174
1175    /// Iterates over imports of the module
1176    ///
1177    /// # Panics
1178    ///
1179    /// The `engine` provided must be the [`Engine`] that this type's component
1180    /// was compiled with. This method may panic, or return types that don't
1181    /// describe this component, if it's a different [`Engine`].
1182    pub fn imports<'a>(
1183        &'a self,
1184        engine: &'a Engine,
1185    ) -> impl ExactSizeIterator<Item = ((&'a str, &'a str), ExternType)> + 'a {
1186        self.0.types[self.0.index]
1187            .imports
1188            .iter()
1189            .map(|((namespace, name), ty)| {
1190                (
1191                    (namespace.as_str(), name.as_str()),
1192                    ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
1193                )
1194            })
1195    }
1196
1197    /// Iterates over exports of the module
1198    ///
1199    /// # Panics
1200    ///
1201    /// The `engine` provided must be the [`Engine`] that this type's component
1202    /// was compiled with. This method may panic, or return types that don't
1203    /// describe this component, if it's a different [`Engine`].
1204    pub fn exports<'a>(
1205        &'a self,
1206        engine: &'a Engine,
1207    ) -> impl ExactSizeIterator<Item = (&'a str, ExternType)> + 'a {
1208        self.0.types[self.0.index].exports.iter().map(|(name, ty)| {
1209            (
1210                name.as_str(),
1211                ExternType::from_wasmtime(engine, self.0.types.module_types(), ty),
1212            )
1213        })
1214    }
1215}
1216
1217/// Component type
1218#[derive(Clone, Debug)]
1219pub struct Component(Handle<TypeComponentIndex>);
1220
1221impl Component {
1222    pub(crate) fn from(index: TypeComponentIndex, ty: &InstanceType<'_>) -> Self {
1223        Self(Handle::new(index, ty))
1224    }
1225
1226    /// Returns import associated with `name`, if such exists in the component
1227    ///
1228    /// # Panics
1229    ///
1230    /// The `engine` provided must be the [`Engine`] that this type's component
1231    /// was compiled with. This method may panic, or return types that don't
1232    /// describe this component, if it's a different [`Engine`].
1233    pub fn get_import<'a>(&'a self, engine: &'a Engine, name: &str) -> Option<ComponentExtern<'a>> {
1234        self.0.types[self.0.index]
1235            .imports
1236            .get(name)
1237            .map(|e| ComponentExtern::new(engine, &self.0.instance(), e))
1238    }
1239
1240    /// Iterates over imports of the component
1241    ///
1242    /// # Panics
1243    ///
1244    /// The `engine` provided must be the [`Engine`] that this type's component
1245    /// was compiled with. This method may panic, or return types that don't
1246    /// describe this component, if it's a different [`Engine`].
1247    pub fn imports<'a>(
1248        &'a self,
1249        engine: &'a Engine,
1250    ) -> impl ExactSizeIterator<Item = (&'a str, ComponentExtern<'a>)> + 'a {
1251        self.0.types[self.0.index].imports.iter().map(|(name, e)| {
1252            (
1253                name.as_str(),
1254                ComponentExtern::new(engine, &self.0.instance(), e),
1255            )
1256        })
1257    }
1258
1259    /// Returns export associated with `name`, if such exists in the component
1260    ///
1261    /// # Panics
1262    ///
1263    /// The `engine` provided must be the [`Engine`] that this type's component
1264    /// was compiled with. This method may panic, or return types that don't
1265    /// describe this component, if it's a different [`Engine`].
1266    pub fn get_export<'a>(&'a self, engine: &'a Engine, name: &str) -> Option<ComponentExtern<'a>> {
1267        self.0.types[self.0.index]
1268            .exports
1269            .get(name)
1270            .map(|e| ComponentExtern::new(engine, &self.0.instance(), e))
1271    }
1272
1273    /// Iterates over exports of the component
1274    ///
1275    /// # Panics
1276    ///
1277    /// The `engine` provided must be the [`Engine`] that this type's component
1278    /// was compiled with. This method may panic, or return types that don't
1279    /// describe this component, if it's a different [`Engine`].
1280    pub fn exports<'a>(
1281        &'a self,
1282        engine: &'a Engine,
1283    ) -> impl ExactSizeIterator<Item = (&'a str, ComponentExtern<'a>)> + 'a {
1284        self.0.types[self.0.index].exports.iter().map(|(name, e)| {
1285            (
1286                name.as_str(),
1287                ComponentExtern::new(engine, &self.0.instance(), e),
1288            )
1289        })
1290    }
1291
1292    #[doc(hidden)]
1293    pub fn instance_type(&self) -> InstanceType<'_> {
1294        InstanceType {
1295            types: &self.0.types,
1296            resources: self.0.resources.as_ref(),
1297        }
1298    }
1299}
1300
1301/// Component instance type
1302#[derive(Clone, Debug)]
1303pub struct ComponentInstance(Handle<TypeComponentInstanceIndex>);
1304
1305impl ComponentInstance {
1306    pub(crate) fn from(index: TypeComponentInstanceIndex, ty: &InstanceType<'_>) -> Self {
1307        Self(Handle::new(index, ty))
1308    }
1309
1310    /// Returns export associated with `name`, if such exists in the component instance
1311    ///
1312    /// # Panics
1313    ///
1314    /// The `engine` provided must be the [`Engine`] that this type's component
1315    /// was compiled with. This method may panic, or return types that don't
1316    /// describe this component, if it's a different [`Engine`].
1317    pub fn get_export<'a>(&'a self, engine: &'a Engine, name: &str) -> Option<ComponentExtern<'a>> {
1318        self.0.types[self.0.index]
1319            .exports
1320            .get(name)
1321            .map(|e| ComponentExtern::new(engine, &self.0.instance(), e))
1322    }
1323
1324    /// Iterates over exports of the component instance
1325    ///
1326    /// # Panics
1327    ///
1328    /// The `engine` provided must be the [`Engine`] that this type's component
1329    /// was compiled with. This method may panic, or return types that don't
1330    /// describe this component, if it's a different [`Engine`].
1331    pub fn exports<'a>(
1332        &'a self,
1333        engine: &'a Engine,
1334    ) -> impl ExactSizeIterator<Item = (&'a str, ComponentExtern<'a>)> {
1335        self.0.types[self.0.index].exports.iter().map(|(name, e)| {
1336            (
1337                name.as_str(),
1338                ComponentExtern::new(engine, &self.0.instance(), e),
1339            )
1340        })
1341    }
1342}
1343
1344/// An import or an export from either [`Component`] or [`ComponentInstance`].
1345///
1346/// This records the type of the item that is being imported or exported along
1347/// with any other metadata associated.
1348#[derive(Clone, Debug)]
1349pub struct ComponentExtern<'a> {
1350    /// The type of this item.
1351    pub ty: ComponentItem,
1352    /// The `(implements "...")` annotation, if present.
1353    pub implements: Option<&'a str>,
1354    /// The `(external-id "...")` annotation, if present.
1355    ///
1356    /// This is a free-form host-defined identifier and is intended to indicate
1357    /// how the host should satisfy an import (or interpret an export).
1358    pub external_id: Option<&'a str>,
1359}
1360
1361impl<'a> ComponentExtern<'a> {
1362    fn new(
1363        engine: &'a Engine,
1364        instance_ty: &InstanceType<'_>,
1365        env: &'a wasmtime_environ::component::ComponentExtern,
1366    ) -> Self {
1367        Self {
1368            implements: env.data.implements.as_deref(),
1369            external_id: env.data.external_id.as_deref(),
1370            ty: ComponentItem::from(engine, &env.ty, instance_ty),
1371        }
1372    }
1373
1374    /// Returns whether this item is tagged with `(implements "..")` with an
1375    /// interface that's compatible with `name`.
1376    ///
1377    /// This function will return `false` if `(implements "...")` is not
1378    /// present. If it is present, and it's equal to `name`, then `true` is
1379    /// returned. Failing that, this attempts to perform version-matching to see
1380    /// if a compatible version of this item is implemented. For example if
1381    /// `(implements "a:b/c@1.1.0")` is specified then this will return `true`
1382    /// for `a:b/c@1.0.0` and `a:b/c@1.2.0` as well. The same goes for a
1383    /// canonical name such as `(implements "a:b/c@1")`.
1384    pub fn is_implements(&self, name: &str) -> bool {
1385        let implements = match self.implements {
1386            Some(s) => s,
1387            None => return false,
1388        };
1389        if name == implements {
1390            return true;
1391        }
1392
1393        // Compare semver-compatible versions in their reduced form, for
1394        // example `a:b/c@1.2.0` as `a:b/c@1`. Canonical names are already in
1395        // that form, so they're compared as-is.
1396        let reduced = |name| alternate_lookup_key(name).map_or(name, |(name, _)| name);
1397        reduced(implements) == reduced(name)
1398    }
1399}
1400
1401/// Type of an item contained within the component
1402#[derive(Clone, Debug)]
1403pub enum ComponentItem {
1404    /// Component function item
1405    ComponentFunc(ComponentFunc),
1406    /// Core function item
1407    CoreFunc(FuncType),
1408    /// Core module item
1409    Module(Module),
1410    /// Component item
1411    Component(Component),
1412    /// Component instance item
1413    ComponentInstance(ComponentInstance),
1414    /// Interface type item
1415    Type(Type),
1416    /// Resource item
1417    Resource(ResourceType),
1418}
1419
1420impl ComponentItem {
1421    pub(crate) fn from(engine: &Engine, def: &TypeDef, ty: &InstanceType<'_>) -> Self {
1422        match def {
1423            TypeDef::Component(idx) => Self::Component(Component::from(*idx, ty)),
1424            TypeDef::ComponentInstance(idx) => {
1425                Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1426            }
1427            TypeDef::ComponentFunc(idx) => Self::ComponentFunc(ComponentFunc::from(*idx, ty)),
1428            TypeDef::Interface(iface_ty) => Self::Type(Type::from(iface_ty, ty)),
1429            TypeDef::Module(idx) => Self::Module(Module::from(*idx, ty)),
1430            TypeDef::CoreFunc(idx) => {
1431                let subty = &ty.types[*idx];
1432                Self::CoreFunc(
1433                    FuncType::from_wasm_func_type(
1434                        engine,
1435                        subty.is_final,
1436                        subty.supertype,
1437                        subty.unwrap_func().try_clone().panic_on_oom(),
1438                    )
1439                    .panic_on_oom(),
1440                )
1441            }
1442            TypeDef::Resource(idx) => match ty.types[*idx] {
1443                TypeResourceTable::Concrete {
1444                    ty: resource_index, ..
1445                } => {
1446                    let ty = match ty.resources.and_then(|t| t.get(resource_index)) {
1447                        // This resource type was substituted by a linker for
1448                        // example so it's replaced here.
1449                        Some(ty) => *ty,
1450
1451                        // This resource type was not substituted.
1452                        None => ResourceType::uninstantiated(&ty.types, resource_index),
1453                    };
1454                    Self::Resource(ty)
1455                }
1456                TypeResourceTable::Abstract(resource_index) => {
1457                    Self::Resource(ResourceType::abstract_(&ty.types, resource_index))
1458                }
1459            },
1460        }
1461    }
1462    pub(crate) fn from_export(engine: &Engine, export: &Export, ty: &InstanceType<'_>) -> Self {
1463        match export {
1464            Export::Instance { ty: idx, .. } => {
1465                Self::ComponentInstance(ComponentInstance::from(*idx, ty))
1466            }
1467            Export::LiftedFunction { ty: idx, .. } => {
1468                Self::ComponentFunc(ComponentFunc::from(*idx, ty))
1469            }
1470            Export::ModuleStatic { ty: idx, .. } | Export::ModuleImport { ty: idx, .. } => {
1471                Self::Module(Module::from(*idx, ty))
1472            }
1473            Export::Type(idx) => Self::from(engine, idx, ty),
1474        }
1475    }
1476}