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#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
20pub struct PackageKey {
21 name: String,
23 version: Option<Version>,
25}
26
27impl PackageKey {
28 pub fn new(package: &Package) -> Self {
30 Self {
31 name: package.name.clone(),
32 version: package.version.clone(),
33 }
34 }
35
36 pub fn name(&self) -> &str {
38 &self.name
39 }
40
41 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#[derive(Copy, Clone, Hash, PartialEq, Eq)]
60pub struct BorrowedPackageKey<'a> {
61 pub name: &'a str,
63 pub version: Option<&'a Version>,
65}
66
67impl<'a> BorrowedPackageKey<'a> {
68 pub fn new(package: &'a Package) -> Self {
70 Self {
71 name: &package.name,
72 version: package.version.as_ref(),
73 }
74 }
75
76 pub fn from_name_and_version(name: &'a str, version: Option<&'a Version>) -> Self {
78 Self { name, version }
79 }
80
81 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
101pub trait BorrowedKey {
103 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#[derive(Clone)]
146#[cfg_attr(feature = "serde", derive(serde::Serialize))]
147#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
148pub struct Package {
149 name: String,
151 version: Option<Version>,
153 #[cfg_attr(feature = "serde", serde(skip))]
157 bytes: Vec<u8>,
158 ty: WorldId,
160 instance_type: InterfaceId,
162 definitions: IndexMap<String, ItemKind>,
164}
165
166impl Package {
167 pub fn key(&self) -> BorrowedPackageKey {
169 BorrowedPackageKey::new(self)
170 }
171
172 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 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 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 pub fn name(&self) -> &str {
296 &self.name
297 }
298
299 pub fn version(&self) -> Option<&Version> {
301 self.version.as_ref()
302 }
303
304 pub fn bytes(&self) -> &[u8] {
308 &self.bytes
309 }
310
311 pub fn ty(&self) -> WorldId {
313 self.ty
314 }
315
316 pub fn instance_type(&self) -> InterfaceId {
319 self.instance_type
320 }
321
322 pub fn definitions(&self) -> &IndexMap<String, ItemKind> {
324 &self.definitions
325 }
326
327 fn find_definitions(types: &Types, world: WorldId) -> IndexMap<String, ItemKind> {
328 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 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 Interface(InterfaceId),
378 World(WorldId),
380}
381
382#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
383enum Entity {
384 Type(Type),
386 Resource(ResourceId),
388}
389
390struct 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 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 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 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 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 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}