wac_types/
package.rs

1use crate::{
2    CoreExtern, CoreFuncType, DefinedType, Enum, Flags, FuncType, FuncTypeId, Interface,
3    InterfaceId, ItemKind, ModuleType, ModuleTypeId, Record, Resource, ResourceAlias, ResourceId,
4    Type, Types, UsedType, ValueType, Variant, World, WorldId,
5};
6use anyhow::{bail, Context, Result};
7use indexmap::IndexMap;
8use semver::Version;
9use std::borrow::Borrow;
10use std::fmt;
11use std::{collections::HashMap, path::Path, rc::Rc};
12use wasmparser::{
13    component_types::{self as wasm},
14    names::{ComponentName, ComponentNameKind},
15    Chunk, Encoding, Parser, Payload, ValidPayload, Validator, WasmFeatures,
16};
17
18/// Represents a package key that can be used in associative containers.
19#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
20pub struct PackageKey {
21    /// The name of the package,
22    name: String,
23    /// The version of the package.
24    version: Option<Version>,
25}
26
27impl PackageKey {
28    /// Constructs a new package key from the given package reference.
29    pub fn new(package: &Package) -> Self {
30        Self {
31            name: package.name.clone(),
32            version: package.version.clone(),
33        }
34    }
35
36    /// Gets the name of the package.
37    pub fn name(&self) -> &str {
38        &self.name
39    }
40
41    /// Gets the version of the package.
42    pub fn version(&self) -> Option<&Version> {
43        self.version.as_ref()
44    }
45}
46
47impl fmt::Display for PackageKey {
48    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49        write!(f, "{name}", name = self.name)?;
50        if let Some(version) = &self.version {
51            write!(f, "@{version}")?;
52        }
53
54        Ok(())
55    }
56}
57
58/// A borrowed package key.
59#[derive(Copy, Clone, Hash, PartialEq, Eq)]
60pub struct BorrowedPackageKey<'a> {
61    /// The package name.
62    pub name: &'a str,
63    /// The optional package version.
64    pub version: Option<&'a Version>,
65}
66
67impl<'a> BorrowedPackageKey<'a> {
68    /// Constructs a new borrowed package key from the given package reference.
69    pub fn new(package: &'a Package) -> Self {
70        Self {
71            name: &package.name,
72            version: package.version.as_ref(),
73        }
74    }
75
76    /// Constructs a new borrowed package key from the given name and version.
77    pub fn from_name_and_version(name: &'a str, version: Option<&'a Version>) -> Self {
78        Self { name, version }
79    }
80
81    /// Converts the borrowed package key into an owned package key.
82    pub fn into_owned(self) -> PackageKey {
83        PackageKey {
84            name: self.name.to_owned(),
85            version: self.version.cloned(),
86        }
87    }
88}
89
90impl fmt::Display for BorrowedPackageKey<'_> {
91    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
92        write!(f, "{name}", name = self.name)?;
93        if let Some(version) = self.version {
94            write!(f, "@{version}")?;
95        }
96
97        Ok(())
98    }
99}
100
101/// A trait implemented by types that can be borrowed as a package key.
102pub trait BorrowedKey {
103    /// Borrows the key as a borrowed package key.
104    fn borrowed_key(&self) -> BorrowedPackageKey;
105}
106
107impl BorrowedKey for PackageKey {
108    fn borrowed_key(&self) -> BorrowedPackageKey {
109        BorrowedPackageKey {
110            name: &self.name,
111            version: self.version.as_ref(),
112        }
113    }
114}
115
116impl BorrowedKey for BorrowedPackageKey<'_> {
117    fn borrowed_key(&self) -> BorrowedPackageKey {
118        *self
119    }
120}
121
122impl<'a> Borrow<dyn BorrowedKey + 'a> for PackageKey {
123    fn borrow(&self) -> &(dyn BorrowedKey + 'a) {
124        self
125    }
126}
127
128impl Eq for (dyn BorrowedKey + '_) {}
129
130impl PartialEq for (dyn BorrowedKey + '_) {
131    fn eq(&self, other: &dyn BorrowedKey) -> bool {
132        self.borrowed_key().eq(&other.borrowed_key())
133    }
134}
135
136impl std::hash::Hash for (dyn BorrowedKey + '_) {
137    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
138        self.borrowed_key().hash(state)
139    }
140}
141
142/// Represents a WebAssembly component model package.
143///
144/// A package is a binary-encoded WebAssembly component.
145#[derive(Clone)]
146#[cfg_attr(feature = "serde", derive(serde::Serialize))]
147#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
148pub struct Package {
149    /// The package name.
150    name: String,
151    /// The package version.
152    version: Option<Version>,
153    /// The bytes of the package.
154    ///
155    /// The bytes are a binary-encoded WebAssembly component.
156    #[cfg_attr(feature = "serde", serde(skip))]
157    bytes: Vec<u8>,
158    /// The type of the represented component.
159    ty: WorldId,
160    /// The type resulting from instantiating the component.
161    instance_type: InterfaceId,
162    /// Defined interfaces and worlds (from a WIT package).
163    definitions: IndexMap<String, ItemKind>,
164}
165
166impl Package {
167    /// Gets the package key for the package.
168    pub fn key(&self) -> BorrowedPackageKey {
169        BorrowedPackageKey::new(self)
170    }
171
172    /// Creates a new package from the given file path.
173    ///
174    /// The package will populate its types into the provided type collection.
175    pub fn from_file(
176        name: &str,
177        version: Option<&Version>,
178        path: impl AsRef<Path>,
179        types: &mut Types,
180    ) -> Result<Self> {
181        let path = path.as_ref();
182        let bytes = std::fs::read(path)
183            .with_context(|| format!("failed to read `{path}`", path = path.display()))?;
184        Self::from_bytes(name, version, bytes, types)
185    }
186
187    /// Creates a new package from the given bytes.
188    ///
189    /// The package will populate its types into the provided type collection.
190    pub fn from_bytes(
191        name: &str,
192        version: Option<&Version>,
193        bytes: impl Into<Vec<u8>>,
194        types: &mut Types,
195    ) -> Result<Self> {
196        let bytes = bytes.into();
197        if !Parser::is_component(&bytes) {
198            bail!("package `{name}` is not a binary-encoded WebAssembly component");
199        }
200
201        let mut parser = Parser::new(0);
202        let mut parsers = Vec::new();
203        let mut validator = Validator::new_with_features(WasmFeatures::all());
204        let mut imports = Vec::new();
205        let mut exports = Vec::new();
206
207        let mut cur = bytes.as_ref();
208        loop {
209            match parser.parse(cur, true)? {
210                Chunk::Parsed { payload, consumed } => {
211                    cur = &cur[consumed..];
212
213                    match validator.payload(&payload)? {
214                        ValidPayload::Ok => {
215                            // Don't parse any sub-components or sub-modules
216                            if !parsers.is_empty() {
217                                continue;
218                            }
219
220                            match payload {
221                                Payload::Version { encoding, .. } => {
222                                    assert_eq!(encoding, Encoding::Component);
223                                }
224                                Payload::ComponentImportSection(s) => {
225                                    imports.reserve(s.count() as usize);
226                                    for import in s {
227                                        imports.push(import?.name.0);
228                                    }
229                                }
230                                Payload::ComponentExportSection(s) => {
231                                    exports.reserve(s.count() as usize);
232                                    for export in s {
233                                        exports.push(export?.name.0);
234                                    }
235                                }
236                                _ => {}
237                            }
238                        }
239                        ValidPayload::Func(_, _) => {}
240                        ValidPayload::Parser(next) => {
241                            parsers.push(parser);
242                            parser = next;
243                        }
244                        ValidPayload::End(wasm_types) => match parsers.pop() {
245                            Some(parent) => parser = parent,
246                            None => {
247                                let mut converter = TypeConverter::new(types, wasm_types);
248
249                                let imports = imports
250                                    .into_iter()
251                                    .map(|i| Ok((i.to_string(), converter.import(i)?)))
252                                    .collect::<Result<_>>()?;
253
254                                let exports: IndexMap<String, ItemKind> = exports
255                                    .into_iter()
256                                    .map(|i| Ok((i.to_string(), converter.export(i)?)))
257                                    .collect::<Result<_>>()?;
258
259                                let ty = types.add_world(World {
260                                    id: None,
261                                    uses: Default::default(),
262                                    imports,
263                                    exports: exports.clone(),
264                                });
265
266                                let instance_type = types.add_interface(Interface {
267                                    id: None,
268                                    uses: Default::default(),
269                                    exports,
270                                });
271
272                                let definitions = Self::find_definitions(types, ty);
273
274                                return Ok(Self {
275                                    name: name.to_owned(),
276                                    version: version.map(ToOwned::to_owned),
277                                    bytes,
278                                    ty,
279                                    instance_type,
280                                    definitions,
281                                });
282                            }
283                        },
284                    }
285                }
286                Chunk::NeedMoreData(_) => panic!("all data should be present"),
287            }
288        }
289    }
290
291    /// Gets the name of the package.
292    pub fn name(&self) -> &str {
293        &self.name
294    }
295
296    /// Gets the version of the package.
297    pub fn version(&self) -> Option<&Version> {
298        self.version.as_ref()
299    }
300
301    /// Gets the bytes of the package.
302    ///
303    /// The bytes are a binary-encoded WebAssembly component.
304    pub fn bytes(&self) -> &[u8] {
305        &self.bytes
306    }
307
308    /// Gets the id of the world (i.e. component type) of the package.
309    pub fn ty(&self) -> WorldId {
310        self.ty
311    }
312
313    /// Gets the id of the interface (i.e. instance type) that would
314    /// result from instantiating the package.
315    pub fn instance_type(&self) -> InterfaceId {
316        self.instance_type
317    }
318
319    /// Gets the interfaces and worlds defined in this package.
320    pub fn definitions(&self) -> &IndexMap<String, ItemKind> {
321        &self.definitions
322    }
323
324    fn find_definitions(types: &Types, world: WorldId) -> IndexMap<String, ItemKind> {
325        // Look for any component type exports that export a component type or instance type
326        let exports = &types[world].exports;
327        let mut defs = IndexMap::new();
328        for (name, kind) in exports {
329            if let ItemKind::Type(Type::World(id)) = kind {
330                let world = &types[*id];
331                if world.exports.len() != 1 {
332                    continue;
333                }
334
335                // Check if the export name is an interface name
336                let (export_name, kind) = world.exports.get_index(0).unwrap();
337                match ComponentName::new(export_name, 0).unwrap().kind() {
338                    ComponentNameKind::Interface(_) => {}
339                    _ => continue,
340                }
341
342                match kind {
343                    ItemKind::Instance(id) => {
344                        defs.insert(name.clone(), ItemKind::Type(Type::Interface(*id)));
345                    }
346                    ItemKind::Component(id) => {
347                        defs.insert(name.clone(), ItemKind::Type(Type::World(*id)));
348                    }
349                    _ => continue,
350                }
351            }
352        }
353
354        defs
355    }
356}
357
358impl fmt::Debug for Package {
359    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360        f.debug_struct("Package")
361            .field("name", &self.name)
362            .field("version", &self.version)
363            .field("bytes", &"...")
364            .field("ty", &self.ty)
365            .field("instance_type", &self.instance_type)
366            .field("definitions", &self.definitions)
367            .finish()
368    }
369}
370
371#[derive(Debug, Clone, Copy, PartialEq, Eq)]
372enum Owner {
373    /// The owner is an interface.
374    Interface(InterfaceId),
375    /// The owner is a world.
376    World(WorldId),
377}
378
379#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
380enum Entity {
381    /// The entity is a type.
382    Type(Type),
383    /// The entity is a resource.
384    Resource(ResourceId),
385}
386
387/// Responsible for converting between wasmparser and wac-parser type
388/// representations.
389struct TypeConverter<'a> {
390    types: &'a mut Types,
391    wasm_types: Rc<wasmparser::types::Types>,
392    cache: HashMap<wasm::AnyTypeId, Entity>,
393    resource_map: HashMap<wasm::ResourceId, ResourceId>,
394    owners: HashMap<wasm::ComponentAnyTypeId, (Owner, String)>,
395}
396
397impl<'a> TypeConverter<'a> {
398    fn new(types: &'a mut Types, wasm_types: wasmparser::types::Types) -> Self {
399        Self {
400            types,
401            wasm_types: Rc::new(wasm_types),
402            cache: Default::default(),
403            resource_map: Default::default(),
404            owners: Default::default(),
405        }
406    }
407
408    fn import(&mut self, name: &str) -> Result<ItemKind> {
409        let import = self
410            .wasm_types
411            .component_entity_type_of_import(name)
412            .unwrap();
413        self.entity(name, import)
414    }
415
416    fn export(&mut self, name: &str) -> Result<ItemKind> {
417        let export = self
418            .wasm_types
419            .component_entity_type_of_export(name)
420            .unwrap();
421        self.entity(name, export)
422    }
423
424    fn component_func_type(&mut self, id: wasm::ComponentFuncTypeId) -> Result<FuncTypeId> {
425        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Func(id));
426        if let Some(ty) = self.cache.get(&key) {
427            match ty {
428                Entity::Type(Type::Func(id)) => return Ok(*id),
429                _ => panic!("invalid cached type"),
430            }
431        }
432
433        let wasm_types = self.wasm_types.clone();
434        let func_ty = &wasm_types[id];
435        let params = func_ty
436            .params
437            .iter()
438            .map(|(name, ty)| Ok((name.to_string(), self.component_val_type(*ty)?)))
439            .collect::<Result<_>>()?;
440
441        let result = match func_ty.result {
442            Some(ty) => Some(self.component_val_type(ty)?),
443            None => None,
444        };
445
446        let id = self.types.add_func_type(FuncType { params, result });
447        self.cache.insert(key, Entity::Type(Type::Func(id)));
448        Ok(id)
449    }
450
451    fn module_type(&mut self, id: wasm::ComponentCoreModuleTypeId) -> Result<ModuleTypeId> {
452        let key = wasm::AnyTypeId::Core(wasm::ComponentCoreTypeId::Module(id));
453        if let Some(ty) = self.cache.get(&key) {
454            match ty {
455                Entity::Type(Type::Module(id)) => return Ok(*id),
456                _ => panic!("invalid cached type"),
457            }
458        }
459
460        let module_ty = &self.wasm_types[id];
461
462        let imports = module_ty
463            .imports
464            .iter()
465            .map(|((module, name), ty)| ((module.clone(), name.clone()), self.entity_type(*ty)))
466            .collect();
467
468        let exports = module_ty
469            .exports
470            .iter()
471            .map(|(name, ty)| (name.clone(), self.entity_type(*ty)))
472            .collect();
473
474        let module_id = self.types.add_module_type(ModuleType { imports, exports });
475        self.cache
476            .insert(key, Entity::Type(Type::Module(module_id)));
477        Ok(module_id)
478    }
479
480    fn ty(&mut self, name: &str, id: wasm::ComponentAnyTypeId) -> Result<Type> {
481        match id {
482            wasm::ComponentAnyTypeId::Defined(id) => {
483                Ok(Type::Value(self.component_defined_type(id)?))
484            }
485            wasm::ComponentAnyTypeId::Func(id) => Ok(Type::Func(self.component_func_type(id)?)),
486            wasm::ComponentAnyTypeId::Component(id) => {
487                Ok(Type::World(self.component_type(None, id)?))
488            }
489            wasm::ComponentAnyTypeId::Instance(id) => {
490                Ok(Type::Interface(self.component_instance_type(None, id)?))
491            }
492            wasm::ComponentAnyTypeId::Resource(id) => Ok(Type::Resource(self.resource(name, id))),
493        }
494    }
495
496    fn component_val_type(&mut self, ty: wasm::ComponentValType) -> Result<ValueType> {
497        match ty {
498            wasm::ComponentValType::Primitive(ty) => Ok(ValueType::Primitive(ty.into())),
499            wasm::ComponentValType::Type(id) => Ok(self.component_defined_type(id)?),
500        }
501    }
502
503    fn component_instance_type(
504        &mut self,
505        name: Option<&str>,
506        id: wasm::ComponentInstanceTypeId,
507    ) -> Result<InterfaceId> {
508        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Instance(id));
509        if let Some(ty) = self.cache.get(&key) {
510            match ty {
511                Entity::Type(Type::Interface(id)) => {
512                    return Ok(*id);
513                }
514                _ => panic!("invalid cached type"),
515            }
516        }
517
518        let wasm_types = self.wasm_types.clone();
519        let instance_ty = &wasm_types[id];
520        let id = self.types.add_interface(Interface {
521            id: name.and_then(|n| n.contains(':').then(|| n.to_owned())),
522            uses: Default::default(),
523            exports: IndexMap::with_capacity(instance_ty.exports.len()),
524        });
525
526        for (name, ty) in &instance_ty.exports {
527            let export = self.entity(name, *ty)?;
528
529            if let wasm::ComponentEntityType::Type {
530                referenced,
531                created,
532            } = ty
533            {
534                self.use_or_own(Owner::Interface(id), name, *referenced, *created);
535
536                // Prevent self-referential ownership of any aliased resources in this interface
537                if let ItemKind::Type(Type::Resource(res)) = export {
538                    if let Some(ResourceAlias { owner, .. }) = &mut self.types[res].alias {
539                        if let Some(owner_id) = owner {
540                            if *owner_id == id {
541                                *owner = None;
542                            }
543                        }
544                    }
545                }
546            }
547
548            let prev = self.types[id].exports.insert(name.clone(), export);
549            assert!(prev.is_none());
550        }
551
552        self.cache.insert(key, Entity::Type(Type::Interface(id)));
553        Ok(id)
554    }
555
556    fn entity(&mut self, name: &str, ty: wasm::ComponentEntityType) -> Result<ItemKind> {
557        match ty {
558            wasm::ComponentEntityType::Module(id) => Ok(ItemKind::Module(self.module_type(id)?)),
559            wasm::ComponentEntityType::Value(ty) => {
560                Ok(ItemKind::Value(self.component_val_type(ty)?))
561            }
562            wasm::ComponentEntityType::Type { created, .. } => {
563                Ok(ItemKind::Type(self.ty(name, created)?))
564            }
565            wasm::ComponentEntityType::Func(id) => {
566                Ok(ItemKind::Func(self.component_func_type(id)?))
567            }
568            wasm::ComponentEntityType::Instance(id) => Ok(ItemKind::Instance(
569                self.component_instance_type(Some(name), id)?,
570            )),
571            wasm::ComponentEntityType::Component(id) => {
572                Ok(ItemKind::Component(self.component_type(Some(name), id)?))
573            }
574        }
575    }
576
577    fn use_or_own(
578        &mut self,
579        owner: Owner,
580        name: &str,
581        referenced: wasm::ComponentAnyTypeId,
582        created: wasm::ComponentAnyTypeId,
583    ) {
584        if let Some((other, orig)) = self.find_owner(referenced) {
585            match *other {
586                Owner::Interface(interface) if owner != *other => {
587                    let used = UsedType {
588                        interface,
589                        name: if name != orig {
590                            Some(orig.to_string())
591                        } else {
592                            None
593                        },
594                    };
595
596                    // Owner is a different interface, so add a using reference
597                    let uses = match owner {
598                        Owner::Interface(id) => &mut self.types[id].uses,
599                        Owner::World(id) => &mut self.types[id].uses,
600                    };
601
602                    uses.insert(name.to_string(), used);
603                }
604                _ => {}
605            }
606            return;
607        }
608
609        // Take ownership of the entity
610        let prev = self.owners.insert(created, (owner, name.to_string()));
611        assert!(prev.is_none());
612    }
613
614    fn component_type(&mut self, name: Option<&str>, id: wasm::ComponentTypeId) -> Result<WorldId> {
615        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Component(id));
616        if let Some(ty) = self.cache.get(&key) {
617            match ty {
618                Entity::Type(Type::World(id)) => return Ok(*id),
619                _ => panic!("invalid cached type"),
620            }
621        }
622
623        let wasm_types = self.wasm_types.clone();
624        let component_ty = &wasm_types[id];
625        let id = self.types.add_world(World {
626            id: name.and_then(|n| n.contains(':').then(|| n.to_owned())),
627            uses: Default::default(),
628            imports: IndexMap::with_capacity(component_ty.imports.len()),
629            exports: IndexMap::with_capacity(component_ty.exports.len()),
630        });
631
632        for (name, ty) in &component_ty.imports {
633            let import = self.entity(name, *ty)?;
634
635            if let wasm::ComponentEntityType::Type {
636                referenced,
637                created,
638            } = ty
639            {
640                self.use_or_own(Owner::World(id), name, *referenced, *created);
641            }
642
643            let prev = self.types[id].imports.insert(name.clone(), import);
644            assert!(prev.is_none());
645        }
646
647        for (name, ty) in &component_ty.exports {
648            let ty = self.entity(name, *ty)?;
649            let prev = self.types[id].exports.insert(name.clone(), ty);
650            assert!(prev.is_none());
651        }
652
653        self.cache.insert(key, Entity::Type(Type::World(id)));
654        Ok(id)
655    }
656
657    fn component_defined_type(&mut self, id: wasm::ComponentDefinedTypeId) -> Result<ValueType> {
658        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Defined(id));
659        if let Some(ty) = self.cache.get(&key) {
660            match ty {
661                Entity::Type(Type::Value(ty)) => return Ok(*ty),
662                _ => panic!("invalid cached type"),
663            }
664        }
665
666        let wasm_types = self.wasm_types.clone();
667        let ty = match &wasm_types[id] {
668            wasm::ComponentDefinedType::Primitive(ty) => ValueType::Defined(
669                self.types
670                    .add_defined_type(DefinedType::Alias(ValueType::Primitive((*ty).into()))),
671            ),
672            wasm::ComponentDefinedType::Record(ty) => {
673                let fields = ty
674                    .fields
675                    .iter()
676                    .map(|(name, ty)| Ok((name.as_str().to_owned(), self.component_val_type(*ty)?)))
677                    .collect::<Result<_>>()?;
678
679                ValueType::Defined(
680                    self.types
681                        .add_defined_type(DefinedType::Record(Record { fields })),
682                )
683            }
684            wasm::ComponentDefinedType::Variant(ty) => {
685                let cases = ty
686                    .cases
687                    .iter()
688                    .map(|(name, case)| {
689                        Ok((
690                            name.as_str().to_owned(),
691                            case.ty.map(|ty| self.component_val_type(ty)).transpose()?,
692                        ))
693                    })
694                    .collect::<Result<_>>()?;
695
696                ValueType::Defined(
697                    self.types
698                        .add_defined_type(DefinedType::Variant(Variant { cases })),
699                )
700            }
701            wasm::ComponentDefinedType::List(ty) => {
702                let ty = self.component_val_type(*ty)?;
703                ValueType::Defined(self.types.add_defined_type(DefinedType::List(ty)))
704            }
705            wasm::ComponentDefinedType::Tuple(ty) => {
706                let types = ty
707                    .types
708                    .iter()
709                    .map(|ty| self.component_val_type(*ty))
710                    .collect::<Result<_>>()?;
711                ValueType::Defined(self.types.add_defined_type(DefinedType::Tuple(types)))
712            }
713            wasm::ComponentDefinedType::Flags(flags) => {
714                let flags = flags.iter().map(|flag| flag.as_str().to_owned()).collect();
715                ValueType::Defined(
716                    self.types
717                        .add_defined_type(DefinedType::Flags(Flags(flags))),
718                )
719            }
720            wasm::ComponentDefinedType::Enum(cases) => {
721                let cases = cases.iter().map(|case| case.as_str().to_owned()).collect();
722                ValueType::Defined(self.types.add_defined_type(DefinedType::Enum(Enum(cases))))
723            }
724            wasm::ComponentDefinedType::Option(ty) => {
725                let ty = self.component_val_type(*ty)?;
726                ValueType::Defined(self.types.add_defined_type(DefinedType::Option(ty)))
727            }
728            wasm::ComponentDefinedType::Result { ok, err } => {
729                let ok = ok.map(|ty| self.component_val_type(ty)).transpose()?;
730                let err = err.map(|ty| self.component_val_type(ty)).transpose()?;
731                ValueType::Defined(self.types.add_defined_type(DefinedType::Result { ok, err }))
732            }
733            wasm::ComponentDefinedType::Borrow(id) => ValueType::Borrow(
734                match self.cache.get(&wasm::AnyTypeId::Component(
735                    wasm::ComponentAnyTypeId::Resource(*id),
736                )) {
737                    Some(Entity::Resource(id)) => *id,
738                    _ => panic!("expected a resource"),
739                },
740            ),
741            wasm::ComponentDefinedType::Own(id) => ValueType::Own(
742                match self.cache.get(&wasm::AnyTypeId::Component(
743                    wasm::ComponentAnyTypeId::Resource(*id),
744                )) {
745                    Some(Entity::Resource(id)) => *id,
746                    _ => panic!("expected a resource"),
747                },
748            ),
749            wasm::ComponentDefinedType::Stream(ty) => {
750                let stream = ty.map(|ty| self.component_val_type(ty)).transpose()?;
751                ValueType::Defined(self.types.add_defined_type(DefinedType::Stream(stream)))
752            }
753            wasm::ComponentDefinedType::Future(ty) => {
754                let option = ty.map(|ty| self.component_val_type(ty)).transpose()?;
755                ValueType::Defined(self.types.add_defined_type(DefinedType::Future(option)))
756            }
757            wasm::ComponentDefinedType::FixedSizeList(ty, _) => {
758                let ty = self.component_val_type(*ty)?;
759                ValueType::Defined(self.types.add_defined_type(DefinedType::List(ty)))
760            }
761        };
762
763        self.cache.insert(key, Entity::Type(Type::Value(ty)));
764        Ok(ty)
765    }
766
767    fn resource(&mut self, name: &str, id: wasm::AliasableResourceId) -> ResourceId {
768        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Resource(id));
769        if let Some(ty) = self.cache.get(&key) {
770            match ty {
771                Entity::Resource(id) => return *id,
772                _ => panic!("invalid cached type"),
773            }
774        }
775
776        // Check if this is an alias of another resource
777        if let Some(resource_id) = self.resource_map.get(&id.resource()) {
778            let alias_id = self.types.add_resource(Resource {
779                name: name.to_owned(),
780                alias: Some(ResourceAlias {
781                    owner: match self.find_owner(wasm::ComponentAnyTypeId::Resource(id)) {
782                        Some((Owner::Interface(id), _)) => Some(*id),
783                        _ => None,
784                    },
785                    source: *resource_id,
786                }),
787            });
788            self.cache.insert(key, Entity::Resource(alias_id));
789            return alias_id;
790        }
791
792        // Otherwise, this is a new resource
793        let resource_id = self.types.add_resource(Resource {
794            name: name.to_owned(),
795            alias: None,
796        });
797
798        self.resource_map.insert(id.resource(), resource_id);
799        self.cache.insert(key, Entity::Resource(resource_id));
800        resource_id
801    }
802
803    fn entity_type(&self, ty: wasmparser::types::EntityType) -> CoreExtern {
804        match ty {
805            wasmparser::types::EntityType::Func(ty) => CoreExtern::Func(self.func_type(ty)),
806            wasmparser::types::EntityType::Table(ty) => ty.into(),
807            wasmparser::types::EntityType::Memory(ty) => ty.into(),
808            wasmparser::types::EntityType::Global(ty) => ty.into(),
809            wasmparser::types::EntityType::Tag(ty) => CoreExtern::Tag(self.func_type(ty)),
810        }
811    }
812
813    fn func_type(&self, ty: wasmparser::types::CoreTypeId) -> CoreFuncType {
814        let func_ty = self.wasm_types[ty].unwrap_func();
815        CoreFuncType {
816            params: func_ty.params().iter().copied().map(Into::into).collect(),
817            results: func_ty.results().iter().copied().map(Into::into).collect(),
818        }
819    }
820
821    fn find_owner(&self, mut id: wasm::ComponentAnyTypeId) -> Option<&(Owner, String)> {
822        let mut prev = None;
823        while prev.is_none() {
824            prev = self.owners.get(&id);
825            id = match self.wasm_types.peel_alias(id) {
826                Some(next) => next,
827                None => break,
828            };
829        }
830        prev
831    }
832}