1use crate::api::value::RuleResultValue;
4use crate::evaluation::evaluate_data::EvaluateDataValue;
5use crate::evaluation::explanations::Explanation;
6use crate::evaluation::response::{Response as DomainResponse, RuleResult as DomainRuleResult};
7use crate::parsing::ast::DateTimeValue;
8use crate::result_value::RowResult;
9use indexmap::IndexMap;
10use serde::Serialize;
11
12fn evaluate_data_json(value: &EvaluateDataValue) -> serde_json::Value {
13 enum Step<'a> {
14 Descend(&'a EvaluateDataValue),
15 NextChild,
16 Deliver(serde_json::Value),
17 }
18 enum Frame<'a> {
19 List {
20 out: Vec<serde_json::Value>,
21 children: std::slice::Iter<'a, EvaluateDataValue>,
22 },
23 Map {
24 out: serde_json::Map<String, serde_json::Value>,
25 pending_key: Option<String>,
26 children: indexmap::map::Iter<'a, String, EvaluateDataValue>,
27 },
28 }
29
30 let mut frames: Vec<Frame<'_>> = Vec::new();
31 let mut step = Step::Descend(value);
32 loop {
33 step = match step {
34 Step::Descend(node) => match node {
35 EvaluateDataValue::Literal(text) => {
36 Step::Deliver(serde_json::Value::String(text.clone()))
37 }
38 EvaluateDataValue::Boolean(bit) => Step::Deliver(serde_json::Value::Bool(*bit)),
39 EvaluateDataValue::List(items) => {
40 frames.push(Frame::List {
41 out: Vec::with_capacity(items.len()),
42 children: items.iter(),
43 });
44 Step::NextChild
45 }
46 EvaluateDataValue::Map(entries) => {
47 frames.push(Frame::Map {
48 out: serde_json::Map::with_capacity(entries.len()),
49 pending_key: None,
50 children: entries.iter(),
51 });
52 Step::NextChild
53 }
54 },
55 Step::NextChild => {
56 let child = match frames.last_mut() {
57 Some(Frame::List { children, .. }) => children.next(),
58 Some(Frame::Map {
59 pending_key,
60 children,
61 ..
62 }) => children.next().map(|(key, child)| {
63 *pending_key = Some(key.clone());
64 child
65 }),
66 None => {
67 panic!("BUG: evaluate data json frame stack empty while reading a child")
68 }
69 };
70 match child {
71 Some(child) => Step::Descend(child),
72 None => {
73 let finished = frames
74 .pop()
75 .expect("BUG: evaluate data json frame stack empty on completion");
76 let done = match finished {
77 Frame::List { out, .. } => serde_json::Value::Array(out),
78 Frame::Map { out, .. } => serde_json::Value::Object(out),
79 };
80 Step::Deliver(done)
81 }
82 }
83 }
84 Step::Deliver(done) => match frames.last_mut() {
85 None => return done,
86 Some(Frame::List { out, .. }) => {
87 out.push(done);
88 Step::NextChild
89 }
90 Some(Frame::Map {
91 out, pending_key, ..
92 }) => {
93 let key = pending_key
94 .take()
95 .expect("BUG: nested evaluate data json value has no field name");
96 out.insert(key, done);
97 Step::NextChild
98 }
99 },
100 };
101 }
102}
103
104#[derive(Debug, Clone, Serialize)]
105pub struct Response {
106 #[serde(rename = "spec")]
107 pub spec_name: String,
108 pub effective: String,
109 #[serde(skip_serializing_if = "Option::is_none")]
110 pub spec_effective_from: Option<DateTimeValue>,
111 #[serde(skip_serializing_if = "Option::is_none")]
112 pub spec_effective_to: Option<DateTimeValue>,
113 pub results: IndexMap<String, RuleResult>,
114 #[serde(skip_serializing_if = "Vec::is_empty")]
115 pub rows: Vec<RowResult>,
116}
117
118impl From<&DomainResponse> for Response {
119 fn from(response: &DomainResponse) -> Self {
120 Self {
121 spec_name: response.spec_name.clone(),
122 effective: response.effective.clone(),
123 spec_effective_from: response.spec_effective_from.clone(),
124 spec_effective_to: response.spec_effective_to.clone(),
125 results: response
126 .results
127 .iter()
128 .map(|(name, result)| (name.clone(), RuleResult::from(result)))
129 .collect(),
130 rows: response.rows.clone(),
131 }
132 }
133}
134
135#[derive(Debug, Clone, Serialize)]
137pub struct RuleResult {
138 pub vetoed: bool,
139 #[serde(skip_serializing_if = "Option::is_none")]
140 pub veto_reason: Option<String>,
141 pub rule_type: String,
142 #[serde(flatten)]
143 pub result: Option<RuleResultValue>,
144 #[serde(skip_serializing_if = "Option::is_none")]
145 pub explanation: Option<Explanation>,
146 #[serde(skip_serializing_if = "Vec::is_empty")]
147 pub missing_data: Vec<String>,
148 #[serde(skip_serializing_if = "IndexMap::is_empty")]
150 pub missing_data_options: IndexMap<String, Vec<serde_json::Value>>,
151}
152
153impl From<&DomainRuleResult> for RuleResult {
154 fn from(result: &DomainRuleResult) -> Self {
155 Self {
156 vetoed: result.vetoed,
157 veto_reason: result.veto_reason.clone(),
158 rule_type: result.rule_type.clone(),
159 result: result.result.as_ref().map(RuleResultValue::from),
160 explanation: result.explanation.clone(),
161 missing_data: result.missing_data().to_vec(),
162 missing_data_options: result
163 .missing_data_options()
164 .iter()
165 .map(|(key, options)| {
166 (
167 key.clone(),
168 options.iter().map(evaluate_data_json).collect(),
169 )
170 })
171 .collect(),
172 }
173 }
174}