use miden_mast_package::{Dependency, debug_info::PackageDebugInfo};
use super::*;
pub struct AssemblyProduct {
package: Box<Package>,
kernel_package: Option<Arc<Package>>,
debug_info: Box<PackageDebugInfo>,
}
impl AssemblyProduct {
pub(super) fn new(
package: Box<Package>,
kernel: Option<Arc<Package>>,
debug_info: Box<PackageDebugInfo>,
) -> Self {
assert!(
kernel.is_none() || !package.is_kernel(),
"kernels cannot depend on another kernel"
);
Self {
package,
kernel_package: kernel,
debug_info,
}
}
#[cfg_attr(not(feature = "std"), expect(unused))]
pub fn extend_dependencies(
&mut self,
deps: impl IntoIterator<Item = Dependency>,
) -> Result<(), Report> {
for dep in deps {
self.package.manifest.add_dependency(dep).map_err(Report::msg)?;
}
Ok(())
}
pub fn into_artifact(self, emit_debug_info: bool) -> Result<Box<Package>, Report> {
let Self { mut package, kernel_package, debug_info } = self;
if package.is_program()
&& let Some(kernel_package) = kernel_package
{
package.sections.push(linked_kernel_package_section(kernel_package.as_ref()));
if let Some(kernel_dep) =
package.manifest.dependencies().find(|dep| dep.id() == &kernel_package.name)
{
if kernel_dep.digest != kernel_package.digest()
|| kernel_dep.kind != kernel_package.kind
|| kernel_dep.version() != &kernel_package.version
{
return Err(Report::msg(format!(
"unable to register kernel dependency: '{}' already exists as a dependency, but with different metadata than the actual kernel package",
kernel_package.name
)));
}
} else {
package
.manifest
.add_dependency(Dependency {
name: kernel_package.name.clone(),
kind: kernel_package.kind,
version: kernel_package.version.clone(),
digest: kernel_package.digest(),
})
.map_err(|err| {
Report::msg(format!("unable to register kernel dependency: {err}"))
})?;
}
}
if emit_debug_info {
package
.sections
.push(Section::new(SectionId::DEBUG_INFO, debug_info.to_bytes()));
}
Ok(package)
}
}
fn linked_kernel_package_section(package: &Package) -> Section {
Section::new(SectionId::KERNEL, package.to_bytes())
}