1use crate::api::value::RuleResultValue;
4use crate::evaluation::explanations::Explanation;
5use crate::evaluation::response::{Response as DomainResponse, RuleResult as DomainRuleResult};
6use crate::parsing::ast::DateTimeValue;
7use indexmap::IndexMap;
8use serde::Serialize;
9
10#[derive(Debug, Clone, Serialize)]
11pub struct Response {
12 #[serde(rename = "spec")]
13 pub spec_name: String,
14 pub effective: String,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub spec_effective_from: Option<DateTimeValue>,
17 #[serde(skip_serializing_if = "Option::is_none")]
18 pub spec_effective_to: Option<DateTimeValue>,
19 pub results: IndexMap<String, RuleResult>,
20}
21
22impl From<&DomainResponse> for Response {
23 fn from(response: &DomainResponse) -> Self {
24 Self {
25 spec_name: response.spec_name.clone(),
26 effective: response.effective.clone(),
27 spec_effective_from: response.spec_effective_from.clone(),
28 spec_effective_to: response.spec_effective_to.clone(),
29 results: response
30 .results
31 .iter()
32 .map(|(name, result)| (name.clone(), RuleResult::from(result)))
33 .collect(),
34 }
35 }
36}
37
38#[derive(Debug, Clone, Serialize)]
40pub struct RuleResult {
41 pub vetoed: bool,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub veto_reason: Option<String>,
44 pub rule_type: String,
45 #[serde(flatten)]
46 pub value: Option<RuleResultValue>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub explanation: Option<Explanation>,
49 #[serde(skip_serializing_if = "Vec::is_empty")]
50 pub missing_data: Vec<String>,
51}
52
53impl From<&DomainRuleResult> for RuleResult {
54 fn from(result: &DomainRuleResult) -> Self {
55 Self {
56 vetoed: result.vetoed,
57 veto_reason: result.veto_reason.clone(),
58 rule_type: result.rule_type.clone(),
59 value: result.value.as_ref().map(RuleResultValue::from),
60 explanation: result.explanation.clone(),
61 missing_data: result.missing_data().to_vec(),
62 }
63 }
64}