use crate::tick::{Check, Tick};
use serde_json::{json, Map, Value};
use sha2::{Digest, Sha256};
fn sorted_set(v: &[String]) -> Vec<String> {
let mut s: Vec<String> = v.to_vec();
s.sort(); s.dedup();
s
}
fn check_value(c: &Check) -> Value {
match c {
Check::Person { reference } => json!({ "by": "person", "ref": reference }),
Check::Test {
reference,
verified_at_sha,
counter_test,
liveness,
} => json!({
"by": "test",
"ref": reference,
"verified_at_sha": verified_at_sha,
"counter_test": counter_test,
"liveness": {
"platforms": sorted_set(&liveness.platforms),
"triggered_by": sorted_set(&liveness.triggered_by),
"surfaces": sorted_set(&liveness.surfaces),
}
}),
}
}
pub fn hashed_value(t: &Tick) -> Value {
let grounds: Vec<Value> = t
.grounds
.iter()
.map(|g| {
let mut o = Map::new();
o.insert("claim".into(), Value::String(g.claim.clone()));
o.insert("supports".into(), Value::String(g.supports.clone()));
if let Some(c) = &g.check {
o.insert("check".into(), check_value(c));
}
Value::Object(o)
})
.collect();
json!({
"decision": t.decision,
"observe": t.observe,
"grounds": grounds,
"parent_id": t.parent_id,
})
}
pub fn canonical_json(v: &Value) -> String {
serde_json::to_string(v).expect("Value is serializable")
}
pub fn compute_id(t: &Tick) -> String {
let canon = canonical_json(&hashed_value(t));
let full = hex::encode(Sha256::digest(canon.as_bytes()));
full[..12].to_string()
}