wac_types/
package.rs

1use crate::{
2    CoreExtern, CoreFuncType, DefinedType, Enum, Flags, FuncResult, FuncType, FuncTypeId,
3    Interface, InterfaceId, ItemKind, ModuleType, ModuleTypeId, Record, Resource, ResourceAlias,
4    ResourceId, 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    names::{ComponentName, ComponentNameKind},
14    types::{self as wasm, ComponentAnyTypeId},
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<'a> std::hash::Hash for (dyn BorrowedKey + 'a) {
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 {
204            component_model: true,
205            ..Default::default()
206        });
207        let mut imports = Vec::new();
208        let mut exports = Vec::new();
209
210        let mut cur = bytes.as_ref();
211        loop {
212            match parser.parse(cur, true)? {
213                Chunk::Parsed { payload, consumed } => {
214                    cur = &cur[consumed..];
215
216                    match validator.payload(&payload)? {
217                        ValidPayload::Ok => {
218                            // Don't parse any sub-components or sub-modules
219                            if !parsers.is_empty() {
220                                continue;
221                            }
222
223                            match payload {
224                                Payload::Version { encoding, .. } => {
225                                    assert_eq!(encoding, Encoding::Component);
226                                }
227                                Payload::ComponentImportSection(s) => {
228                                    imports.reserve(s.count() as usize);
229                                    for import in s {
230                                        imports.push(import?.name.0);
231                                    }
232                                }
233                                Payload::ComponentExportSection(s) => {
234                                    exports.reserve(s.count() as usize);
235                                    for export in s {
236                                        exports.push(export?.name.0);
237                                    }
238                                }
239                                _ => {}
240                            }
241                        }
242                        ValidPayload::Func(_, _) => {}
243                        ValidPayload::Parser(next) => {
244                            parsers.push(parser);
245                            parser = next;
246                        }
247                        ValidPayload::End(wasm_types) => match parsers.pop() {
248                            Some(parent) => parser = parent,
249                            None => {
250                                let mut converter = TypeConverter::new(types, wasm_types);
251
252                                let imports = imports
253                                    .into_iter()
254                                    .map(|i| Ok((i.to_string(), converter.import(i)?)))
255                                    .collect::<Result<_>>()?;
256
257                                let exports: IndexMap<String, ItemKind> = exports
258                                    .into_iter()
259                                    .map(|i| Ok((i.to_string(), converter.export(i)?)))
260                                    .collect::<Result<_>>()?;
261
262                                let ty = types.add_world(World {
263                                    id: None,
264                                    uses: Default::default(),
265                                    imports,
266                                    exports: exports.clone(),
267                                });
268
269                                let instance_type = types.add_interface(Interface {
270                                    id: None,
271                                    uses: Default::default(),
272                                    exports,
273                                });
274
275                                let definitions = Self::find_definitions(types, ty);
276
277                                return Ok(Self {
278                                    name: name.to_owned(),
279                                    version: version.map(ToOwned::to_owned),
280                                    bytes,
281                                    ty,
282                                    instance_type,
283                                    definitions,
284                                });
285                            }
286                        },
287                    }
288                }
289                Chunk::NeedMoreData(_) => panic!("all data should be present"),
290            }
291        }
292    }
293
294    /// Gets the name of the package.
295    pub fn name(&self) -> &str {
296        &self.name
297    }
298
299    /// Gets the version of the package.
300    pub fn version(&self) -> Option<&Version> {
301        self.version.as_ref()
302    }
303
304    /// Gets the bytes of the package.
305    ///
306    /// The bytes are a binary-encoded WebAssembly component.
307    pub fn bytes(&self) -> &[u8] {
308        &self.bytes
309    }
310
311    /// Gets the id of the world (i.e. component type) of the package.
312    pub fn ty(&self) -> WorldId {
313        self.ty
314    }
315
316    /// Gets the id of the interface (i.e. instance type) that would
317    /// result from instantiating the package.
318    pub fn instance_type(&self) -> InterfaceId {
319        self.instance_type
320    }
321
322    /// Gets the interfaces and worlds defined in this package.
323    pub fn definitions(&self) -> &IndexMap<String, ItemKind> {
324        &self.definitions
325    }
326
327    fn find_definitions(types: &Types, world: WorldId) -> IndexMap<String, ItemKind> {
328        // Look for any component type exports that export a component type or instance type
329        let exports = &types[world].exports;
330        let mut defs = IndexMap::new();
331        for (name, kind) in exports {
332            if let ItemKind::Type(Type::World(id)) = kind {
333                let world = &types[*id];
334                if world.exports.len() != 1 {
335                    continue;
336                }
337
338                // Check if the export name is an interface name
339                let (export_name, kind) = world.exports.get_index(0).unwrap();
340                match ComponentName::new(export_name, 0).unwrap().kind() {
341                    ComponentNameKind::Interface(_) => {}
342                    _ => continue,
343                }
344
345                match kind {
346                    ItemKind::Instance(id) => {
347                        defs.insert(name.clone(), ItemKind::Type(Type::Interface(*id)));
348                    }
349                    ItemKind::Component(id) => {
350                        defs.insert(name.clone(), ItemKind::Type(Type::World(*id)));
351                    }
352                    _ => continue,
353                }
354            }
355        }
356
357        defs
358    }
359}
360
361impl fmt::Debug for Package {
362    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
363        f.debug_struct("Package")
364            .field("name", &self.name)
365            .field("version", &self.version)
366            .field("bytes", &"...")
367            .field("ty", &self.ty)
368            .field("instance_type", &self.instance_type)
369            .field("definitions", &self.definitions)
370            .finish()
371    }
372}
373
374#[derive(Debug, Clone, Copy, PartialEq, Eq)]
375enum Owner {
376    /// The owner is an interface.
377    Interface(InterfaceId),
378    /// The owner is a world.
379    World(WorldId),
380}
381
382#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
383enum Entity {
384    /// The entity is a type.
385    Type(Type),
386    /// The entity is a resource.
387    Resource(ResourceId),
388}
389
390/// Responsible for converting between wasmparser and wac-parser type
391/// representations.
392struct TypeConverter<'a> {
393    types: &'a mut Types,
394    wasm_types: Rc<wasm::Types>,
395    cache: HashMap<wasm::AnyTypeId, Entity>,
396    resource_map: HashMap<wasm::ResourceId, ResourceId>,
397    owners: HashMap<wasm::ComponentAnyTypeId, (Owner, String)>,
398}
399
400impl<'a> TypeConverter<'a> {
401    fn new(types: &'a mut Types, wasm_types: wasm::Types) -> Self {
402        Self {
403            types,
404            wasm_types: Rc::new(wasm_types),
405            cache: Default::default(),
406            resource_map: Default::default(),
407            owners: Default::default(),
408        }
409    }
410
411    fn import(&mut self, name: &str) -> Result<ItemKind> {
412        let import = self
413            .wasm_types
414            .component_entity_type_of_import(name)
415            .unwrap();
416        self.entity(name, import)
417    }
418
419    fn export(&mut self, name: &str) -> Result<ItemKind> {
420        let export = self
421            .wasm_types
422            .component_entity_type_of_export(name)
423            .unwrap();
424        self.entity(name, export)
425    }
426
427    fn component_func_type(&mut self, id: wasm::ComponentFuncTypeId) -> Result<FuncTypeId> {
428        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Func(id));
429        if let Some(ty) = self.cache.get(&key) {
430            match ty {
431                Entity::Type(Type::Func(id)) => return Ok(*id),
432                _ => panic!("invalid cached type"),
433            }
434        }
435
436        let wasm_types = self.wasm_types.clone();
437        let func_ty = &wasm_types[id];
438        let params = func_ty
439            .params
440            .iter()
441            .map(|(name, ty)| Ok((name.to_string(), self.component_val_type(*ty)?)))
442            .collect::<Result<_>>()?;
443
444        let results = if func_ty.results.len() == 0 {
445            None
446        } else if func_ty.results.len() == 1 && func_ty.results[0].0.is_none() {
447            Some(FuncResult::Scalar(
448                self.component_val_type(func_ty.results[0].1)?,
449            ))
450        } else {
451            Some(FuncResult::List(
452                func_ty
453                    .results
454                    .iter()
455                    .map(|(name, ty)| {
456                        Ok((
457                            name.as_ref().unwrap().to_string(),
458                            self.component_val_type(*ty)?,
459                        ))
460                    })
461                    .collect::<Result<_>>()?,
462            ))
463        };
464
465        let id = self.types.add_func_type(FuncType { params, results });
466        self.cache.insert(key, Entity::Type(Type::Func(id)));
467        Ok(id)
468    }
469
470    fn module_type(&mut self, id: wasm::ComponentCoreModuleTypeId) -> Result<ModuleTypeId> {
471        let key = wasm::AnyTypeId::Core(wasm::ComponentCoreTypeId::Module(id));
472        if let Some(ty) = self.cache.get(&key) {
473            match ty {
474                Entity::Type(Type::Module(id)) => return Ok(*id),
475                _ => panic!("invalid cached type"),
476            }
477        }
478
479        let module_ty = &self.wasm_types[id];
480
481        let imports = module_ty
482            .imports
483            .iter()
484            .map(|((module, name), ty)| ((module.clone(), name.clone()), self.entity_type(*ty)))
485            .collect();
486
487        let exports = module_ty
488            .exports
489            .iter()
490            .map(|(name, ty)| (name.clone(), self.entity_type(*ty)))
491            .collect();
492
493        let module_id = self.types.add_module_type(ModuleType { imports, exports });
494        self.cache
495            .insert(key, Entity::Type(Type::Module(module_id)));
496        Ok(module_id)
497    }
498
499    fn ty(&mut self, name: &str, id: wasm::ComponentAnyTypeId) -> Result<Type> {
500        match id {
501            wasm::ComponentAnyTypeId::Defined(id) => {
502                Ok(Type::Value(self.component_defined_type(id)?))
503            }
504            wasm::ComponentAnyTypeId::Func(id) => Ok(Type::Func(self.component_func_type(id)?)),
505            wasm::ComponentAnyTypeId::Component(id) => {
506                Ok(Type::World(self.component_type(None, id)?))
507            }
508            wasm::ComponentAnyTypeId::Instance(id) => {
509                Ok(Type::Interface(self.component_instance_type(None, id)?))
510            }
511            wasm::ComponentAnyTypeId::Resource(id) => Ok(Type::Resource(self.resource(name, id))),
512        }
513    }
514
515    fn component_val_type(&mut self, ty: wasm::ComponentValType) -> Result<ValueType> {
516        match ty {
517            wasm::ComponentValType::Primitive(ty) => Ok(ValueType::Primitive(ty.into())),
518            wasm::ComponentValType::Type(id) => Ok(self.component_defined_type(id)?),
519        }
520    }
521
522    fn component_instance_type(
523        &mut self,
524        name: Option<&str>,
525        id: wasm::ComponentInstanceTypeId,
526    ) -> Result<InterfaceId> {
527        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Instance(id));
528        if let Some(ty) = self.cache.get(&key) {
529            match ty {
530                Entity::Type(Type::Interface(id)) => {
531                    return Ok(*id);
532                }
533                _ => panic!("invalid cached type"),
534            }
535        }
536
537        let wasm_types = self.wasm_types.clone();
538        let instance_ty = &wasm_types[id];
539        let id = self.types.add_interface(Interface {
540            id: name.and_then(|n| n.contains(':').then(|| n.to_owned())),
541            uses: Default::default(),
542            exports: IndexMap::with_capacity(instance_ty.exports.len()),
543        });
544
545        for (name, ty) in &instance_ty.exports {
546            let export = self.entity(name, *ty)?;
547
548            if let wasm::ComponentEntityType::Type {
549                referenced,
550                created,
551            } = ty
552            {
553                self.use_or_own(Owner::Interface(id), name, *referenced, *created);
554
555                // Prevent self-referential ownership of any aliased resources in this interface
556                if let ItemKind::Type(Type::Resource(res)) = export {
557                    if let Some(ResourceAlias { owner, .. }) = &mut self.types[res].alias {
558                        if let Some(owner_id) = owner {
559                            if *owner_id == id {
560                                *owner = None;
561                            }
562                        }
563                    }
564                }
565            }
566
567            let prev = self.types[id].exports.insert(name.clone(), export);
568            assert!(prev.is_none());
569        }
570
571        self.cache.insert(key, Entity::Type(Type::Interface(id)));
572        Ok(id)
573    }
574
575    fn entity(&mut self, name: &str, ty: wasm::ComponentEntityType) -> Result<ItemKind> {
576        match ty {
577            wasm::ComponentEntityType::Module(id) => Ok(ItemKind::Module(self.module_type(id)?)),
578            wasm::ComponentEntityType::Value(ty) => {
579                Ok(ItemKind::Value(self.component_val_type(ty)?))
580            }
581            wasm::ComponentEntityType::Type { created, .. } => {
582                Ok(ItemKind::Type(self.ty(name, created)?))
583            }
584            wasm::ComponentEntityType::Func(id) => {
585                Ok(ItemKind::Func(self.component_func_type(id)?))
586            }
587            wasm::ComponentEntityType::Instance(id) => Ok(ItemKind::Instance(
588                self.component_instance_type(Some(name), id)?,
589            )),
590            wasm::ComponentEntityType::Component(id) => {
591                Ok(ItemKind::Component(self.component_type(Some(name), id)?))
592            }
593        }
594    }
595
596    fn use_or_own(
597        &mut self,
598        owner: Owner,
599        name: &str,
600        referenced: ComponentAnyTypeId,
601        created: ComponentAnyTypeId,
602    ) {
603        if let Some((other, orig)) = self.find_owner(referenced) {
604            match *other {
605                Owner::Interface(interface) if owner != *other => {
606                    let used = UsedType {
607                        interface,
608                        name: if name != orig {
609                            Some(orig.to_string())
610                        } else {
611                            None
612                        },
613                    };
614
615                    // Owner is a different interface, so add a using reference
616                    let uses = match owner {
617                        Owner::Interface(id) => &mut self.types[id].uses,
618                        Owner::World(id) => &mut self.types[id].uses,
619                    };
620
621                    uses.insert(name.to_string(), used);
622                }
623                _ => {}
624            }
625            return;
626        }
627
628        // Take ownership of the entity
629        let prev = self.owners.insert(created, (owner, name.to_string()));
630        assert!(prev.is_none());
631    }
632
633    fn component_type(&mut self, name: Option<&str>, id: wasm::ComponentTypeId) -> Result<WorldId> {
634        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Component(id));
635        if let Some(ty) = self.cache.get(&key) {
636            match ty {
637                Entity::Type(Type::World(id)) => return Ok(*id),
638                _ => panic!("invalid cached type"),
639            }
640        }
641
642        let wasm_types = self.wasm_types.clone();
643        let component_ty = &wasm_types[id];
644        let id = self.types.add_world(World {
645            id: name.and_then(|n| n.contains(':').then(|| n.to_owned())),
646            uses: Default::default(),
647            imports: IndexMap::with_capacity(component_ty.imports.len()),
648            exports: IndexMap::with_capacity(component_ty.exports.len()),
649        });
650
651        for (name, ty) in &component_ty.imports {
652            let import = self.entity(name, *ty)?;
653
654            if let wasm::ComponentEntityType::Type {
655                referenced,
656                created,
657            } = ty
658            {
659                self.use_or_own(Owner::World(id), name, *referenced, *created);
660            }
661
662            let prev = self.types[id].imports.insert(name.clone(), import);
663            assert!(prev.is_none());
664        }
665
666        for (name, ty) in &component_ty.exports {
667            let ty = self.entity(name, *ty)?;
668            let prev = self.types[id].exports.insert(name.clone(), ty);
669            assert!(prev.is_none());
670        }
671
672        self.cache.insert(key, Entity::Type(Type::World(id)));
673        Ok(id)
674    }
675
676    fn component_defined_type(&mut self, id: wasm::ComponentDefinedTypeId) -> Result<ValueType> {
677        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Defined(id));
678        if let Some(ty) = self.cache.get(&key) {
679            match ty {
680                Entity::Type(Type::Value(ty)) => return Ok(*ty),
681                _ => panic!("invalid cached type"),
682            }
683        }
684
685        let wasm_types = self.wasm_types.clone();
686        let ty = match &wasm_types[id] {
687            wasm::ComponentDefinedType::Primitive(ty) => ValueType::Defined(
688                self.types
689                    .add_defined_type(DefinedType::Alias(ValueType::Primitive((*ty).into()))),
690            ),
691            wasm::ComponentDefinedType::Record(ty) => {
692                let fields = ty
693                    .fields
694                    .iter()
695                    .map(|(name, ty)| Ok((name.as_str().to_owned(), self.component_val_type(*ty)?)))
696                    .collect::<Result<_>>()?;
697
698                ValueType::Defined(
699                    self.types
700                        .add_defined_type(DefinedType::Record(Record { fields })),
701                )
702            }
703            wasm::ComponentDefinedType::Variant(ty) => {
704                let cases = ty
705                    .cases
706                    .iter()
707                    .map(|(name, case)| {
708                        Ok((
709                            name.as_str().to_owned(),
710                            case.ty.map(|ty| self.component_val_type(ty)).transpose()?,
711                        ))
712                    })
713                    .collect::<Result<_>>()?;
714
715                ValueType::Defined(
716                    self.types
717                        .add_defined_type(DefinedType::Variant(Variant { cases })),
718                )
719            }
720            wasm::ComponentDefinedType::List(ty) => {
721                let ty = self.component_val_type(*ty)?;
722                ValueType::Defined(self.types.add_defined_type(DefinedType::List(ty)))
723            }
724            wasm::ComponentDefinedType::Tuple(ty) => {
725                let types = ty
726                    .types
727                    .iter()
728                    .map(|ty| self.component_val_type(*ty))
729                    .collect::<Result<_>>()?;
730                ValueType::Defined(self.types.add_defined_type(DefinedType::Tuple(types)))
731            }
732            wasm::ComponentDefinedType::Flags(flags) => {
733                let flags = flags.iter().map(|flag| flag.as_str().to_owned()).collect();
734                ValueType::Defined(
735                    self.types
736                        .add_defined_type(DefinedType::Flags(Flags(flags))),
737                )
738            }
739            wasm::ComponentDefinedType::Enum(cases) => {
740                let cases = cases.iter().map(|case| case.as_str().to_owned()).collect();
741                ValueType::Defined(self.types.add_defined_type(DefinedType::Enum(Enum(cases))))
742            }
743            wasm::ComponentDefinedType::Option(ty) => {
744                let ty = self.component_val_type(*ty)?;
745                ValueType::Defined(self.types.add_defined_type(DefinedType::Option(ty)))
746            }
747            wasm::ComponentDefinedType::Result { ok, err } => {
748                let ok = ok.map(|ty| self.component_val_type(ty)).transpose()?;
749                let err = err.map(|ty| self.component_val_type(ty)).transpose()?;
750                ValueType::Defined(self.types.add_defined_type(DefinedType::Result { ok, err }))
751            }
752            wasm::ComponentDefinedType::Borrow(id) => ValueType::Borrow(
753                match self.cache.get(&wasm::AnyTypeId::Component(
754                    wasm::ComponentAnyTypeId::Resource(*id),
755                )) {
756                    Some(Entity::Resource(id)) => *id,
757                    _ => panic!("expected a resource"),
758                },
759            ),
760            wasm::ComponentDefinedType::Own(id) => ValueType::Own(
761                match self.cache.get(&wasm::AnyTypeId::Component(
762                    wasm::ComponentAnyTypeId::Resource(*id),
763                )) {
764                    Some(Entity::Resource(id)) => *id,
765                    _ => panic!("expected a resource"),
766                },
767            ),
768        };
769
770        self.cache.insert(key, Entity::Type(Type::Value(ty)));
771        Ok(ty)
772    }
773
774    fn resource(&mut self, name: &str, id: wasm::AliasableResourceId) -> ResourceId {
775        let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Resource(id));
776        if let Some(ty) = self.cache.get(&key) {
777            match ty {
778                Entity::Resource(id) => return *id,
779                _ => panic!("invalid cached type"),
780            }
781        }
782
783        // Check if this is an alias of another resource
784        if let Some(resource_id) = self.resource_map.get(&id.resource()) {
785            let alias_id = self.types.add_resource(Resource {
786                name: name.to_owned(),
787                alias: Some(ResourceAlias {
788                    owner: match self.find_owner(ComponentAnyTypeId::Resource(id)) {
789                        Some((Owner::Interface(id), _)) => Some(*id),
790                        _ => None,
791                    },
792                    source: *resource_id,
793                }),
794            });
795            self.cache.insert(key, Entity::Resource(alias_id));
796            return alias_id;
797        }
798
799        // Otherwise, this is a new resource
800        let resource_id = self.types.add_resource(Resource {
801            name: name.to_owned(),
802            alias: None,
803        });
804
805        self.resource_map.insert(id.resource(), resource_id);
806        self.cache.insert(key, Entity::Resource(resource_id));
807        resource_id
808    }
809
810    fn entity_type(&self, ty: wasm::EntityType) -> CoreExtern {
811        match ty {
812            wasm::EntityType::Func(ty) => CoreExtern::Func(self.func_type(ty)),
813            wasm::EntityType::Table(ty) => ty.into(),
814            wasm::EntityType::Memory(ty) => ty.into(),
815            wasm::EntityType::Global(ty) => ty.into(),
816            wasm::EntityType::Tag(ty) => CoreExtern::Tag(self.func_type(ty)),
817        }
818    }
819
820    fn func_type(&self, ty: wasm::CoreTypeId) -> CoreFuncType {
821        let func_ty = self.wasm_types[ty].unwrap_func();
822        CoreFuncType {
823            params: func_ty.params().iter().copied().map(Into::into).collect(),
824            results: func_ty.results().iter().copied().map(Into::into).collect(),
825        }
826    }
827
828    fn find_owner(&self, mut id: wasm::ComponentAnyTypeId) -> Option<&(Owner, String)> {
829        let mut prev = None;
830        while prev.is_none() {
831            prev = self.owners.get(&id);
832            id = match self.wasm_types.peel_alias(id) {
833                Some(next) => next,
834                None => break,
835            };
836        }
837        prev
838    }
839}