diff --git a/crates/wit-component/src/encoding/wit/v2.rs b/crates/wit-component/src/encoding/wit/v2.rs index 7476dfd094..2723f00511 100644 --- a/crates/wit-component/src/encoding/wit/v2.rs +++ b/crates/wit-component/src/encoding/wit/v2.rs @@ -53,73 +53,15 @@ impl Encoder<'_> { // roundtripping. let mut names = NameMap::new(); for pkg in self.packages { - let package = &self.resolve.packages[*pkg]; if self.packages.len() > 1 { - let mut sub_encoder = Encoder { + let sub_encoder = Encoder { component: ComponentBuilder::default(), resolve: self.resolve, packages: self.packages, }; - let package_metadata = PackageMetadata::extract(self.resolve, *pkg); - sub_encoder.component.custom_section(&CustomSection { - name: PackageMetadata::SECTION_NAME.into(), - data: package_metadata.encode()?.into(), - }); - for (name, &id) in self.resolve.packages[*pkg].interfaces.iter() { - let component_ty = sub_encoder.encode_interface(id, pkg)?; - let ty = sub_encoder.component.type_component(&component_ty); - sub_encoder.component.export( - name.as_ref(), - ComponentExportKind::Type, - ty, - None, - ); - } - for (name, &world) in self.resolve.packages[*pkg].worlds.iter() { - // Encode the `world` directly as a component, then create a wrapper - // component that exports that component. - let component_ty = super::encode_world(self.resolve, world)?; - - let world = &sub_encoder.resolve.worlds[world]; - let mut wrapper = ComponentType::new(); - wrapper.ty().component(&component_ty); - let pkg = &sub_encoder.resolve.packages[world.package.unwrap()]; - wrapper.export(&pkg.name.interface_id(name), ComponentTypeRef::Component(0)); - let ty = sub_encoder.component.type_component(&wrapper); - sub_encoder.component.export( - name.as_ref(), - ComponentExportKind::Type, - ty, - None, - ); - } - let sub = self.component.component(sub_encoder.component); - names.append(sub, &package.name.to_string()); + self.encode_package(&mut names, pkg, Some(sub_encoder))?; } else { - for (name, &id) in self.resolve.packages[*pkg].interfaces.iter() { - let component_ty = self.encode_interface(id, pkg)?; - let ty = self.component.type_component(&component_ty); - self.component - .export(name.as_ref(), ComponentExportKind::Type, ty, None); - } - for (name, &world) in self.resolve.packages[*pkg].worlds.iter() { - // Encode the `world` directly as a component, then create a wrapper - // component that exports that component. - let component_ty = super::encode_world(self.resolve, world)?; - let world = &self.resolve.worlds[world]; - let mut wrapper = ComponentType::new(); - wrapper.ty().component(&component_ty); - let pkg = &self.resolve.packages[world.package.unwrap()]; - wrapper.export(&pkg.name.interface_id(name), ComponentTypeRef::Component(0)); - let ty = self.component.type_component(&wrapper); - self.component - .export(name.as_ref(), ComponentExportKind::Type, ty, None); - } - let package_metadata = PackageMetadata::extract(self.resolve, *pkg); - self.component.custom_section(&CustomSection { - name: PackageMetadata::SECTION_NAME.into(), - data: package_metadata.encode()?.into(), - }); + self.encode_package(&mut names, pkg, None)?; } } let mut final_names = ComponentNameSection::new(); @@ -129,6 +71,76 @@ impl Encoder<'_> { Ok(()) } + fn encode_package( + &mut self, + names: &mut NameMap, + pkg: &PackageId, + mut sub_encoder: Option, + ) -> Result<()> { + let package = &self.resolve.packages[*pkg]; + if let Some(ref mut sub) = sub_encoder { + let package_metadata = PackageMetadata::extract(self.resolve, *pkg); + sub.component.custom_section(&CustomSection { + name: PackageMetadata::SECTION_NAME.into(), + data: package_metadata.encode()?.into(), + }); + } + + for (name, &id) in self.resolve.packages[*pkg].interfaces.iter() { + if let Some(ref mut sub) = sub_encoder { + let component_ty = sub.encode_interface(id, pkg)?; + let ty = sub.component.type_component(&component_ty); + sub.component + .export(name.as_ref(), ComponentExportKind::Type, ty, None); + } else { + let component_ty = self.encode_interface(id, pkg)?; + let ty = self.component.type_component(&component_ty); + self.component + .export(name.as_ref(), ComponentExportKind::Type, ty, None); + } + } + for (name, &world) in self.resolve.packages[*pkg].worlds.iter() { + if let Some(ref mut sub) = sub_encoder { + // Encode the `world` directly as a component, then create a wrapper + // component that exports that component. + let component_ty = super::encode_world(self.resolve, world)?; + + let world = &sub.resolve.worlds[world]; + let mut wrapper = ComponentType::new(); + wrapper.ty().component(&component_ty); + let pkg = &sub.resolve.packages[world.package.unwrap()]; + wrapper.export(&pkg.name.interface_id(name), ComponentTypeRef::Component(0)); + let ty = sub.component.type_component(&wrapper); + sub.component + .export(name.as_ref(), ComponentExportKind::Type, ty, None); + } else { + // Encode the `world` directly as a component, then create a wrapper + // component that exports that component. + let component_ty = super::encode_world(self.resolve, world)?; + let world = &self.resolve.worlds[world]; + let mut wrapper = ComponentType::new(); + wrapper.ty().component(&component_ty); + let pkg = &self.resolve.packages[world.package.unwrap()]; + wrapper.export(&pkg.name.interface_id(name), ComponentTypeRef::Component(0)); + let ty = self.component.type_component(&wrapper); + self.component + .export(name.as_ref(), ComponentExportKind::Type, ty, None); + } + } + if sub_encoder.is_none() { + let package_metadata = PackageMetadata::extract(self.resolve, *pkg); + self.component.custom_section(&CustomSection { + name: PackageMetadata::SECTION_NAME.into(), + data: package_metadata.encode()?.into(), + }); + } + if let Some(sub_encoder) = sub_encoder { + let sub = self.component.component(sub_encoder.component); + names.append(sub, &package.name.to_string()); + } + Ok(()) + } + fn encode_interface(&mut self, id: InterfaceId, pkg: &PackageId) -> Result { // Build a set of interfaces reachable from this document, including the // interfaces in the document itself. This is used to import instances