1use rustev_contract::Document;
7use rustev_contract::ids::PlanId;
8use rustev_contract::judgment::Judgment;
9use rustev_contract::replay::CaptureStatus;
10use rustev_contract::run::{RunRecord, Termination};
11use serde_json::json;
12
13use crate::out::{Done, Out, code};
14
15pub fn base(command: &str, decision_id: &str, plan_id: &PlanId) -> Out {
17 Out::new(command, "")
18 .set("decision_id", decision_id)
19 .set("plan_id", plan_id)
20}
21
22pub fn rejected(base: Out, kind: &str, detail: &str) -> Done {
24 Done::new(
25 code::REJECTED,
26 base.set("status", "rejected")
27 .set("rejection", kind)
28 .set("detail", detail),
29 )
30}
31
32pub fn delivered(base: Out, record: &str, receipt: &str) -> Out {
34 base.set("record", record).set("receipt", receipt)
35}
36
37pub fn judged(out: Out, j: &Judgment) -> (Out, u8) {
39 (
40 addressing(
41 out.set("status", "judged")
42 .set("completion", "judged")
43 .raw("judgment", judgment_bytes(j)),
44 j,
45 ),
46 code::OK,
47 )
48}
49
50pub fn cancelled(out: Out) -> (Out, u8) {
52 (
53 out.set("status", "cancelled")
54 .set("completion", "cancelled"),
55 code::CANCELLED,
56 )
57}
58
59pub fn not_delivered(base: Out, record: &RunRecord, detail: &str, uncertain: bool) -> (Out, u8) {
62 let completion = match record.termination {
63 Termination::Judged => "judged",
64 Termination::Cancelled => "cancelled",
65 };
66 (
67 base.set("status", "evidence_not_delivered")
68 .set("completion", completion)
69 .set("detail", detail)
70 .set("uncertain", &uncertain)
71 .raw("run_record", record_bytes(record)),
72 code::EVIDENCE_NOT_DELIVERED,
73 )
74}
75
76fn addressing(out: Out, j: &Judgment) -> Out {
83 use rustev_contract::judgment::Outcome;
84 if j.schema != rustev_contract::schema::JUDGMENT_V2 {
85 return out;
86 }
87 let (to, transient) = match &j.outcome {
88 Outcome::UnresolvedAction { action, .. } => {
89 (json!(action.addressed_to), json!(action.transient))
90 }
91 Outcome::NeedsInput(n) => (json!(n.action.addressed_to), json!(n.action.transient)),
92 Outcome::Refused { addressed_to, .. } => (json!(addressed_to), json!(false)),
93 _ => (json!(null), json!(null)),
94 };
95 out.set("addressed_to", &to).set("transient", &transient)
96}
97
98pub fn judgment_bytes(j: &Judgment) -> Vec<u8> {
100 j.record_canonical()
103 .expect("a judgment has a record canonical form")
104}
105
106pub fn record_bytes(r: &RunRecord) -> Vec<u8> {
108 r.record_canonical()
109 .expect("a run record has a record canonical form")
110}
111
112pub fn capture_status(s: CaptureStatus) -> &'static str {
114 match s {
115 CaptureStatus::Complete => "complete",
116 CaptureStatus::Disabled => "disabled",
117 CaptureStatus::LimitExceeded => "limit_exceeded",
118 CaptureStatus::Cancelled => "cancelled",
119 CaptureStatus::Abandoned => "abandoned",
120 }
121}