wasm_compose/
encoding.rs

1use crate::graph::{
2    CompositionGraph, EncodeOptions, ExportIndex, ImportIndex, InstanceId, type_desc,
3};
4use anyhow::{Result, anyhow, bail};
5use indexmap::{IndexMap, IndexSet};
6use petgraph::EdgeDirection;
7use smallvec::SmallVec;
8use std::collections::{HashMap, hash_map::Entry};
9use std::mem;
10use wasm_encoder::*;
11use wasmparser::{
12    ComponentExternalKind,
13    component_types::{
14        self as ct, AnyTypeId, ComponentAnyTypeId, ComponentCoreModuleTypeId, ComponentCoreTypeId,
15        ComponentDefinedType, ComponentDefinedTypeId, ComponentEntityType, ComponentFuncTypeId,
16        ComponentInstanceTypeId, ComponentTypeId, RecordType, Remap, Remapping, ResourceId,
17        SubtypeCx, TupleType, VariantType,
18    },
19    names::KebabString,
20    types,
21};
22
23fn type_ref_to_export_kind(ty: wasmparser::ComponentTypeRef) -> ComponentExportKind {
24    match ty {
25        wasmparser::ComponentTypeRef::Module(_) => ComponentExportKind::Module,
26        wasmparser::ComponentTypeRef::Func(_) => ComponentExportKind::Func,
27        wasmparser::ComponentTypeRef::Value(_) => ComponentExportKind::Value,
28        wasmparser::ComponentTypeRef::Type { .. } => ComponentExportKind::Type,
29        wasmparser::ComponentTypeRef::Instance(_) => ComponentExportKind::Instance,
30        wasmparser::ComponentTypeRef::Component(_) => ComponentExportKind::Component,
31    }
32}
33
34enum Encodable {
35    Component(ComponentType),
36    Instance(InstanceType),
37    Builder(ComponentBuilder),
38}
39
40impl Encodable {
41    fn type_count(&self) -> u32 {
42        match self {
43            Encodable::Component(t) => t.type_count(),
44            Encodable::Instance(t) => t.type_count(),
45            Encodable::Builder(t) => t.type_count(),
46        }
47    }
48
49    fn instance_count(&self) -> u32 {
50        match self {
51            Encodable::Component(t) => t.instance_count(),
52            Encodable::Instance(t) => t.instance_count(),
53            Encodable::Builder(t) => t.instance_count(),
54        }
55    }
56
57    fn core_type_count(&self) -> u32 {
58        match self {
59            Encodable::Component(t) => t.core_type_count(),
60            Encodable::Instance(t) => t.core_type_count(),
61            Encodable::Builder(t) => t.core_type_count(),
62        }
63    }
64
65    fn ty(&mut self) -> ComponentTypeEncoder<'_> {
66        match self {
67            Encodable::Component(t) => t.ty(),
68            Encodable::Instance(t) => t.ty(),
69            Encodable::Builder(t) => t.ty(None).1,
70        }
71    }
72
73    fn core_type(&mut self) -> ComponentCoreTypeEncoder<'_> {
74        match self {
75            Encodable::Component(t) => t.core_type(),
76            Encodable::Instance(t) => t.core_type(),
77            Encodable::Builder(t) => t.core_type(None).1,
78        }
79    }
80
81    fn alias(&mut self, alias: Alias<'_>) {
82        match self {
83            Encodable::Component(t) => {
84                t.alias(alias);
85            }
86            Encodable::Instance(t) => {
87                t.alias(alias);
88            }
89            Encodable::Builder(t) => {
90                t.alias(None, alias);
91            }
92        }
93    }
94}
95
96/// Metadata necessary to track type definitions across both instances and also
97/// across unioning components.
98///
99/// This state is used when assembling the imports into a composed component.
100/// The imported instances will have types that are intended to mirror the
101/// original source components which means that the type structure, such as
102/// aliases, additionally needs to be mirrored. This structure keeps track of
103/// type scopes and is used throughout type translation to facilitate this.
104pub(crate) struct TypeState<'a> {
105    // Current outer scopes of this state which can be referred to with
106    // `alias outer`
107    scopes: Vec<TypeScope<'a>>,
108
109    // Current type scope that's being translated into.
110    cur: TypeScope<'a>,
111
112    remapping: HashMap<ResourceId, (&'a crate::graph::Component<'a>, ResourceId)>,
113}
114
115/// A unique key identifying a type.
116///
117/// Note that this has two components: the first is the component that a type
118/// comes from and the second is the wasmparser-unique id for within that
119/// component.
120type TypeKey<'a> = (PtrKey<'a, crate::graph::Component<'a>>, AnyTypeId);
121
122/// A scope that types can be defined into.
123///
124/// This is stored within `TypeState` and contains all the relevant information
125/// for mirroring a preexisting wasmparser-defined structure of types into a
126/// new component type (such as an instance for an instance import).
127struct TypeScope<'a> {
128    /// Types defined in this current scope.
129    ///
130    /// Contains the type index that the type is defined at.
131    type_defs: HashMap<TypeKey<'a>, u32>,
132
133    /// Types exported in the current scope.
134    ///
135    /// This is filled out during `export` and indicates that a particular type
136    /// is exported with the specified name.
137    type_exports: HashMap<TypeKey<'a>, &'a str>,
138
139    /// Reverse of the `type_exports` map, indicating which name exports which
140    /// types.
141    ///
142    /// Note that this can export a "list" of types which represents that
143    /// multiple components may be "unioned" together to create a single
144    /// instance import, so exporting a type can have different names as each
145    /// original component may have ID for the same export name.
146    ///
147    /// This enables translating type-use situations where one component
148    /// translates the base type and then a second component refers to that.
149    type_exports_rev: HashMap<&'a str, Vec<TypeKey<'a>>>,
150
151    /// Instances that are available to alias from in this scope.
152    ///
153    /// This map is keyed by the types that are available to be referred to.
154    /// The value here is the instance index that the type is defined in along
155    /// with its export name. This is used to generate `alias export` items.
156    instance_exports: HashMap<TypeKey<'a>, (u32, &'a str)>,
157
158    /// Encoded representation of this type scope, a `wasm-encoder` structure.
159    encodable: Encodable,
160}
161
162impl<'a> TypeState<'a> {
163    fn new() -> TypeState<'a> {
164        Self::new_with_remapping(HashMap::new())
165    }
166
167    fn new_with_remapping(
168        remapping: HashMap<ResourceId, (&'a crate::graph::Component<'a>, ResourceId)>,
169    ) -> TypeState<'a> {
170        TypeState {
171            scopes: Vec::new(),
172            cur: TypeScope {
173                type_exports: HashMap::new(),
174                type_exports_rev: HashMap::new(),
175                instance_exports: HashMap::new(),
176                type_defs: HashMap::new(),
177                encodable: Encodable::Builder(Default::default()),
178            },
179            remapping,
180        }
181    }
182
183    /// Pushes a new scope which will be written to the `encodable` provided.
184    fn push(&mut self, encodable: Encodable) {
185        let prev = mem::replace(
186            &mut self.cur,
187            TypeScope {
188                type_exports: HashMap::new(),
189                type_exports_rev: HashMap::new(),
190                instance_exports: HashMap::new(),
191                type_defs: HashMap::new(),
192                encodable,
193            },
194        );
195        self.scopes.push(prev);
196    }
197
198    /// Pops a previously pushed scope and returns the encoding.
199    fn pop(&mut self) -> Encodable {
200        let prev = mem::replace(&mut self.cur, self.scopes.pop().unwrap());
201
202        // If the previous scope was an instance then assume that the instance
203        // type is about to be used as an import or export which defines a new
204        // instance that this previously-outer-now-current scope has access to.
205        //
206        // This scope then takes all of the type exports of the created instance
207        // and registers them as available at this next instance index.
208        if let Encodable::Instance(_) = &prev.encodable {
209            let idx = self.cur.encodable.instance_count();
210            for (id, name) in prev.type_exports {
211                let prev = self.cur.instance_exports.insert(id, (idx, name));
212                assert!(prev.is_none());
213            }
214        }
215
216        prev.encodable
217    }
218}
219
220impl Default for TypeState<'_> {
221    fn default() -> Self {
222        Self::new()
223    }
224}
225
226impl<'a> TypeScope<'a> {
227    /// Registers that `ty` is exported as `name`, filling in both type export
228    /// maps at the same time.
229    fn add_type_export(&mut self, ty: TypeKey<'a>, name: &'a str) {
230        let prev = self.type_exports.insert(ty, name);
231        assert!(prev.is_none());
232        self.type_exports_rev.entry(name).or_default().push(ty);
233    }
234}
235
236pub struct PtrKey<'a, T>(&'a T);
237
238impl<T> PartialEq for PtrKey<'_, T> {
239    fn eq(&self, other: &Self) -> bool {
240        std::ptr::eq(self.0, other.0)
241    }
242}
243
244impl<T> Eq for PtrKey<'_, T> {}
245
246impl<T> Copy for PtrKey<'_, T> {}
247
248impl<T> Clone for PtrKey<'_, T> {
249    fn clone(&self) -> Self {
250        *self
251    }
252}
253
254impl<T> std::hash::Hash for PtrKey<'_, T> {
255    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
256        std::ptr::hash(self.0, state);
257    }
258}
259
260pub(crate) struct TypeEncoder<'a>(&'a crate::graph::Component<'a>);
261
262impl<'a> TypeEncoder<'a> {
263    pub fn new(component: &'a crate::graph::Component) -> Self {
264        Self(component)
265    }
266
267    pub fn component<I, E>(
268        &self,
269        state: &mut TypeState<'a>,
270        imports: I,
271        exports: E,
272    ) -> ComponentType
273    where
274        I: IntoIterator<Item = (&'a str, ComponentEntityType)>,
275        E: IntoIterator<Item = (&'a str, ComponentEntityType)>,
276    {
277        state.push(Encodable::Component(ComponentType::new()));
278
279        for (name, ty) in imports {
280            let ty = self.component_entity_type(state, ty);
281            let c = match &mut state.cur.encodable {
282                Encodable::Component(c) => c,
283                _ => unreachable!(),
284            };
285            c.import(name, ty);
286        }
287
288        for (name, ty) in exports {
289            let export = self.export(name, ty, state);
290            let c = match &mut state.cur.encodable {
291                Encodable::Component(c) => c,
292                _ => unreachable!(),
293            };
294            c.export(name, export);
295        }
296
297        match state.pop() {
298            Encodable::Component(c) => c,
299            _ => unreachable!(),
300        }
301    }
302
303    pub fn instance<E>(&self, state: &mut TypeState<'a>, exports: E) -> InstanceType
304    where
305        E: IntoIterator<Item = (&'a str, ComponentEntityType)>,
306    {
307        state.push(Encodable::Instance(InstanceType::new()));
308
309        for (name, ty) in exports {
310            let export = self.export(name, ty, state);
311            let c = match &mut state.cur.encodable {
312                Encodable::Instance(c) => c,
313                _ => unreachable!(),
314            };
315            c.export(name, export);
316        }
317
318        match state.pop() {
319            Encodable::Instance(c) => c,
320            _ => unreachable!(),
321        }
322    }
323
324    pub fn module<I, E>(&self, imports: I, exports: E) -> ModuleType
325    where
326        I: IntoIterator<Item = (&'a str, &'a str, wasmparser::types::EntityType)>,
327        E: IntoIterator<Item = (&'a str, wasmparser::types::EntityType)>,
328    {
329        let mut encoded = ModuleType::new();
330        let mut types = HashMap::default();
331
332        for (module, name, ty) in imports {
333            let ty = self.entity_type(&mut encoded, &mut types, ty);
334            encoded.import(module, name, ty);
335        }
336
337        for (name, ty) in exports {
338            let ty = self.entity_type(&mut encoded, &mut types, ty);
339            encoded.export(name, ty);
340        }
341
342        encoded
343    }
344
345    fn entity_type(
346        &self,
347        encodable: &mut ModuleType,
348        types: &mut HashMap<AnyTypeId, u32>,
349        ty: wasmparser::types::EntityType,
350    ) -> EntityType {
351        match ty {
352            wasmparser::types::EntityType::Func(id) => {
353                let ty = &self.0.types[id].unwrap_func();
354                let idx = match types.entry(ComponentCoreTypeId::Sub(id).into()) {
355                    Entry::Occupied(e) => *e.get(),
356                    Entry::Vacant(e) => {
357                        let index = encodable.type_count();
358                        encodable.ty().function(
359                            ty.params().iter().copied().map(Self::val_type),
360                            ty.results().iter().copied().map(Self::val_type),
361                        );
362                        *e.insert(index)
363                    }
364                };
365                EntityType::Function(idx)
366            }
367            wasmparser::types::EntityType::Table(ty) => EntityType::Table(ty.try_into().unwrap()),
368            wasmparser::types::EntityType::Memory(ty) => EntityType::Memory(ty.into()),
369            wasmparser::types::EntityType::Global(ty) => EntityType::Global(ty.try_into().unwrap()),
370            wasmparser::types::EntityType::Tag(id) => {
371                let ty = &self.0.types[id];
372                let idx = match types.entry(ComponentCoreTypeId::Sub(id).into()) {
373                    Entry::Occupied(e) => *e.get(),
374                    Entry::Vacant(e) => {
375                        let ty = ty.unwrap_func();
376                        let index = encodable.type_count();
377                        encodable.ty().function(
378                            ty.params().iter().copied().map(Self::val_type),
379                            ty.results().iter().copied().map(Self::val_type),
380                        );
381                        *e.insert(index)
382                    }
383                };
384                EntityType::Tag(TagType {
385                    kind: TagKind::Exception,
386                    func_type_idx: idx,
387                })
388            }
389        }
390    }
391
392    fn component_entity_type(
393        &self,
394        state: &mut TypeState<'a>,
395        ty: ComponentEntityType,
396    ) -> ComponentTypeRef {
397        match ty {
398            ComponentEntityType::Module(id) => ComponentTypeRef::Module(self.ty(state, id.into())),
399            ComponentEntityType::Func(id) => ComponentTypeRef::Func(self.ty(state, id.into())),
400            ComponentEntityType::Value(ty) => {
401                ComponentTypeRef::Value(self.component_val_type(state, ty))
402            }
403            ComponentEntityType::Type {
404                created: created @ ComponentAnyTypeId::Resource(_),
405                referenced,
406            } => {
407                if created == referenced {
408                    log::trace!("creation of a new resource");
409                    ComponentTypeRef::Type(TypeBounds::SubResource)
410                } else {
411                    log::trace!("alias of an existing resource");
412                    ComponentTypeRef::Type(TypeBounds::Eq(self.ty(state, referenced.into())))
413                }
414            }
415            ComponentEntityType::Type { referenced, .. } => {
416                ComponentTypeRef::Type(TypeBounds::Eq(self.ty(state, referenced.into())))
417            }
418            ComponentEntityType::Instance(id) => {
419                ComponentTypeRef::Instance(self.ty(state, id.into()))
420            }
421            ComponentEntityType::Component(id) => {
422                ComponentTypeRef::Component(self.ty(state, id.into()))
423            }
424        }
425    }
426
427    fn val_type(ty: wasmparser::ValType) -> ValType {
428        ty.try_into().unwrap()
429    }
430
431    fn module_type(&self, state: &mut TypeState<'a>, id: ComponentCoreModuleTypeId) -> u32 {
432        let ty = &self.0.types[id];
433
434        let module = self.module(
435            ty.imports
436                .iter()
437                .map(|((m, n), t)| (m.as_str(), n.as_str(), *t)),
438            ty.exports.iter().map(|(n, t)| (n.as_str(), *t)),
439        );
440
441        let index = state.cur.encodable.core_type_count();
442        state.cur.encodable.core_type().module(&module);
443        index
444    }
445
446    fn component_instance_type(
447        &self,
448        state: &mut TypeState<'a>,
449        id: ComponentInstanceTypeId,
450    ) -> u32 {
451        let ty = &self.0.types[id];
452        let instance = self.instance(state, ty.exports.iter().map(|(n, t)| (n.as_str(), *t)));
453        let index = state.cur.encodable.type_count();
454        state.cur.encodable.ty().instance(&instance);
455        index
456    }
457
458    fn component_type(&self, state: &mut TypeState<'a>, id: ComponentTypeId) -> u32 {
459        let ty = &self.0.types[id];
460
461        let component = self.component(
462            state,
463            ty.imports.iter().map(|(n, t)| (n.as_str(), *t)),
464            ty.exports.iter().map(|(n, t)| (n.as_str(), *t)),
465        );
466
467        let index = state.cur.encodable.type_count();
468        state.cur.encodable.ty().component(&component);
469        index
470    }
471
472    fn component_func_type(&self, state: &mut TypeState<'a>, id: ComponentFuncTypeId) -> u32 {
473        let ty = &self.0.types[id];
474        let params = ty
475            .params
476            .iter()
477            .map(|(name, ty)| (name.as_str(), self.component_val_type(state, *ty)))
478            .collect::<Vec<_>>();
479
480        let result = ty.result.map(|ty| self.component_val_type(state, ty));
481
482        let index = state.cur.encodable.type_count();
483        let mut f = state.cur.encodable.ty().function();
484
485        f.params(params).result(result);
486
487        index
488    }
489
490    /// Translates a type `id` provided, returning the index that it is defined
491    /// at.
492    ///
493    /// This is the main point at which type translation flows through. This
494    /// performs everything necessary such as:
495    ///
496    /// * Each type is translated only once
497    /// * If `id` comes from a different instance it's aliased
498    /// * Dispatching to the correct translation internally.
499    fn ty(&self, state: &mut TypeState<'a>, id: AnyTypeId) -> u32 {
500        // Consult our scope's `type_defs` map, and if it's not present then
501        // generate the type and fill it in.
502        let key = (PtrKey(self.0), id);
503        if let Some(ret) = state.cur.type_defs.get(&key) {
504            return *ret;
505        }
506
507        // If it's a resource that has been remapped, check one more time using
508        // the remapped version.
509        if let AnyTypeId::Component(ComponentAnyTypeId::Resource(resource)) = id {
510            if let Some((component, id)) = state.remapping.get(&resource.resource()) {
511                let key = (
512                    PtrKey(*component),
513                    AnyTypeId::Component(ComponentAnyTypeId::Resource(
514                        resource.with_resource_id(*id),
515                    )),
516                );
517                if let Some(ret) = state.cur.type_defs.get(&key) {
518                    return *ret;
519                }
520            }
521        }
522
523        let idx = self._ty(state, id);
524        let prev = state.cur.type_defs.insert(key, idx);
525        assert!(prev.is_none());
526        idx
527    }
528
529    // Inner version of `ty` above which is a separate method to make it easier
530    // to use `return` and not thwart the caching above.
531    fn _ty(&self, state: &mut TypeState<'a>, mut id: AnyTypeId) -> u32 {
532        // This loop will walk the "alias chain" starting at `id` which will
533        // eventually reach the definition of `id`.
534        loop {
535            let key = (PtrKey(self.0), id);
536
537            // First see if this `id` has already been defined under a different
538            // name. This can happen where one component's view of an imported
539            // instance may be partial and then unioned with another component's
540            // view of an imported instance. The second instance should reuse
541            // all the types defined/exported by the first.
542            //
543            // Here the reverse-export map is consulted where if `key` as an
544            // exported type from this instance (which is registered in
545            // "parallel" when one of those is encountered for all components)
546            // then search with the exported name if any other component has a
547            // type definition for their own version of our `id`.
548            if let Some(name) = state.cur.type_exports.get(&key) {
549                for key in state.cur.type_exports_rev[name].iter() {
550                    if let Some(ret) = state.cur.type_defs.get(key) {
551                        log::trace!("id already defined through a different component");
552                        return *ret;
553                    }
554                }
555            }
556
557            // Otherwise see if this type is defined elsewhere and if an alias
558            // hasn't previously been created then one is done so here. This
559            // will search all outer scopes for an instance that exports `id`.
560            for (i, scope) in state.scopes.iter_mut().rev().enumerate() {
561                let (instance, name) = match scope.instance_exports.get(&key) {
562                    Some(pair) => *pair,
563                    None => continue,
564                };
565                let scope_idx = scope.encodable.type_count();
566                scope.encodable.alias(Alias::InstanceExport {
567                    instance,
568                    name,
569                    kind: ComponentExportKind::Type,
570                });
571                match &scope.encodable {
572                    Encodable::Instance(_) => log::trace!("instance"),
573                    Encodable::Component(_) => log::trace!("component"),
574                    Encodable::Builder(_) => log::trace!("builder"),
575                }
576                let ret = state.cur.encodable.type_count();
577                state.cur.encodable.alias(Alias::Outer {
578                    count: i as u32 + 1,
579                    index: scope_idx,
580                    kind: ComponentOuterAliasKind::Type,
581                });
582                log::trace!("id defined in a different instance");
583                return ret;
584            }
585
586            if let Some((instance, name)) = state.cur.instance_exports.get(&key) {
587                let ret = state.cur.encodable.type_count();
588                state.cur.encodable.alias(Alias::InstanceExport {
589                    instance: *instance,
590                    name,
591                    kind: ComponentExportKind::Type,
592                });
593                log::trace!("id defined in current instance");
594                return ret;
595            }
596
597            match id.peel_alias(&self.0.types) {
598                Some(next) => id = next,
599                // If there's no more aliases then fall through to the
600                // definition of the type below.
601                None => break,
602            }
603        }
604
605        // This type wasn't previously defined, so define it here.
606        return match id {
607            AnyTypeId::Core(ComponentCoreTypeId::Sub(_)) => unreachable!(),
608            AnyTypeId::Core(ComponentCoreTypeId::Module(id)) => self.module_type(state, id),
609            AnyTypeId::Component(id) => match id {
610                ComponentAnyTypeId::Resource(r) => {
611                    unreachable!(
612                        "should have been handled in `TypeEncoder::component_entity_type`: {r:?}"
613                    )
614                }
615                ComponentAnyTypeId::Defined(id) => self.defined_type(state, id),
616                ComponentAnyTypeId::Func(id) => self.component_func_type(state, id),
617                ComponentAnyTypeId::Instance(id) => self.component_instance_type(state, id),
618                ComponentAnyTypeId::Component(id) => self.component_type(state, id),
619            },
620        };
621    }
622
623    fn component_val_type(
624        &self,
625        state: &mut TypeState<'a>,
626        ty: ct::ComponentValType,
627    ) -> ComponentValType {
628        match ty {
629            ct::ComponentValType::Primitive(ty) => ComponentValType::Primitive(ty.into()),
630            ct::ComponentValType::Type(id) => {
631                ComponentValType::Type(self.ty(state, ComponentAnyTypeId::from(id).into()))
632            }
633        }
634    }
635
636    fn defined_type(&self, state: &mut TypeState<'a>, id: ComponentDefinedTypeId) -> u32 {
637        let ty = &self.0.types[id];
638
639        match ty {
640            ComponentDefinedType::Primitive(ty) => {
641                let index = state.cur.encodable.type_count();
642                state
643                    .cur
644                    .encodable
645                    .ty()
646                    .defined_type()
647                    .primitive((*ty).into());
648                index
649            }
650            ComponentDefinedType::Record(r) => self.record(state, r),
651            ComponentDefinedType::Variant(v) => self.variant(state, v),
652            ComponentDefinedType::List(ty) => self.list(state, *ty),
653            ComponentDefinedType::FixedSizeList(ty, elements) => {
654                self.fixed_size_list(state, *ty, *elements)
655            }
656            ComponentDefinedType::Tuple(t) => self.tuple(state, t),
657            ComponentDefinedType::Flags(names) => Self::flags(&mut state.cur.encodable, names),
658            ComponentDefinedType::Enum(cases) => Self::enum_type(&mut state.cur.encodable, cases),
659            ComponentDefinedType::Option(ty) => self.option(state, *ty),
660            ComponentDefinedType::Result { ok, err } => self.result(state, *ok, *err),
661            ComponentDefinedType::Own(r) => {
662                let ty = self.ty(state, (*r).into());
663                let index = state.cur.encodable.type_count();
664                state.cur.encodable.ty().defined_type().own(ty);
665                index
666            }
667            ComponentDefinedType::Borrow(r) => {
668                let ty = self.ty(state, (*r).into());
669                let index = state.cur.encodable.type_count();
670                state.cur.encodable.ty().defined_type().borrow(ty);
671                index
672            }
673            ComponentDefinedType::Future(ty) => self.future(state, *ty),
674            ComponentDefinedType::Stream(ty) => self.stream(state, *ty),
675        }
676    }
677
678    fn record(&self, state: &mut TypeState<'a>, record: &RecordType) -> u32 {
679        let fields = record
680            .fields
681            .iter()
682            .map(|(n, ty)| (n.as_str(), self.component_val_type(state, *ty)))
683            .collect::<Vec<_>>();
684
685        let index = state.cur.encodable.type_count();
686        state.cur.encodable.ty().defined_type().record(fields);
687        index
688    }
689
690    fn variant(&self, state: &mut TypeState<'a>, variant: &VariantType) -> u32 {
691        let cases = variant
692            .cases
693            .iter()
694            .map(|(n, c)| {
695                (
696                    n.as_str(),
697                    c.ty.map(|ty| self.component_val_type(state, ty)),
698                    c.refines
699                        .as_deref()
700                        .map(|r| variant.cases.iter().position(|(n, _)| n == r).unwrap() as u32),
701                )
702            })
703            .collect::<Vec<_>>();
704        let index = state.cur.encodable.type_count();
705        state.cur.encodable.ty().defined_type().variant(cases);
706        index
707    }
708
709    fn list(&self, state: &mut TypeState<'a>, ty: ct::ComponentValType) -> u32 {
710        let ty = self.component_val_type(state, ty);
711        let index = state.cur.encodable.type_count();
712        state.cur.encodable.ty().defined_type().list(ty);
713        index
714    }
715
716    fn fixed_size_list(
717        &self,
718        state: &mut TypeState<'a>,
719        ty: ct::ComponentValType,
720        elements: u32,
721    ) -> u32 {
722        let ty = self.component_val_type(state, ty);
723        let index = state.cur.encodable.type_count();
724        state
725            .cur
726            .encodable
727            .ty()
728            .defined_type()
729            .fixed_size_list(ty, elements);
730        index
731    }
732
733    fn tuple(&self, state: &mut TypeState<'a>, tuple: &TupleType) -> u32 {
734        let types = tuple
735            .types
736            .iter()
737            .map(|ty| self.component_val_type(state, *ty))
738            .collect::<Vec<_>>();
739        let index = state.cur.encodable.type_count();
740        state.cur.encodable.ty().defined_type().tuple(types);
741        index
742    }
743
744    fn flags(
745        encodable: &mut Encodable,
746        names: &wasmparser::collections::IndexSet<KebabString>,
747    ) -> u32 {
748        let index = encodable.type_count();
749        encodable
750            .ty()
751            .defined_type()
752            .flags(names.iter().map(|n| n.as_str()));
753        index
754    }
755
756    fn enum_type(
757        encodable: &mut Encodable,
758        cases: &wasmparser::collections::IndexSet<KebabString>,
759    ) -> u32 {
760        let index = encodable.type_count();
761        encodable
762            .ty()
763            .defined_type()
764            .enum_type(cases.iter().map(|c| c.as_str()));
765        index
766    }
767
768    fn option(&self, state: &mut TypeState<'a>, ty: ct::ComponentValType) -> u32 {
769        let ty = self.component_val_type(state, ty);
770
771        let index = state.cur.encodable.type_count();
772        state.cur.encodable.ty().defined_type().option(ty);
773        index
774    }
775
776    fn result(
777        &self,
778        state: &mut TypeState<'a>,
779        ok: Option<ct::ComponentValType>,
780        err: Option<ct::ComponentValType>,
781    ) -> u32 {
782        let ok = ok.map(|ty| self.component_val_type(state, ty));
783        let err = err.map(|ty| self.component_val_type(state, ty));
784
785        let index = state.cur.encodable.type_count();
786        state.cur.encodable.ty().defined_type().result(ok, err);
787        index
788    }
789
790    fn export(
791        &self,
792        name: &'a str,
793        export: ComponentEntityType,
794        state: &mut TypeState<'a>,
795    ) -> ComponentTypeRef {
796        // Check if the export is a type; if so, we need to update the index of the
797        // type to point to the export instead of the original definition
798        let id = match export {
799            ComponentEntityType::Type { created: id, .. } => Some(id),
800            _ => None,
801        };
802        let export = self.component_entity_type(state, export);
803        if let Some(id) = id {
804            // Update the index in the type map to point to this export
805            let key = (PtrKey(self.0), id.into());
806            let value = state.cur.encodable.type_count();
807            let prev = state.cur.type_defs.insert(key, value);
808            assert!(prev.is_none());
809            state.cur.add_type_export(key, name);
810        }
811        export
812    }
813
814    fn future(&self, state: &mut TypeState<'a>, ty: Option<ct::ComponentValType>) -> u32 {
815        let ty = ty.map(|ty| self.component_val_type(state, ty));
816
817        let index = state.cur.encodable.type_count();
818        state.cur.encodable.ty().defined_type().future(ty);
819        index
820    }
821
822    fn stream(&self, state: &mut TypeState<'a>, ty: Option<ct::ComponentValType>) -> u32 {
823        let ty = ty.map(|ty| self.component_val_type(state, ty));
824
825        let index = state.cur.encodable.type_count();
826        state.cur.encodable.ty().defined_type().stream(ty);
827        index
828    }
829}
830
831/// Represents an instance index in a composition graph.
832#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
833struct InstanceIndex(usize);
834
835enum ArgumentImportKind<'a> {
836    /// An item is being imported.
837    ///
838    /// The item may be an instance that does not need to be merged.
839    Item(&'a crate::graph::Component<'a>, ComponentEntityType),
840    /// A merged instance is being imported.
841    ///
842    /// Instances are unioned together to form a single instance to
843    /// import that will satisfy all instantiation arguments that
844    /// reference the import.
845    Instance(IndexMap<&'a str, Vec<(&'a crate::graph::Component<'a>, ComponentEntityType)>>),
846}
847
848/// Represents an import for an instantiation argument.
849struct ArgumentImport<'a> {
850    // The name of the import.
851    name: &'a str,
852    /// The kind of import.
853    kind: ArgumentImportKind<'a>,
854    /// The instances that will use the import for an argument.
855    instances: SmallVec<[(InstanceIndex, ImportIndex); 1]>,
856}
857
858impl ArgumentImport<'_> {
859    fn merge(&mut self, arg: Self, remapping: &mut Remapping) -> Result<()> {
860        assert_eq!(self.name, arg.name);
861        self.instances.extend(arg.instances);
862
863        // If the existing import is an instance, convert this argument import to
864        // a merged instance import.
865        if let ArgumentImportKind::Item(component, ComponentEntityType::Instance(id)) = &self.kind {
866            let exports = component.types[*id].exports.iter();
867
868            let mut map = IndexMap::with_capacity(exports.len());
869            for (name, ty) in exports {
870                map.insert(name.as_str(), vec![(*component, *ty)]);
871            }
872
873            self.kind = ArgumentImportKind::Instance(map);
874        }
875
876        match (&mut self.kind, arg.kind) {
877            // The new item should never be a merged instance
878            (_, ArgumentImportKind::Instance(..)) => {
879                unreachable!("expected an item import to merge with")
880            }
881            // If the existing import is a merged instance, merge with an instance item import
882            (
883                ArgumentImportKind::Instance(exports),
884                ArgumentImportKind::Item(new_component, ComponentEntityType::Instance(id)),
885            ) => {
886                for (name, new_type) in new_component.types[id].exports.iter() {
887                    let dst = exports.entry(name.as_str()).or_default();
888                    for (existing_component, existing_type) in dst.iter_mut() {
889                        if Self::types_compatible(
890                            existing_component,
891                            *existing_type,
892                            new_component,
893                            *new_type,
894                            remapping,
895                        ) {
896                            continue;
897                        }
898                        bail!(
899                            "cannot import instance with name `{name}` for \
900                             an instantiation argument of component \
901                             `{cname}` because it conflicts with an \
902                             imported instantiation argument of component \
903                             `{ecname}`",
904                            name = self.name,
905                            cname = new_component.name,
906                            ecname = existing_component.name,
907                        )
908                    }
909                    dst.push((new_component, *new_type));
910                }
911            }
912            // Otherwise, an attempt to merge an instance with a non-instance is an error
913            (ArgumentImportKind::Instance(_), ArgumentImportKind::Item(component, ty)) => {
914                bail!(
915                    "cannot import {ty} with name `{name}` for an instantiation \
916                     argument of component `{cname}` because it conflicts with \
917                     an instance imported with the same name",
918                    name = self.name,
919                    ty = type_desc(ty),
920                    cname = component.name,
921                );
922            }
923            // Finally, merge two item imports together by finding the most-compatible type
924            (
925                ArgumentImportKind::Item(existing_component, existing_type),
926                ArgumentImportKind::Item(new_component, new_type),
927            ) => {
928                if !Self::types_compatible(
929                    existing_component,
930                    *existing_type,
931                    new_component,
932                    new_type,
933                    remapping,
934                ) {
935                    bail!(
936                        "cannot import {ty} with name `{name}` for an \
937                         instantiation argument of component `{cname}` \
938                         because it conflicts with an imported instantiation \
939                         argument of component `{ecname}`",
940                        ty = type_desc(new_type),
941                        name = self.name,
942                        cname = new_component.name,
943                        ecname = existing_component.name,
944                    )
945                }
946            }
947        }
948
949        Ok(())
950    }
951
952    /// Tests whether two types from different components are compatible with
953    /// one another.
954    ///
955    /// For now this performs a subtype check in both directions, only
956    /// considering them compatible if both checks are "true". This means
957    /// that it effectively requires the types to be structured the same way.
958    fn types_compatible<'a>(
959        existing_component: &'a crate::graph::Component<'a>,
960        existing_type: ComponentEntityType,
961        new_component: &'a crate::graph::Component<'a>,
962        new_type: ComponentEntityType,
963        remapping: &mut Remapping,
964    ) -> bool {
965        let mut context =
966            SubtypeCx::new_with_refs(existing_component.types(), new_component.types());
967        let mut a_ty = existing_type;
968        context.a.remap_component_entity(&mut a_ty, remapping);
969        remapping.reset_type_cache();
970
971        let mut b_ty = new_type;
972        context.b.remap_component_entity(&mut b_ty, remapping);
973        remapping.reset_type_cache();
974
975        if context.component_entity_type(&a_ty, &b_ty, 0).is_err() {
976            return false;
977        }
978
979        context.swap();
980
981        context.component_entity_type(&b_ty, &a_ty, 0).is_ok()
982    }
983}
984
985/// Represents an entry in the import map built up during
986/// the encoding of a composition graph.
987///
988/// A map entry is either an import of a component or
989/// an import of an item to satisfy an instantiation argument.
990enum ImportMapEntry<'a> {
991    /// An import of a component.
992    Component(&'a crate::graph::Component<'a>),
993    /// An import to satisfy one or more instantiation arguments.
994    Argument(ArgumentImport<'a>),
995}
996
997/// Represents the import map built during the encoding
998/// of a composition graph.
999#[derive(Default)]
1000struct ImportMap<'a>(IndexMap<&'a str, ImportMapEntry<'a>>);
1001
1002impl<'a> ImportMap<'a> {
1003    fn new(import_components: bool, graph: &'a CompositionGraph) -> Result<Self> {
1004        let mut imports = Self::default();
1005
1006        if import_components {
1007            imports.add_component_imports(graph);
1008        }
1009
1010        imports.add_instantiation_imports(graph)?;
1011
1012        Ok(imports)
1013    }
1014
1015    fn add_component_imports(&mut self, graph: &'a CompositionGraph) {
1016        for entry in graph
1017            .components
1018            .values()
1019            .filter(|e| !e.instances.is_empty())
1020        {
1021            assert!(
1022                self.0
1023                    .insert(
1024                        &entry.component.name,
1025                        ImportMapEntry::Component(&entry.component),
1026                    )
1027                    .is_none()
1028            );
1029        }
1030    }
1031
1032    fn add_instantiation_imports(&mut self, graph: &'a CompositionGraph) -> Result<()> {
1033        let remapping = &mut graph.resource_mapping.borrow().remapping();
1034        let mut imported = HashMap::new();
1035
1036        // Metadata about dependency edges used below during sorting (see
1037        // below).
1038        let mut component_defining_instance = HashMap::new();
1039        let mut deps = HashMap::new();
1040
1041        for (instance_index, instance) in graph.instances.values().enumerate() {
1042            let (component_index, _, entry) =
1043                graph.components.get_full(&instance.component).unwrap();
1044            let defining_instances = component_defining_instance
1045                .entry(component_index)
1046                .or_insert(HashMap::new());
1047
1048            let instance_index = InstanceIndex(instance_index);
1049
1050            // Import any unconnected instantiation arguments for the instance
1051            for (import_index, name, _) in entry.component.imports() {
1052                if instance.connected.contains(&import_index) {
1053                    continue;
1054                }
1055
1056                let (_, ty) = entry.component.import_entity_type(import_index).unwrap();
1057
1058                let arg = ArgumentImport {
1059                    name,
1060                    kind: ArgumentImportKind::Item(&entry.component, ty),
1061                    instances: smallvec::smallvec![(instance_index, import_index)],
1062                };
1063
1064                // Check to see if we've seen this import before; if so, don't bother with
1065                // type checking, just add the instance to the list of instances
1066                match imported.entry((component_index, import_index)) {
1067                    Entry::Occupied(e) => match self.0.get_index_mut(*e.get()).unwrap().1 {
1068                        ImportMapEntry::Component(_) => {
1069                            unreachable!("import should not be for a component")
1070                        }
1071                        ImportMapEntry::Argument(arg) => {
1072                            arg.instances.push((instance_index, import_index));
1073                        }
1074                    },
1075                    Entry::Vacant(e) => {
1076                        // If this is the first time an instance import is seen
1077                        // then register all of its dependencies on other
1078                        // imports.
1079                        //
1080                        // (see more below on this)
1081                        DependencyRegistrar {
1082                            types: &entry.component.types,
1083                            defining_instances,
1084                            cur: name,
1085                            deps: &mut deps,
1086                        }
1087                        .entity(ty);
1088                        let index = match self.0.entry(name.into()) {
1089                            indexmap::map::Entry::Occupied(mut e) => match e.get_mut() {
1090                                ImportMapEntry::Component(_) => {
1091                                    bail!(
1092                                        "cannot import {ty} `{name}` for an instantiation argument of component `{cname}` because it conflicts with a component imported with the same name",
1093                                        ty = type_desc(ty),
1094                                        cname = entry.component.name,
1095                                    );
1096                                }
1097                                ImportMapEntry::Argument(existing) => {
1098                                    existing.merge(arg, remapping)?;
1099                                    e.index()
1100                                }
1101                            },
1102                            indexmap::map::Entry::Vacant(e) => {
1103                                let index = e.index();
1104                                e.insert(ImportMapEntry::Argument(arg));
1105                                index
1106                            }
1107                        };
1108                        e.insert(index);
1109                    }
1110                }
1111            }
1112        }
1113
1114        // Before returning perform a topological sort of all dependencies to
1115        // ensure that they're translated in the correct order for types to be
1116        // connected.
1117        //
1118        // Why, might you be asking, is this necessary? Each component
1119        // individually already has topologically sorted dependencies and
1120        // they're all iterated through above, so what's the problem?
1121        //
1122        // The reason this loop arises is for when two different components
1123        // are unioned together and a topological ordering between the union
1124        // of the imports is required. While each component is sorted that's
1125        // not enough to ensure everything is sorted.
1126        //
1127        // For example let's say there's three interfaces A, B, and C. C
1128        // depends on both A and B. Then let's have one component import both A
1129        // and C and a second component imports B and C. This can be valid where
1130        // C can be "sliced up" where only the portions that depend on A can be
1131        // separated from the portions that depend on B.
1132        // When walking over the instances above we'll first generate imports
1133        // of A and C. Next though the next instance will add and import for B,
1134        // meaning that the import list is A, C, B. This is not a correct
1135        // topological ordering, which is what this sort is solving.
1136        let mut order = IndexSet::new();
1137        for (name, _) in self.0.iter() {
1138            toposort(&name[..], &deps, &mut order);
1139        }
1140        let order = order
1141            .into_iter()
1142            .map(|s| s.to_string())
1143            .collect::<IndexSet<_>>();
1144        self.0
1145            .sort_by_cached_key(|name, _| order.get_full(&name[..]).unwrap().0);
1146
1147        Ok(())
1148    }
1149}
1150
1151/// Helper structure used to fill out the `deps` and `defining_instances` maps
1152/// when building the imports to a component.
1153///
1154/// The goal of this structure is to take types defined within `self.cur` and
1155/// draw edges in the `deps` map from `cur` to those names in
1156/// `defining_instances`.
1157///
1158/// For example if a type refers to a name defined in a different instance then
1159/// that previous instance will already be registered in `defining_instances`
1160/// and that'll draw a dependency from `self.cur` to that name.
1161struct DependencyRegistrar<'a, 'b> {
1162    types: &'a types::Types,
1163    defining_instances: &'b mut HashMap<ComponentAnyTypeId, &'a str>,
1164    cur: &'a str,
1165    deps: &'b mut HashMap<&'a str, Vec<&'a str>>,
1166}
1167
1168impl DependencyRegistrar<'_, '_> {
1169    fn entity(&mut self, ty: ComponentEntityType) {
1170        match ty {
1171            ComponentEntityType::Type {
1172                created,
1173                referenced,
1174            } => {
1175                let prev = self.defining_instances.insert(created, self.cur);
1176                assert!(prev.is_none());
1177                self.ty(referenced);
1178            }
1179            ComponentEntityType::Module(_) => {}
1180            ComponentEntityType::Value(v) => self.val_type(v),
1181            ComponentEntityType::Instance(e) => self.instance(e),
1182            ComponentEntityType::Component(e) => self.component(e),
1183            ComponentEntityType::Func(e) => self.func(e),
1184        }
1185    }
1186
1187    fn ty(&mut self, ty: ComponentAnyTypeId) {
1188        match self.defining_instances.entry(ty) {
1189            // If it's known where `ty` is defined then there's nothing else to
1190            // do here beyond drawing a new dependency edge. Note though that
1191            // "edges to self" are skipped explicitly here.
1192            Entry::Occupied(e) => {
1193                if *e.get() != self.cur {
1194                    self.deps.entry(self.cur).or_default().push(*e.get());
1195                }
1196                return;
1197            }
1198
1199            // Otherwise `ty` is now registered as defined by `self.cur` and we
1200            // continue below.
1201            Entry::Vacant(e) => {
1202                e.insert(self.cur);
1203            }
1204        }
1205
1206        // Recurse for aliases to see edges across components, and otherwise
1207        // recurse on the structure of the type below.
1208        if let Some(ty) = self.types.as_ref().peel_alias(ty) {
1209            return self.ty(ty);
1210        }
1211
1212        match ty {
1213            ComponentAnyTypeId::Resource(_) => {}
1214            ComponentAnyTypeId::Defined(id) => self.defined(id),
1215            ComponentAnyTypeId::Func(id) => self.func(id),
1216            ComponentAnyTypeId::Instance(id) => self.instance(id),
1217            ComponentAnyTypeId::Component(id) => self.component(id),
1218        }
1219    }
1220
1221    fn val_type(&mut self, ty: ct::ComponentValType) {
1222        match ty {
1223            ct::ComponentValType::Type(t) => self.ty(t.into()),
1224            ct::ComponentValType::Primitive(_) => {}
1225        }
1226    }
1227
1228    fn component(&mut self, ty: ComponentTypeId) {
1229        let ty = &self.types[ty];
1230        for (_, ty) in ty.imports.iter().chain(&ty.exports) {
1231            self.entity(*ty);
1232        }
1233    }
1234
1235    fn instance(&mut self, ty: ComponentInstanceTypeId) {
1236        for (_, ty) in self.types[ty].exports.iter() {
1237            self.entity(*ty);
1238        }
1239    }
1240
1241    fn func(&mut self, ty: ComponentFuncTypeId) {
1242        let ty = &self.types[ty];
1243        for ty in ty.params.iter().map(|p| p.1).chain(ty.result) {
1244            self.val_type(ty);
1245        }
1246    }
1247
1248    fn defined(&mut self, ty: ComponentDefinedTypeId) {
1249        match &self.types[ty] {
1250            ComponentDefinedType::Primitive(_)
1251            | ComponentDefinedType::Enum(_)
1252            | ComponentDefinedType::Flags(_) => {}
1253            ComponentDefinedType::List(t)
1254            | ComponentDefinedType::FixedSizeList(t, _)
1255            | ComponentDefinedType::Option(t) => self.val_type(*t),
1256            ComponentDefinedType::Own(r) | ComponentDefinedType::Borrow(r) => {
1257                self.ty(ComponentAnyTypeId::Resource(*r))
1258            }
1259            ComponentDefinedType::Record(r) => {
1260                for (_, ty) in r.fields.iter() {
1261                    self.val_type(*ty);
1262                }
1263            }
1264            ComponentDefinedType::Tuple(r) => {
1265                for ty in r.types.iter() {
1266                    self.val_type(*ty);
1267                }
1268            }
1269            ComponentDefinedType::Variant(r) => {
1270                for (_, case) in r.cases.iter() {
1271                    if let Some(ty) = case.ty {
1272                        self.val_type(ty);
1273                    }
1274                }
1275            }
1276            ComponentDefinedType::Result { ok, err } => {
1277                if let Some(ok) = ok {
1278                    self.val_type(*ok);
1279                }
1280                if let Some(err) = err {
1281                    self.val_type(*err);
1282                }
1283            }
1284            ComponentDefinedType::Future(ty) => {
1285                if let Some(ty) = ty {
1286                    self.val_type(*ty);
1287                }
1288            }
1289            ComponentDefinedType::Stream(ty) => {
1290                if let Some(ty) = ty {
1291                    self.val_type(*ty);
1292                }
1293            }
1294        }
1295    }
1296}
1297
1298fn toposort<'a>(
1299    cur: &'a str,
1300    deps: &HashMap<&'a str, Vec<&'a str>>,
1301    order: &mut IndexSet<&'a str>,
1302) {
1303    if order.contains(cur) {
1304        return;
1305    }
1306    if let Some(list) = deps.get(cur) {
1307        for dep in list {
1308            toposort(dep, deps, order);
1309        }
1310    }
1311    let ok = order.insert(cur);
1312    assert!(ok);
1313}
1314
1315/// Used to encode a composition graph as a new WebAssembly component.
1316pub(crate) struct CompositionGraphEncoder<'a> {
1317    /// The options for the encoding.
1318    options: EncodeOptions,
1319    /// The graph being encoded.
1320    graph: &'a CompositionGraph<'a>,
1321    /// Map from graph component index to encoded component index.
1322    encoded_components: HashMap<PtrKey<'a, crate::graph::Component<'a>>, u32>,
1323    /// Map from graph instance id to encoded instance index.
1324    encoded_instances: HashMap<InstanceId, u32>,
1325    /// Map from instance and import index to encoded item index.
1326    ///
1327    /// This is used for instantiation arguments that are imported.
1328    imported_args: HashMap<(InstanceIndex, ImportIndex), u32>,
1329    /// Map from instance id and export index to encoded item index.
1330    ///
1331    /// This is used to track instantiation arguments aliased from
1332    /// other instances.
1333    aliases: HashMap<(InstanceId, ExportIndex), u32>,
1334}
1335
1336impl<'a> CompositionGraphEncoder<'a> {
1337    pub(crate) fn new(options: EncodeOptions, graph: &'a CompositionGraph) -> Self {
1338        Self {
1339            options,
1340            graph,
1341            encoded_components: Default::default(),
1342            encoded_instances: Default::default(),
1343            imported_args: Default::default(),
1344            aliases: Default::default(),
1345        }
1346    }
1347
1348    pub(crate) fn encode(mut self) -> Result<Vec<u8>> {
1349        let mut encoded = ComponentBuilder::default();
1350
1351        self.encode_imports(&mut encoded)?;
1352        self.encode_components(&mut encoded);
1353        self.encode_instantiations(&mut encoded)?;
1354
1355        if let Some(id) = self.options.export {
1356            self.encode_exports(&mut encoded, id)?;
1357        }
1358
1359        Ok(encoded.finish())
1360    }
1361
1362    fn encode_imports(&mut self, encoded: &mut ComponentBuilder) -> Result<()> {
1363        let imports = ImportMap::new(!self.options.define_components, self.graph)?;
1364
1365        // Create new state to track where types are defined and in which
1366        // instances. Temporarily "move" the `encoded` builder into this state.
1367        let mut state = TypeState::new_with_remapping(self.graph.remapping_map());
1368        state.cur.encodable = Encodable::Builder(mem::take(encoded));
1369
1370        for (name, entry) in imports.0 {
1371            log::trace!("encoding import {name}");
1372            match entry {
1373                ImportMapEntry::Component(component) => {
1374                    let encoded = match &mut state.cur.encodable {
1375                        Encodable::Builder(builder) => builder,
1376                        _ => unreachable!(),
1377                    };
1378                    self.encode_component_import(encoded, name.as_ref(), component);
1379                }
1380                ImportMapEntry::Argument(arg) => {
1381                    let index = match arg.kind {
1382                        ArgumentImportKind::Item(component, ty) => {
1383                            self.encode_item_import(&mut state, name.as_ref(), component, ty)
1384                        }
1385                        ArgumentImportKind::Instance(exports) => {
1386                            self.encode_instance_import(&mut state, name.as_ref(), exports)
1387                        }
1388                    };
1389
1390                    self.imported_args
1391                        .extend(arg.instances.into_iter().map(|k| (k, index)));
1392                }
1393            }
1394        }
1395
1396        // "Move" the builder back out from the state into this function's
1397        // parameter.
1398        match &mut state.cur.encodable {
1399            Encodable::Builder(builder) => *encoded = mem::take(builder),
1400            _ => unreachable!(),
1401        }
1402
1403        Ok(())
1404    }
1405
1406    fn encode_component_import(
1407        &mut self,
1408        encoded: &mut ComponentBuilder,
1409        name: &str,
1410        component: &'a crate::graph::Component,
1411    ) -> u32 {
1412        let type_index = self.define_component_type(encoded, component);
1413        let index = self.import(encoded, name, ComponentTypeRef::Component(type_index));
1414
1415        assert!(
1416            self.encoded_components
1417                .insert(PtrKey(component), index)
1418                .is_none()
1419        );
1420
1421        index
1422    }
1423
1424    fn encode_item_import(
1425        &mut self,
1426        state: &mut TypeState<'a>,
1427        name: &str,
1428        component: &'a crate::graph::Component,
1429        ty: ComponentEntityType,
1430    ) -> u32 {
1431        log::trace!("encoding item import {name}");
1432        let encoder = TypeEncoder::new(component);
1433        let ty = encoder.component_entity_type(state, ty);
1434
1435        let encoded = match &mut state.cur.encodable {
1436            Encodable::Builder(builder) => builder,
1437            _ => unreachable!(),
1438        };
1439        self.import(encoded, name, ty)
1440    }
1441
1442    fn encode_instance_import(
1443        &mut self,
1444        state: &mut TypeState<'a>,
1445        name: &str,
1446        exports: IndexMap<&'a str, Vec<(&'a crate::graph::Component, ComponentEntityType)>>,
1447    ) -> u32 {
1448        log::trace!("encoding instance import {name}");
1449        state.push(Encodable::Instance(InstanceType::new()));
1450        for (name, types) in exports {
1451            let (component, ty) = types[0];
1452            log::trace!("export {name}: {ty:?}");
1453            let export = TypeEncoder::new(component).export(name, ty, state);
1454            let t = match &mut state.cur.encodable {
1455                Encodable::Instance(c) => c,
1456                _ => unreachable!(),
1457            };
1458            t.export(name, export);
1459
1460            for (component, ty) in types.iter().skip(1) {
1461                if let ComponentEntityType::Type { created, .. } = ty {
1462                    state
1463                        .cur
1464                        .add_type_export((PtrKey(component), (*created).into()), name);
1465                }
1466            }
1467        }
1468
1469        let instance_type = match state.pop() {
1470            Encodable::Instance(c) => c,
1471            _ => unreachable!(),
1472        };
1473
1474        let encoded = match &mut state.cur.encodable {
1475            Encodable::Builder(builder) => builder,
1476            _ => unreachable!(),
1477        };
1478        let index = encoded.type_instance(None, &instance_type);
1479        self.import(encoded, name, ComponentTypeRef::Instance(index))
1480    }
1481
1482    fn encode_instantiations(&mut self, encoded: &mut ComponentBuilder) -> Result<()> {
1483        let ordering = self.graph.instantiation_order()?;
1484
1485        // Encode the independent instances first
1486        for id in self
1487            .graph
1488            .instances
1489            .keys()
1490            .filter(|id| !ordering.contains(*id))
1491        {
1492            self.encode_instantiation(encoded, *id)?;
1493        }
1494
1495        // Encode the dependent instances last
1496        for id in ordering {
1497            self.encode_instantiation(encoded, id)?;
1498        }
1499
1500        Ok(())
1501    }
1502
1503    fn encode_exports(
1504        &mut self,
1505        encoded: &mut ComponentBuilder,
1506        instance_id: InstanceId,
1507    ) -> Result<()> {
1508        let instance = self.graph.instances.get(&instance_id).ok_or_else(|| {
1509            anyhow!("cannot export specified instance because it does not exist in the graph")
1510        })?;
1511        let entry = self.graph.components.get(&instance.component).unwrap();
1512
1513        let encoded_instance_index = self.encoded_instances[&instance_id];
1514
1515        for (export_index, export_name, kind, _) in entry.component.exports() {
1516            let kind = match kind {
1517                ComponentExternalKind::Module => ComponentExportKind::Module,
1518                ComponentExternalKind::Func => ComponentExportKind::Func,
1519                ComponentExternalKind::Value => ComponentExportKind::Value,
1520                ComponentExternalKind::Type => ComponentExportKind::Type,
1521                ComponentExternalKind::Instance => ComponentExportKind::Instance,
1522                ComponentExternalKind::Component => ComponentExportKind::Component,
1523            };
1524
1525            let index = match self.aliases.get(&(instance_id, export_index)) {
1526                Some(index) => *index,
1527                None => {
1528                    let index = self.alias(encoded, encoded_instance_index, export_name, kind);
1529                    self.aliases.insert((instance_id, export_index), index);
1530                    index
1531                }
1532            };
1533
1534            encoded.export(export_name, kind, index, None);
1535        }
1536
1537        Ok(())
1538    }
1539
1540    fn encode_instantiation(
1541        &mut self,
1542        encoded: &mut ComponentBuilder,
1543        instance_id: InstanceId,
1544    ) -> Result<()> {
1545        let (instance_index, _, instance) = self.graph.instances.get_full(&instance_id).unwrap();
1546        let entry = &self.graph.components.get(&instance.component).unwrap();
1547
1548        let instance_index = InstanceIndex(instance_index);
1549        let encoded_component_index = self.encoded_components[&PtrKey(&entry.component)];
1550
1551        let args = self.instantiation_args(encoded, instance_index, &entry.component);
1552
1553        log::debug!(
1554            "instantiating component `{name}` with {args:?}",
1555            name = entry.component.name,
1556        );
1557
1558        let encoded_instance_index = encoded.instantiate(None, encoded_component_index, args);
1559
1560        self.encoded_instances
1561            .insert(instance_id, encoded_instance_index);
1562
1563        Ok(())
1564    }
1565
1566    fn encode_components(&mut self, encoded: &mut ComponentBuilder) {
1567        if !self.options.define_components {
1568            return;
1569        }
1570
1571        for entry in self
1572            .graph
1573            .components
1574            .values()
1575            .filter(|e| !e.instances.is_empty())
1576        {
1577            let index = self.define_component(encoded, &entry.component);
1578            assert!(
1579                self.encoded_components
1580                    .insert(PtrKey(&entry.component), index)
1581                    .is_none()
1582            );
1583        }
1584    }
1585
1586    fn define_component_type(
1587        &mut self,
1588        encoded: &mut ComponentBuilder,
1589        component: &crate::graph::Component,
1590    ) -> u32 {
1591        encoded.type_component(None, &component.ty())
1592    }
1593
1594    fn define_component(
1595        &mut self,
1596        encoded: &mut ComponentBuilder,
1597        component: &crate::graph::Component,
1598    ) -> u32 {
1599        log::debug!(
1600            "defining component `{name}` in composed component",
1601            name = component.name,
1602        );
1603        encoded.component_raw(None, component.bytes())
1604    }
1605
1606    fn instantiation_args(
1607        &mut self,
1608        encoded: &mut ComponentBuilder,
1609        instance_index: InstanceIndex,
1610        component: &'a crate::graph::Component,
1611    ) -> Vec<(&'a str, ComponentExportKind, u32)> {
1612        let (instance_id, instance) = self.graph.instances.get_index(instance_index.0).unwrap();
1613        let mut args = Vec::with_capacity(component.imports.len());
1614
1615        // Add the arguments that are aliased exports from other instances
1616        for (source_id, _, map) in self
1617            .graph
1618            .graph
1619            .edges_directed(*instance_id, EdgeDirection::Incoming)
1620        {
1621            assert!(source_id != *instance_id);
1622            let source_index = self.encoded_instances[&source_id];
1623            let (_, source_component) = &self.graph.get_component_of_instance(source_id).unwrap();
1624
1625            for (import_index, export_index) in map {
1626                // Check to see if we need to alias the item from the source instance
1627                let (name, ty) = component.import(*import_index).unwrap();
1628                let index = match export_index {
1629                    Some(export_index) => {
1630                        let (export_name, _, _) = source_component.export(*export_index).unwrap();
1631                        match self.aliases.get(&(source_id, *export_index)) {
1632                            Some(index) => *index,
1633                            None => {
1634                                let index = self.alias(
1635                                    encoded,
1636                                    source_index,
1637                                    export_name,
1638                                    type_ref_to_export_kind(ty),
1639                                );
1640                                self.aliases.insert((source_id, *export_index), index);
1641                                index
1642                            }
1643                        }
1644                    }
1645                    None => source_index,
1646                };
1647                args.push((name, type_ref_to_export_kind(ty), index));
1648            }
1649        }
1650
1651        // Finally, add any instantiation arguments that are being imported
1652        for (i, (name, ty)) in component.imports.iter().enumerate() {
1653            let import_index = ImportIndex(i);
1654            if instance.connected.contains(&import_index) {
1655                continue;
1656            }
1657
1658            let index = self.imported_args[&(instance_index, import_index)];
1659            args.push((name.as_str(), type_ref_to_export_kind(*ty), index));
1660        }
1661
1662        args
1663    }
1664
1665    fn import(&mut self, encoded: &mut ComponentBuilder, name: &str, ty: ComponentTypeRef) -> u32 {
1666        log::debug!("importing {ty:?} with `{name}` in composed component");
1667        encoded.import(name, ty)
1668    }
1669
1670    fn alias(
1671        &mut self,
1672        encoded: &mut ComponentBuilder,
1673        instance: u32,
1674        name: &str,
1675        kind: ComponentExportKind,
1676    ) -> u32 {
1677        log::debug!(
1678            "aliasing {kind:?} export `{name}` from encoded index {instance} in composed component"
1679        );
1680        encoded.alias_export(instance, name, kind)
1681    }
1682}