Skip to main content

aspero_json/
verify.rs

1//! Verdicts.
2
3use aspero_engine::{Reason, Verification};
4use serde_json::{Value, json};
5
6use crate::{merged, work};
7
8/// A claim that couldn't be read, after its echo.
9pub fn invalid_claim(echo: Value, reason: &str) -> Value {
10    merged(echo, json!({"verdict": "invalid", "reason": reason}))
11}
12
13/// One verification, after the claim's echo (input, key, claim).
14pub fn verification(echo: Value, v: &Verification, full: bool) -> Value {
15    let mut item = merged(
16        echo,
17        json!({
18            "verdict": v.verdict.as_str(),
19            "reason": v.reason,
20            "why": why(v, full),
21            "read": v.read,
22        }),
23    );
24    if let Some(best) = v.best {
25        item["match"] = work::candidate(&v.report.candidates[best], full);
26    }
27    let failures = v.report.failures();
28    if !failures.is_empty() {
29        let errors: Vec<String> = failures.iter().map(ToString::to_string).collect();
30        item["errors"] = json!(errors);
31        let kinds: Vec<&str> = failures.iter().map(|e| e.kind().as_str()).collect();
32        item["error_kinds"] = json!(kinds);
33    }
34    if full {
35        let all: Vec<Value> = v
36            .report
37            .candidates
38            .iter()
39            .map(|c| work::candidate(c, true))
40            .collect();
41        item["candidates"] = json!(all);
42    }
43    item
44}
45
46/// The reason as data: `{"code", "differs": [{"field", "actual", "cited"}],
47/// "cited": candidate}`, so a front end can word it itself.
48fn why(v: &Verification, full: bool) -> Value {
49    let mut out = json!({"code": v.why.as_str()});
50    let differs: Vec<Value> = v
51        .why
52        .differs()
53        .iter()
54        .map(|d| {
55            let mut out = json!({"field": d.field.as_str()});
56            if let Some(actual) = &d.actual {
57                out["actual"] = json!(actual);
58            }
59            if let Some(cited) = &d.cited {
60                out["cited"] = json!(cited);
61            }
62            out
63        })
64        .collect();
65    if !differs.is_empty() {
66        out["differs"] = json!(differs);
67    }
68    if let Reason::IdElsewhere { cited } = v.why {
69        out["cited"] = work::candidate(&v.report.candidates[cited], full);
70    }
71    out
72}