1use crate::literals::rational_to_serialized_str;
4use crate::planning::semantics::{
5 LiteralValue as DomainLiteralValue, SemanticDateTime, SemanticTime,
6 ValueKind as DomainValueKind,
7};
8use crate::result_value::{
9 CalendarResult as DomainCalendarResult, RangeResult as DomainRangeResult,
10 RuleResultValue as DomainRuleResultValue,
11};
12use serde::{Deserialize, Serialize};
13use std::collections::BTreeMap;
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
17#[serde(rename_all = "lowercase")]
18pub enum ValueKind {
19 Number(String),
20 Measure {
21 value: String,
22 },
23 Ratio {
24 value: String,
25 },
26 Text(String),
27 Date(SemanticDateTime),
28 Time(SemanticTime),
29 Boolean(bool),
30 Range {
31 from: Box<ValueKind>,
32 to: Box<ValueKind>,
33 },
34}
35
36impl From<&DomainValueKind> for ValueKind {
37 fn from(value: &DomainValueKind) -> Self {
38 match value {
39 DomainValueKind::Number(rational) => Self::Number(
40 rational_to_serialized_str(rational)
41 .expect("BUG: planned bound must serialize to decimal string"),
42 ),
43 DomainValueKind::Measure(rational) => Self::Measure {
44 value: rational_to_serialized_str(rational)
45 .expect("BUG: planned bound must serialize to decimal string"),
46 },
47 DomainValueKind::Ratio(rational) => Self::Ratio {
48 value: rational_to_serialized_str(rational)
49 .expect("BUG: planned bound must serialize to decimal string"),
50 },
51 DomainValueKind::Text(text) => Self::Text(text.clone()),
52 DomainValueKind::Date(date) => Self::Date(date.clone()),
53 DomainValueKind::Time(time) => Self::Time(time.clone()),
54 DomainValueKind::Boolean(flag) => Self::Boolean(*flag),
55 DomainValueKind::Range(from, to) => Self::Range {
56 from: Box::new(ValueKind::from(&from.value)),
57 to: Box::new(ValueKind::from(&to.value)),
58 },
59 }
60 }
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
64pub struct LiteralValue {
65 pub value: ValueKind,
66}
67
68impl From<&DomainLiteralValue> for LiteralValue {
69 fn from(literal: &DomainLiteralValue) -> Self {
70 Self {
71 value: ValueKind::from(&literal.value),
72 }
73 }
74}
75
76#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
77pub struct CalendarResult {
78 pub value: String,
79 pub unit: String,
80}
81
82impl From<&DomainCalendarResult> for CalendarResult {
83 fn from(calendar: &DomainCalendarResult) -> Self {
84 Self {
85 value: calendar.value.clone(),
86 unit: calendar.unit.clone(),
87 }
88 }
89}
90
91#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
92pub struct RangeResult {
93 pub from: RuleResultValue,
94 pub to: RuleResultValue,
95}
96
97impl From<&DomainRangeResult> for RangeResult {
98 fn from(range: &DomainRangeResult) -> Self {
99 Self {
100 from: RuleResultValue::from(&range.from),
101 to: RuleResultValue::from(&range.to),
102 }
103 }
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Default)]
107pub struct RuleResultValue {
108 #[serde(default, skip_serializing_if = "Option::is_none")]
109 pub display: Option<String>,
110 #[serde(default, skip_serializing_if = "Option::is_none")]
111 pub measure: Option<BTreeMap<String, String>>,
112 #[serde(default, skip_serializing_if = "Option::is_none")]
113 pub ratio: Option<BTreeMap<String, String>>,
114 #[serde(default, skip_serializing_if = "Option::is_none")]
115 pub number: Option<String>,
116 #[serde(default, skip_serializing_if = "Option::is_none")]
117 pub boolean: Option<bool>,
118 #[serde(default, skip_serializing_if = "Option::is_none")]
119 pub text: Option<String>,
120 #[serde(default, skip_serializing_if = "Option::is_none")]
121 pub date: Option<SemanticDateTime>,
122 #[serde(default, skip_serializing_if = "Option::is_none")]
123 pub time: Option<SemanticTime>,
124 #[serde(default, skip_serializing_if = "Option::is_none")]
125 pub calendar: Option<CalendarResult>,
126 #[serde(default, skip_serializing_if = "Option::is_none")]
127 pub range: Option<Box<RangeResult>>,
128}
129
130impl From<&DomainRuleResultValue> for RuleResultValue {
131 fn from(value: &DomainRuleResultValue) -> Self {
132 Self {
133 display: value.display.clone(),
134 measure: value.measure.clone(),
135 ratio: value.ratio.clone(),
136 number: value.number.clone(),
137 boolean: value.boolean,
138 text: value.text.clone(),
139 date: value.date.clone(),
140 time: value.time.clone(),
141 calendar: value.calendar.as_ref().map(CalendarResult::from),
142 range: value
143 .range
144 .as_ref()
145 .map(|range| Box::new(RangeResult::from(range.as_ref()))),
146 }
147 }
148}