use crate::{
ComponentEncoder, StringEncoding, dummy_module, embed_component_metadata,
encoding::encode_world,
};
use anyhow::{Context, Result, bail};
use wasm_encoder::{ComponentBuilder, ComponentExportKind, ComponentTypeRef};
use wasmparser::Validator;
use wit_parser::{ManglingAndAbi, Resolve, WorldId};
pub fn semver_check(mut resolve: Resolve, prev: WorldId, new: WorldId) -> Result<()> {
for (_id, pkg) in resolve.packages.iter_mut() {
pkg.name.version = None;
}
let old_pkg_id = resolve.worlds[prev]
.package
.context("old world not in named package")?;
let old_pkg_name = &resolve.packages[old_pkg_id].name;
let new_pkg_id = resolve.worlds[new]
.package
.context("new world not in named package")?;
let new_pkg_name = &resolve.packages[new_pkg_id].name;
if old_pkg_name != new_pkg_name {
bail!(
"the old world is in package {old_pkg_name}, which is not the same as the new world, which is in package {new_pkg_name}",
)
}
let mut root_component = ComponentBuilder::default();
let mut prev_as_module = dummy_module(&resolve, prev, ManglingAndAbi::Standard32);
embed_component_metadata(&mut prev_as_module, &resolve, prev, StringEncoding::UTF8)
.context("failed to embed component metadata")?;
let prev_as_component = ComponentEncoder::default()
.module(&prev_as_module)
.context("failed to register previous world encoded as a module")?
.encode()
.context("failed to encode previous world as a component")?;
let component_to_test_idx = root_component.component_raw(None, &prev_as_component);
let test_component_idx = {
let component_ty =
encode_world(&resolve, new).context("failed to encode the new world as a type")?;
let mut component = ComponentBuilder::default();
let component_ty_idx = component.type_component(None, &component_ty);
component.import(
&resolve.worlds[new].name,
ComponentTypeRef::Component(component_ty_idx),
);
root_component.component(None, component)
};
root_component.instantiate(
None,
test_component_idx,
[(
resolve.worlds[new].name.clone(),
ComponentExportKind::Component,
component_to_test_idx,
)],
);
let bytes = root_component.finish();
Validator::new()
.validate_all(&bytes)
.context("new world is not semver-compatible with the previous world")?;
Ok(())
}