Skip to main content

lemma/api/
show.rs

1//! Show / ShowData / ShowRule / ShowExpression JSON shapes.
2
3use crate::api::types::LemmaType;
4use crate::api::value::RuleResultValue;
5use crate::literals::Value;
6use crate::parsing::ast::{
7    ArithmeticComputation, CalendarPeriodUnit, ComparisonComputation, DateCalendarKind,
8    DateRelativeKind, DateTimeValue, MathematicalComputation, PrimitiveKind,
9};
10use crate::parsing::source::SourceType;
11use crate::planning::execution_plan::{
12    Show as DomainShow, ShowBranch as DomainShowBranch,
13    ShowConversionTarget as DomainConversionTarget, ShowData as DomainShowData,
14    ShowExpression as DomainShowExpression, ShowRule as DomainShowRule,
15    ShowVersion as DomainShowVersion,
16};
17use indexmap::IndexMap;
18use serde::{Deserialize, Serialize};
19
20#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
21pub struct ShowData {
22    #[serde(rename = "type")]
23    pub lemma_type: LemmaType,
24    #[serde(skip_serializing_if = "Option::is_none", default)]
25    pub fill: Option<RuleResultValue>,
26    #[serde(skip_serializing_if = "Option::is_none", default)]
27    pub suggestion: Option<RuleResultValue>,
28    pub needed_by_rules: Vec<String>,
29}
30
31impl From<&DomainShowData> for ShowData {
32    fn from(data: &DomainShowData) -> Self {
33        Self {
34            lemma_type: LemmaType::from(&data.lemma_type),
35            fill: data.fill.as_ref().map(RuleResultValue::from),
36            suggestion: data.suggestion.as_ref().map(RuleResultValue::from),
37            needed_by_rules: data.needed_by_rules.clone(),
38        }
39    }
40}
41
42#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
43pub struct ShowVersion {
44    #[serde(skip_serializing_if = "Option::is_none", default)]
45    pub effective_from: Option<DateTimeValue>,
46    #[serde(skip_serializing_if = "Option::is_none", default)]
47    pub effective_to: Option<DateTimeValue>,
48}
49
50impl From<&DomainShowVersion> for ShowVersion {
51    fn from(version: &DomainShowVersion) -> Self {
52        Self {
53            effective_from: version.effective_from.clone(),
54            effective_to: version.effective_to.clone(),
55        }
56    }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
60#[serde(rename_all = "snake_case")]
61pub enum ShowConversionTarget {
62    Type(PrimitiveKind),
63    Unit { unit_name: String },
64}
65
66impl From<&DomainConversionTarget> for ShowConversionTarget {
67    fn from(target: &DomainConversionTarget) -> Self {
68        match target {
69            DomainConversionTarget::Type(kind) => Self::Type(*kind),
70            DomainConversionTarget::Unit { unit_name } => Self::Unit {
71                unit_name: unit_name.clone(),
72            },
73        }
74    }
75}
76
77/// Resolved expression on a Show rule branch.
78#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
79#[serde(tag = "type", rename_all = "snake_case")]
80pub enum ShowExpression {
81    Literal {
82        #[serde(flatten)]
83        value: Box<RuleResultValue>,
84    },
85    Data {
86        name: String,
87    },
88    Rule {
89        name: String,
90    },
91    And {
92        left: Box<ShowExpression>,
93        right: Box<ShowExpression>,
94    },
95    Not {
96        operand: Box<ShowExpression>,
97    },
98    Arithmetic {
99        op: ArithmeticComputation,
100        left: Box<ShowExpression>,
101        right: Box<ShowExpression>,
102    },
103    Comparison {
104        op: ComparisonComputation,
105        left: Box<ShowExpression>,
106        right: Box<ShowExpression>,
107    },
108    UnitConversion {
109        operand: Box<ShowExpression>,
110        target: ShowConversionTarget,
111    },
112    Math {
113        op: MathematicalComputation,
114        operand: Box<ShowExpression>,
115    },
116    Veto {
117        #[serde(skip_serializing_if = "Option::is_none", default)]
118        message: Option<String>,
119    },
120    Now,
121    DateRelative {
122        kind: DateRelativeKind,
123        operand: Box<ShowExpression>,
124    },
125    DateCalendar {
126        kind: DateCalendarKind,
127        unit: CalendarPeriodUnit,
128        operand: Box<ShowExpression>,
129    },
130    RangeLiteral {
131        from: Box<ShowExpression>,
132        to: Box<ShowExpression>,
133    },
134    PastFutureRange {
135        kind: DateRelativeKind,
136        operand: Box<ShowExpression>,
137    },
138    RangeContainment {
139        value: Box<ShowExpression>,
140        range: Box<ShowExpression>,
141    },
142    IsVeto {
143        operand: Box<ShowExpression>,
144    },
145}
146
147impl From<&DomainShowExpression> for ShowExpression {
148    fn from(expression: &DomainShowExpression) -> Self {
149        match expression {
150            DomainShowExpression::Literal(value) => Self::Literal {
151                value: Box::new(RuleResultValue::from(value.as_ref())),
152            },
153            DomainShowExpression::Data { name } => Self::Data { name: name.clone() },
154            DomainShowExpression::Rule { name } => Self::Rule { name: name.clone() },
155            DomainShowExpression::And { left, right } => Self::And {
156                left: Box::new(ShowExpression::from(left.as_ref())),
157                right: Box::new(ShowExpression::from(right.as_ref())),
158            },
159            DomainShowExpression::Not { operand } => Self::Not {
160                operand: Box::new(ShowExpression::from(operand.as_ref())),
161            },
162            DomainShowExpression::Arithmetic { op, left, right } => Self::Arithmetic {
163                op: op.clone(),
164                left: Box::new(ShowExpression::from(left.as_ref())),
165                right: Box::new(ShowExpression::from(right.as_ref())),
166            },
167            DomainShowExpression::Comparison { op, left, right } => Self::Comparison {
168                op: op.clone(),
169                left: Box::new(ShowExpression::from(left.as_ref())),
170                right: Box::new(ShowExpression::from(right.as_ref())),
171            },
172            DomainShowExpression::UnitConversion { operand, target } => Self::UnitConversion {
173                operand: Box::new(ShowExpression::from(operand.as_ref())),
174                target: ShowConversionTarget::from(target),
175            },
176            DomainShowExpression::Math { op, operand } => Self::Math {
177                op: op.clone(),
178                operand: Box::new(ShowExpression::from(operand.as_ref())),
179            },
180            DomainShowExpression::Veto { message } => Self::Veto {
181                message: message.clone(),
182            },
183            DomainShowExpression::Now => Self::Now,
184            DomainShowExpression::DateRelative { kind, operand } => Self::DateRelative {
185                kind: *kind,
186                operand: Box::new(ShowExpression::from(operand.as_ref())),
187            },
188            DomainShowExpression::DateCalendar {
189                kind,
190                unit,
191                operand,
192            } => Self::DateCalendar {
193                kind: *kind,
194                unit: *unit,
195                operand: Box::new(ShowExpression::from(operand.as_ref())),
196            },
197            DomainShowExpression::RangeLiteral { from, to } => Self::RangeLiteral {
198                from: Box::new(ShowExpression::from(from.as_ref())),
199                to: Box::new(ShowExpression::from(to.as_ref())),
200            },
201            DomainShowExpression::PastFutureRange { kind, operand } => Self::PastFutureRange {
202                kind: *kind,
203                operand: Box::new(ShowExpression::from(operand.as_ref())),
204            },
205            DomainShowExpression::RangeContainment { value, range } => Self::RangeContainment {
206                value: Box::new(ShowExpression::from(value.as_ref())),
207                range: Box::new(ShowExpression::from(range.as_ref())),
208            },
209            DomainShowExpression::IsVeto { operand } => Self::IsVeto {
210                operand: Box::new(ShowExpression::from(operand.as_ref())),
211            },
212        }
213    }
214}
215
216#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
217pub struct ShowBranch {
218    #[serde(skip_serializing_if = "Option::is_none", default)]
219    pub condition: Option<ShowExpression>,
220    pub result: ShowExpression,
221}
222
223impl From<&DomainShowBranch> for ShowBranch {
224    fn from(branch: &DomainShowBranch) -> Self {
225        Self {
226            condition: branch.condition.as_ref().map(ShowExpression::from),
227            result: ShowExpression::from(&branch.result),
228        }
229    }
230}
231
232#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
233pub struct ShowRule {
234    #[serde(rename = "type")]
235    pub lemma_type: LemmaType,
236    pub branches: Vec<ShowBranch>,
237    pub depends_on_rules: Vec<String>,
238}
239
240impl From<&DomainShowRule> for ShowRule {
241    fn from(rule: &DomainShowRule) -> Self {
242        Self {
243            lemma_type: LemmaType::from(&rule.lemma_type),
244            branches: rule.branches.iter().map(ShowBranch::from).collect(),
245            depends_on_rules: rule.depends_on_rules.clone(),
246        }
247    }
248}
249
250#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
251pub struct Show {
252    pub spec: String,
253    #[serde(skip_serializing_if = "Option::is_none", default)]
254    pub commentary: Option<String>,
255    #[serde(skip_serializing_if = "Option::is_none", default)]
256    pub effective_from: Option<DateTimeValue>,
257    #[serde(skip_serializing_if = "Option::is_none", default)]
258    pub effective_to: Option<DateTimeValue>,
259    #[serde(skip_serializing_if = "Vec::is_empty", default)]
260    pub versions: Vec<ShowVersion>,
261    pub start_line: usize,
262    #[serde(skip_serializing_if = "Option::is_none", default)]
263    pub source_type: Option<SourceType>,
264    pub data: IndexMap<String, ShowData>,
265    pub rules: IndexMap<String, ShowRule>,
266    pub meta: IndexMap<String, Value>,
267}
268
269impl From<&DomainShow> for Show {
270    fn from(show: &DomainShow) -> Self {
271        Self {
272            spec: show.spec.clone(),
273            commentary: show.commentary.clone(),
274            effective_from: show.effective_from.clone(),
275            effective_to: show.effective_to.clone(),
276            versions: show.versions.iter().map(ShowVersion::from).collect(),
277            start_line: show.start_line,
278            source_type: show.source_type.clone(),
279            data: show
280                .data
281                .iter()
282                .map(|(name, data)| (name.clone(), ShowData::from(data)))
283                .collect(),
284            rules: show
285                .rules
286                .iter()
287                .map(|(name, rule)| (name.clone(), ShowRule::from(rule)))
288                .collect(),
289            meta: show.meta.clone(),
290        }
291    }
292}