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#[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 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#[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::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 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.name);
228 }
229 }
230 Payload::ComponentExportSection(s) => {
231 exports.reserve(s.count() as usize);
232 for export in s {
233 exports.push(export?.name.name);
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 pub fn name(&self) -> &str {
293 &self.name
294 }
295
296 pub fn version(&self) -> Option<&Version> {
298 self.version.as_ref()
299 }
300
301 pub fn bytes(&self) -> &[u8] {
305 &self.bytes
306 }
307
308 pub fn ty(&self) -> WorldId {
310 self.ty
311 }
312
313 pub fn instance_type(&self) -> InterfaceId {
316 self.instance_type
317 }
318
319 pub fn definitions(&self) -> &IndexMap<String, ItemKind> {
321 &self.definitions
322 }
323
324 fn find_definitions(types: &Types, world: WorldId) -> IndexMap<String, ItemKind> {
325 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 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 Interface(InterfaceId),
375 World(WorldId),
377}
378
379#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
380enum Entity {
381 Type(Type),
383 Resource(ResourceId),
385}
386
387struct 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 wasm_types = self.wasm_types.clone();
410 let import = wasm_types.component_item_for_import(name).unwrap();
411 self.entity(name, import)
412 }
413
414 fn export(&mut self, name: &str) -> Result<ItemKind> {
415 let wasm_types = self.wasm_types.clone();
416 let export = wasm_types.component_item_for_export(name).unwrap();
417 self.entity(name, export)
418 }
419
420 fn component_func_type(&mut self, id: wasm::ComponentFuncTypeId) -> Result<FuncTypeId> {
421 let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Func(id));
422 if let Some(ty) = self.cache.get(&key) {
423 match ty {
424 Entity::Type(Type::Func(id)) => return Ok(*id),
425 _ => panic!("invalid cached type"),
426 }
427 }
428
429 let wasm_types = self.wasm_types.clone();
430 let func_ty = &wasm_types[id];
431 let params = func_ty
432 .params
433 .iter()
434 .map(|(name, ty)| Ok((name.to_string(), self.component_val_type(*ty)?)))
435 .collect::<Result<_>>()?;
436
437 let result = match func_ty.result {
438 Some(ty) => Some(self.component_val_type(ty)?),
439 None => None,
440 };
441
442 let id = self.types.add_func_type(FuncType {
443 params,
444 result,
445 is_async: func_ty.async_,
446 });
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)| {
466 Ok(((module.clone(), name.clone()), self.entity_type(*ty)?))
467 })
468 .collect::<Result<_>>()?;
469
470 let exports = module_ty
471 .exports
472 .iter()
473 .map(|(name, ty)| Ok((name.clone(), self.entity_type(*ty)?)))
474 .collect::<Result<_>>()?;
475
476 let module_id = self.types.add_module_type(ModuleType { imports, exports });
477 self.cache
478 .insert(key, Entity::Type(Type::Module(module_id)));
479 Ok(module_id)
480 }
481
482 fn ty(&mut self, name: &str, id: wasm::ComponentAnyTypeId) -> Result<Type> {
483 match id {
484 wasm::ComponentAnyTypeId::Defined(id) => {
485 Ok(Type::Value(self.component_defined_type(id)?))
486 }
487 wasm::ComponentAnyTypeId::Func(id) => Ok(Type::Func(self.component_func_type(id)?)),
488 wasm::ComponentAnyTypeId::Component(id) => {
489 Ok(Type::World(self.component_type(None, id)?))
490 }
491 wasm::ComponentAnyTypeId::Instance(id) => {
492 Ok(Type::Interface(self.component_instance_type(None, id)?))
493 }
494 wasm::ComponentAnyTypeId::Resource(id) => Ok(Type::Resource(self.resource(name, id))),
495 }
496 }
497
498 fn component_val_type(&mut self, ty: wasm::ComponentValType) -> Result<ValueType> {
499 match ty {
500 wasm::ComponentValType::Primitive(ty) => Ok(ValueType::Primitive(ty.into())),
501 wasm::ComponentValType::Type(id) => Ok(self.component_defined_type(id)?),
502 }
503 }
504
505 fn component_instance_type(
506 &mut self,
507 name: Option<&str>,
508 id: wasm::ComponentInstanceTypeId,
509 ) -> Result<InterfaceId> {
510 let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Instance(id));
511 if let Some(ty) = self.cache.get(&key) {
512 match ty {
513 Entity::Type(Type::Interface(id)) => {
514 return Ok(*id);
515 }
516 _ => panic!("invalid cached type"),
517 }
518 }
519
520 let wasm_types = self.wasm_types.clone();
521 let instance_ty = &wasm_types[id];
522 let id = self.types.add_interface(Interface {
523 id: name.and_then(|n| n.contains(':').then(|| n.to_owned())),
524 uses: Default::default(),
525 exports: IndexMap::with_capacity(instance_ty.exports.len()),
526 });
527
528 for (name, item) in &instance_ty.exports {
529 let export = self.entity(name, item)?;
530
531 if let wasm::ComponentEntityType::Type {
532 referenced,
533 created,
534 } = &item.ty
535 {
536 self.use_or_own(Owner::Interface(id), name, *referenced, *created);
537
538 if let ItemKind::Type(Type::Resource(res)) = export {
540 if let Some(ResourceAlias { owner, .. }) = &mut self.types[res].alias {
541 if let Some(owner_id) = owner {
542 if *owner_id == id {
543 *owner = None;
544 }
545 }
546 }
547 }
548 }
549
550 let prev = self.types[id].exports.insert(name.clone(), export);
551 assert!(prev.is_none());
552 }
553
554 self.cache.insert(key, Entity::Type(Type::Interface(id)));
555 Ok(id)
556 }
557
558 fn entity(&mut self, name: &str, item: &wasm::ComponentItem) -> Result<ItemKind> {
559 match item.ty {
560 wasm::ComponentEntityType::Module(id) => Ok(ItemKind::Module(self.module_type(id)?)),
561 wasm::ComponentEntityType::Value(ty) => {
562 Ok(ItemKind::Value(self.component_val_type(ty)?))
563 }
564 wasm::ComponentEntityType::Type { created, .. } => {
565 Ok(ItemKind::Type(self.ty(name, created)?))
566 }
567 wasm::ComponentEntityType::Func(id) => {
568 Ok(ItemKind::Func(self.component_func_type(id)?))
569 }
570 wasm::ComponentEntityType::Instance(id) => {
571 let iface_name = item.implements.as_deref().unwrap_or(name);
577 Ok(ItemKind::Instance(
578 self.component_instance_type(Some(iface_name), id)?,
579 ))
580 }
581 wasm::ComponentEntityType::Component(id) => {
582 Ok(ItemKind::Component(self.component_type(Some(name), id)?))
583 }
584 }
585 }
586
587 fn use_or_own(
588 &mut self,
589 owner: Owner,
590 name: &str,
591 referenced: wasm::ComponentAnyTypeId,
592 created: wasm::ComponentAnyTypeId,
593 ) {
594 if let Some((other, orig)) = self.find_owner(referenced) {
595 match *other {
596 Owner::Interface(interface) if owner != *other => {
597 let used = UsedType {
598 interface,
599 name: if name != orig {
600 Some(orig.to_string())
601 } else {
602 None
603 },
604 };
605
606 let uses = match owner {
608 Owner::Interface(id) => &mut self.types[id].uses,
609 Owner::World(id) => &mut self.types[id].uses,
610 };
611
612 uses.insert(name.to_string(), used);
613 }
614 _ => {}
615 }
616 return;
617 }
618
619 let prev = self.owners.insert(created, (owner, name.to_string()));
621 assert!(prev.is_none());
622 }
623
624 fn component_type(&mut self, name: Option<&str>, id: wasm::ComponentTypeId) -> Result<WorldId> {
625 let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Component(id));
626 if let Some(ty) = self.cache.get(&key) {
627 match ty {
628 Entity::Type(Type::World(id)) => return Ok(*id),
629 _ => panic!("invalid cached type"),
630 }
631 }
632
633 let wasm_types = self.wasm_types.clone();
634 let component_ty = &wasm_types[id];
635 let id = self.types.add_world(World {
636 id: name.and_then(|n| n.contains(':').then(|| n.to_owned())),
637 uses: Default::default(),
638 imports: IndexMap::with_capacity(component_ty.imports.len()),
639 exports: IndexMap::with_capacity(component_ty.exports.len()),
640 });
641
642 for (name, item) in &component_ty.imports {
643 let import = self.entity(name, item)?;
644
645 if let wasm::ComponentEntityType::Type {
646 referenced,
647 created,
648 } = &item.ty
649 {
650 self.use_or_own(Owner::World(id), name, *referenced, *created);
651 }
652
653 let prev = self.types[id].imports.insert(name.clone(), import);
654 assert!(prev.is_none());
655 }
656
657 for (name, item) in &component_ty.exports {
658 let ty = self.entity(name, item)?;
659 let prev = self.types[id].exports.insert(name.clone(), ty);
660 assert!(prev.is_none());
661 }
662
663 self.cache.insert(key, Entity::Type(Type::World(id)));
664 Ok(id)
665 }
666
667 fn component_defined_type(&mut self, id: wasm::ComponentDefinedTypeId) -> Result<ValueType> {
668 let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Defined(id));
669 if let Some(ty) = self.cache.get(&key) {
670 match ty {
671 Entity::Type(Type::Value(ty)) => return Ok(*ty),
672 _ => panic!("invalid cached type"),
673 }
674 }
675
676 let wasm_types = self.wasm_types.clone();
677 let ty = match &wasm_types[id] {
678 wasm::ComponentDefinedType::Primitive(ty) => ValueType::Defined(
679 self.types
680 .add_defined_type(DefinedType::Alias(ValueType::Primitive((*ty).into()))),
681 ),
682 wasm::ComponentDefinedType::Record(ty) => {
683 let fields = ty
684 .fields
685 .iter()
686 .map(|(name, ty)| Ok((name.as_str().to_owned(), self.component_val_type(*ty)?)))
687 .collect::<Result<_>>()?;
688
689 ValueType::Defined(
690 self.types
691 .add_defined_type(DefinedType::Record(Record { fields })),
692 )
693 }
694 wasm::ComponentDefinedType::Variant(ty) => {
695 let cases = ty
696 .cases
697 .iter()
698 .map(|(name, case)| {
699 Ok((
700 name.as_str().to_owned(),
701 case.ty.map(|ty| self.component_val_type(ty)).transpose()?,
702 ))
703 })
704 .collect::<Result<_>>()?;
705
706 ValueType::Defined(
707 self.types
708 .add_defined_type(DefinedType::Variant(Variant { cases })),
709 )
710 }
711 wasm::ComponentDefinedType::List { element, .. } => {
712 let ty = self.component_val_type(*element)?;
713 ValueType::Defined(self.types.add_defined_type(DefinedType::List(ty)))
714 }
715 wasm::ComponentDefinedType::Tuple(ty) => {
716 let types = ty
717 .types
718 .iter()
719 .map(|ty| self.component_val_type(*ty))
720 .collect::<Result<_>>()?;
721 ValueType::Defined(self.types.add_defined_type(DefinedType::Tuple(types)))
722 }
723 wasm::ComponentDefinedType::Flags(flags) => {
724 let flags = flags.iter().map(|flag| flag.as_str().to_owned()).collect();
725 ValueType::Defined(
726 self.types
727 .add_defined_type(DefinedType::Flags(Flags(flags))),
728 )
729 }
730 wasm::ComponentDefinedType::Enum(cases) => {
731 let cases = cases.iter().map(|case| case.as_str().to_owned()).collect();
732 ValueType::Defined(self.types.add_defined_type(DefinedType::Enum(Enum(cases))))
733 }
734 wasm::ComponentDefinedType::Option { ty, .. } => {
735 let ty = self.component_val_type(*ty)?;
736 ValueType::Defined(self.types.add_defined_type(DefinedType::Option(ty)))
737 }
738 wasm::ComponentDefinedType::Result { ok, err, .. } => {
739 let ok = ok.map(|ty| self.component_val_type(ty)).transpose()?;
740 let err = err.map(|ty| self.component_val_type(ty)).transpose()?;
741 ValueType::Defined(self.types.add_defined_type(DefinedType::Result { ok, err }))
742 }
743 wasm::ComponentDefinedType::Borrow(id) => ValueType::Borrow(
744 match self.cache.get(&wasm::AnyTypeId::Component(
745 wasm::ComponentAnyTypeId::Resource(*id),
746 )) {
747 Some(Entity::Resource(id)) => *id,
748 _ => panic!("expected a resource"),
749 },
750 ),
751 wasm::ComponentDefinedType::Own(id) => ValueType::Own(
752 match self.cache.get(&wasm::AnyTypeId::Component(
753 wasm::ComponentAnyTypeId::Resource(*id),
754 )) {
755 Some(Entity::Resource(id)) => *id,
756 _ => panic!("expected a resource"),
757 },
758 ),
759 wasm::ComponentDefinedType::Stream { ty, .. } => {
760 let stream = ty.map(|ty| self.component_val_type(ty)).transpose()?;
761 ValueType::Defined(self.types.add_defined_type(DefinedType::Stream(stream)))
762 }
763 wasm::ComponentDefinedType::Future { ty, .. } => {
764 let option = ty.map(|ty| self.component_val_type(ty)).transpose()?;
765 ValueType::Defined(self.types.add_defined_type(DefinedType::Future(option)))
766 }
767 wasm::ComponentDefinedType::FixedLengthList {
768 element, length, ..
769 } => {
770 let ty = self.component_val_type(*element)?;
771 ValueType::Defined(
772 self.types
773 .add_defined_type(DefinedType::FixedSizeList(ty, *length)),
774 )
775 }
776 wasm::ComponentDefinedType::Map { .. } => {
777 bail!("ComponentDefinedType::Map is not yet supported");
778 }
779 };
780
781 self.cache.insert(key, Entity::Type(Type::Value(ty)));
782 Ok(ty)
783 }
784
785 fn resource(&mut self, name: &str, id: wasm::AliasableResourceId) -> ResourceId {
786 let key = wasm::AnyTypeId::Component(wasm::ComponentAnyTypeId::Resource(id));
787 if let Some(ty) = self.cache.get(&key) {
788 match ty {
789 Entity::Resource(id) => return *id,
790 _ => panic!("invalid cached type"),
791 }
792 }
793
794 if let Some(resource_id) = self.resource_map.get(&id.resource()) {
796 let alias_id = self.types.add_resource(Resource {
797 name: name.to_owned(),
798 alias: Some(ResourceAlias {
799 owner: match self.find_owner(wasm::ComponentAnyTypeId::Resource(id)) {
800 Some((Owner::Interface(id), _)) => Some(*id),
801 _ => None,
802 },
803 source: *resource_id,
804 }),
805 });
806 self.cache.insert(key, Entity::Resource(alias_id));
807 return alias_id;
808 }
809
810 let resource_id = self.types.add_resource(Resource {
812 name: name.to_owned(),
813 alias: None,
814 });
815
816 self.resource_map.insert(id.resource(), resource_id);
817 self.cache.insert(key, Entity::Resource(resource_id));
818 resource_id
819 }
820
821 fn entity_type(&self, ty: wasmparser::types::EntityType) -> Result<CoreExtern> {
822 Ok(match ty {
823 wasmparser::types::EntityType::Func(ty) => CoreExtern::Func(self.func_type(ty)?),
824 wasmparser::types::EntityType::Table(ty) => ty.try_into()?,
825 wasmparser::types::EntityType::Memory(ty) => ty.into(),
826 wasmparser::types::EntityType::Global(ty) => ty.try_into()?,
827 wasmparser::types::EntityType::Tag(ty) => CoreExtern::Tag(self.func_type(ty)?),
828 wasmparser::types::EntityType::FuncExact(_) => {
829 todo!("wasmparser::types::EntityType::FuncExact")
830 }
831 })
832 }
833
834 fn func_type(&self, ty: wasmparser::types::CoreTypeId) -> Result<CoreFuncType> {
835 let func_ty = self.wasm_types[ty].unwrap_func();
836 Ok(CoreFuncType {
837 params: func_ty
838 .params()
839 .iter()
840 .copied()
841 .map(TryInto::try_into)
842 .collect::<Result<_>>()?,
843 results: func_ty
844 .results()
845 .iter()
846 .copied()
847 .map(TryInto::try_into)
848 .collect::<Result<_>>()?,
849 })
850 }
851
852 fn find_owner(&self, mut id: wasm::ComponentAnyTypeId) -> Option<&(Owner, String)> {
853 let mut prev = None;
854 while prev.is_none() {
855 prev = self.owners.get(&id);
856 id = match self.wasm_types.peel_alias(id) {
857 Some(next) => next,
858 None => break,
859 };
860 }
861 prev
862 }
863}