lemma/planning/
explanation.rs1use crate::planning::semantics::{DataPath, RulePath};
16use serde::{Serialize, Serializer};
17
18pub(crate) fn serialize_rule_path_as_name<S>(
19 path: &RulePath,
20 serializer: S,
21) -> Result<S::Ok, S::Error>
22where
23 S: Serializer,
24{
25 serializer.serialize_str(&path.rule)
26}
27
28pub(crate) fn serialize_data_path_as_name<S>(
29 path: &DataPath,
30 serializer: S,
31) -> Result<S::Ok, S::Error>
32where
33 S: Serializer,
34{
35 serializer.serialize_str(&path.input_key())
36}
37
38#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
39#[serde(tag = "type", rename_all = "snake_case")]
40pub enum ExplanationNode {
41 Rule {
42 #[serde(serialize_with = "serialize_rule_path_as_name")]
43 name: RulePath,
44 #[serde(serialize_with = "serialize_option_string")]
45 result: Option<String>,
46 body: String,
47 #[serde(skip_serializing_if = "Vec::is_empty")]
48 causes: Vec<Cause>,
49 #[serde(skip_serializing_if = "Vec::is_empty")]
50 children: Vec<ExplanationNode>,
51 },
52 Compose {
53 expression: String,
54 operands: Vec<ExplanationNode>,
55 },
56 Data {
58 #[serde(serialize_with = "serialize_data_path_as_name")]
59 name: DataPath,
60 display: String,
61 },
62 DataUnused {
65 #[serde(serialize_with = "serialize_data_path_as_name")]
66 name: DataPath,
67 },
68 Conversion {
69 expression: String,
70 steps: Vec<SerializedConversionTraceStep>,
71 operands: Vec<ExplanationNode>,
72 },
73 Veto {
74 #[serde(skip_serializing_if = "Option::is_none")]
75 message: Option<String>,
76 },
77 UnitEquivalence {
78 text: String,
79 },
80 Piecewise {
82 #[serde(serialize_with = "forbid_piecewise_serialize")]
83 arms: Vec<PiecewiseArm>,
84 },
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
88pub struct PiecewiseArm {
89 pub condition: ExplanationNode,
90 pub result: ExplanationNode,
91 pub static_condition: Option<bool>,
94 pub static_cause_value: Option<bool>,
97}
98
99fn forbid_piecewise_serialize<S: Serializer>(
100 _: &Vec<PiecewiseArm>,
101 _: S,
102) -> Result<S::Ok, S::Error> {
103 panic!("BUG: Piecewise must be lowered before serialize")
104}
105
106fn serialize_option_string<S>(value: &Option<String>, serializer: S) -> Result<S::Ok, S::Error>
107where
108 S: Serializer,
109{
110 match value {
111 Some(s) => serializer.serialize_str(s),
112 None => serializer.serialize_none(),
113 }
114}
115
116#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
117pub struct Cause {
118 pub condition: String,
119 #[serde(serialize_with = "serialize_option_string")]
120 pub value: Option<String>,
121 #[serde(skip_serializing_if = "Vec::is_empty")]
122 pub children: Vec<ExplanationNode>,
123}
124
125#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
126#[serde(rename_all = "snake_case")]
127pub enum ConversionTraceRole {
128 Outcome,
129 Rule,
130 Source,
131}
132
133#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
134pub struct SerializedConversionTraceStep {
135 pub(crate) role: ConversionTraceRole,
136 pub(crate) text: String,
137}