use super::{Certificate, OpOutcome, OpResult};
#[inline]
pub fn to_json(cert: &Certificate) -> Result<String, String> {
serde_json::to_string_pretty(cert)
.map_err(|err| format!("certificate serialization failed: {err}. Fix: report this vyre-conform bug with the certificate shape."))
}
#[must_use]
#[inline]
pub fn to_human(cert: &Certificate) -> String {
let mut lines = Vec::new();
lines.push("vyre conformance certificate".to_string());
lines.push(cert.proof_status.clone());
lines.push(format!(
"backend: {} {}",
cert.backend_name, cert.backend_version
));
lines.push(format!("spec version: {}", cert.spec_version));
lines.push(format!(
"certificate_hash: {}",
hex::encode(cert.certificate_hash)
));
lines.push(format!(
"verification: {:?}, {} u32 witnesses per law",
cert.strength, cert.witness_count
));
lines.push(format!(
"levels: integer={:?}, float={:?}, approximate={:?}",
cert.level.integer, cert.level.float, cert.level.approximate
));
lines.push(format!(
"coverage: {}/{} supported parity ops, {} unsupported ops, {}/{} laws, {} cases",
cert.coverage.ops_parity_passed,
cert.coverage
.ops_total
.saturating_sub(cert.coverage.ops_unsupported),
cert.coverage.ops_unsupported,
cert.coverage.laws_passed,
cert.coverage.laws_total,
cert.coverage.cases_tested
));
lines.push(String::new());
lines.push("integer operations:".to_string());
push_ops(&mut lines, &cert.integer_track.ops);
if let Some(track) = &cert.float_track {
lines.push(String::new());
lines.push("float operations:".to_string());
push_ops(&mut lines, &track.ops);
}
if let Some(track) = &cert.approximate_track {
lines.push(String::new());
lines.push("approximate operations:".to_string());
push_ops(&mut lines, &track.ops);
}
if cert.engines.is_empty() {
lines.push(String::new());
lines.push("engines: not evaluated by op-only certificate run".to_string());
}
lines.join("\n")
}
fn push_ops(lines: &mut Vec<String>, ops: &[OpResult]) {
if ops.is_empty() {
lines.push("- none".to_string());
return;
}
for op in ops {
let parity = match op.outcome {
OpOutcome::Passed => "pass",
OpOutcome::Failed => "fail",
OpOutcome::Pending => "pending",
OpOutcome::Unsupported => "unsupported",
};
let law_denom = op.laws_verified.len() + op.laws_failed.len();
lines.push(format!(
"- {}: parity={}, laws={}/{}, cases={}, witnesses={}",
op.id,
parity,
op.laws_verified.len(),
law_denom,
op.cases_tested,
op.witness_count
));
for violation in &op.laws_failed {
lines.push(format!(" law failure: {violation}"));
}
for failure in &op.parity_failures {
lines.push(format!(" parity failure: {failure}"));
}
}
}