use crate::catalog::{ArtifactKind, BUNDLE_HEADER_LEN, BUNDLE_MAGIC};
use crate::pipeline::Checked;
use serde::Serialize;
#[derive(Serialize)]
struct Manifest {
manifest_version: u32,
signature: String,
nodes: Vec<Node>,
}
#[derive(Serialize)]
struct Node {
name: String,
kind: ArtifactKind,
resolved: Option<String>,
signature: String,
offset: u64,
len: u64,
}
pub fn build(checked: &Checked) -> Vec<u8> {
let mut offset = 0u64;
let nodes: Vec<Node> = checked
.stages()
.iter()
.map(|s| {
let len = s.module_bytes.len() as u64;
let node = Node {
name: s.name.clone(),
kind: s.kind,
resolved: s.resolved.clone(),
signature: s.signature.to_string(),
offset,
len,
};
offset += len;
node
})
.collect();
let manifest = Manifest {
manifest_version: 1,
signature: format!("{} -> {}", checked.input(), checked.output()),
nodes,
};
let manifest_bytes = serde_json::to_vec(&manifest)
.expect("Manifest always serializes: no non-finite floats, no non-string map keys");
let mut out = Vec::with_capacity(BUNDLE_HEADER_LEN + manifest_bytes.len() + offset as usize);
out.extend_from_slice(BUNDLE_MAGIC);
out.extend_from_slice(&(manifest_bytes.len() as u64).to_le_bytes());
out.extend_from_slice(&manifest_bytes);
for stage in checked.stages() {
out.extend_from_slice(&stage.module_bytes);
}
out
}