Skip to main content

lemma/api/
response.rs

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