1use chrono::{DateTime, NaiveDateTime};
2use regex::Regex;
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use serde_json::{Value as JsonValue, Value};
5use std::collections::HashMap;
6
7use crate::{unwrap_or_return, DynamicValue};
8
9use super::dynamic_string::DynamicString;
10
11#[macro_export]
12macro_rules! test_only_make_eval_value {
13 ($x:expr) => {
14 $crate::evaluation::evaluator_value::EvaluatorValue::from(serde_json::json!($x))
15 };
16}
17
18#[derive(Debug, PartialEq)]
19pub enum EvaluatorValueType {
20 Null,
21
22 Bool,
23 Number,
24 String,
25 Array,
26 Object,
27}
28
29#[derive(Debug)]
30pub struct EvaluatorValue {
31 pub value_type: EvaluatorValueType,
32 pub bool_value: Option<bool>,
33 pub float_value: Option<f64>,
34 pub string_value: Option<DynamicString>,
35 pub regex_value: Option<Regex>,
36 pub timestamp_value: Option<i64>,
37 pub array_value: Option<HashMap<String, (usize, String)>>,
39 pub object_value: Option<HashMap<String, DynamicString>>,
40}
41
42impl EvaluatorValue {
43 pub fn new(value_type: EvaluatorValueType) -> Self {
44 Self {
45 value_type,
46 bool_value: None,
47 float_value: None,
48 string_value: None,
49 regex_value: None,
50 timestamp_value: None,
51 array_value: None,
52 object_value: None,
53 }
54 }
55
56 pub fn null() -> Self {
57 Self::new(EvaluatorValueType::Null)
58 }
59
60 pub fn compile_regex(&mut self) {
61 let str_value = match &self.string_value {
62 Some(dyn_str) => &dyn_str.value,
63 None => return,
64 };
65
66 if let Ok(regex) = Regex::new(str_value) {
67 self.regex_value = Some(regex);
68 }
69 }
70
71 pub fn is_equal_to_dynamic_value(&self, other: &DynamicValue) -> bool {
72 match self.value_type {
73 EvaluatorValueType::Null => other.json_value == Value::Null,
74 EvaluatorValueType::Bool => self.bool_value == other.bool_value,
75 EvaluatorValueType::Number => self.float_value == other.float_value,
76 EvaluatorValueType::String => self.string_value == other.string_value,
77 EvaluatorValueType::Array => {
78 let self_keyed_arr = match &self.array_value {
79 Some(map) => map,
80 None => return other.array_value.is_none(),
81 };
82
83 let other_arr = match &other.array_value {
84 Some(arr) => arr,
85 None => return false,
86 };
87
88 if self_keyed_arr.len() != other_arr.len() {
89 return false;
90 }
91
92 for (i, self_value) in self_keyed_arr.values() {
93 let other_dyn_str = unwrap_or_return!(&other_arr[*i].string_value, false);
94 if *self_value != other_dyn_str.value {
95 return false;
96 }
97 }
98
99 true
100 }
101 EvaluatorValueType::Object => {
102 let self_obj = match &self.object_value {
103 Some(map) => map,
104 None => return other.object_value.is_none(),
105 };
106
107 let other_obj = match &other.object_value {
108 Some(arr) => arr,
109 None => return false,
110 };
111
112 if self_obj.len() != other_obj.len() {
113 return false;
114 }
115
116 for (k, v) in self_obj {
117 let other_dyn_val = unwrap_or_return!(other_obj.get(k), false);
118 let other_str_val = unwrap_or_return!(&other_dyn_val.string_value, false);
119 if other_str_val.value != v.value {
120 return false;
121 }
122 }
123
124 true
125 }
126 }
127 }
128}
129
130impl From<String> for EvaluatorValue {
133 fn from(value: String) -> Self {
134 EvaluatorValue {
135 timestamp_value: try_parse_timestamp(&value),
136 float_value: value.parse::<f64>().ok(),
137 string_value: Some(DynamicString::from(value)),
138 ..EvaluatorValue::new(EvaluatorValueType::String)
139 }
140 }
141}
142
143impl From<JsonValue> for EvaluatorValue {
145 fn from(value: JsonValue) -> Self {
146 match value {
147 JsonValue::Null => EvaluatorValue::new(EvaluatorValueType::Null),
148
149 JsonValue::Bool(b) => EvaluatorValue {
150 bool_value: Some(b),
151 ..EvaluatorValue::new(EvaluatorValueType::Bool)
152 },
153
154 JsonValue::Number(n) => EvaluatorValue {
155 float_value: n.as_f64(),
156 ..EvaluatorValue::new(EvaluatorValueType::Number)
157 },
158
159 JsonValue::String(s) => EvaluatorValue::from(s),
160
161 JsonValue::Array(arr) => {
162 let keyed_array: HashMap<String, (usize, String)> = arr
163 .into_iter()
164 .enumerate()
165 .map(|(idx, val)| {
166 let str_value = match val.as_str() {
167 Some(s) => s.to_string(), None => val.to_string(), };
170
171 (str_value.to_lowercase(), (idx, str_value))
172 })
173 .collect();
174
175 EvaluatorValue {
176 array_value: Some(keyed_array),
177 ..EvaluatorValue::new(EvaluatorValueType::Array)
178 }
179 }
180
181 JsonValue::Object(obj) => EvaluatorValue {
182 object_value: Some(
183 obj.into_iter()
184 .map(|(k, v)| (k, DynamicString::from(v)))
185 .collect(),
186 ),
187 ..EvaluatorValue::new(EvaluatorValueType::Object)
188 },
189 }
190 }
191}
192
193impl Serialize for EvaluatorValue {
194 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
195 where
196 S: Serializer,
197 {
198 match &self.value_type {
199 EvaluatorValueType::Null => JsonValue::Null.serialize(serializer),
200 EvaluatorValueType::Bool => self.bool_value.serialize(serializer),
201 EvaluatorValueType::Number => self.float_value.serialize(serializer),
202 EvaluatorValueType::String => self.string_value.serialize(serializer),
203 EvaluatorValueType::Array => {
204 let array_map = match &self.array_value {
205 Some(a) => a,
206 None => return JsonValue::Null.serialize(serializer),
207 };
208
209 let mut result = vec![String::new(); array_map.len()];
210
211 for (idx, val) in array_map.values() {
212 result[*idx] = val.clone();
213 }
214
215 result.serialize(serializer)
216 }
217 EvaluatorValueType::Object => self.object_value.serialize(serializer),
218 }
219 }
220}
221
222impl<'de> Deserialize<'de> for EvaluatorValue {
223 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
224 where
225 D: Deserializer<'de>,
226 {
227 let json_value = JsonValue::deserialize(deserializer)?;
228 Ok(EvaluatorValue::from(json_value))
229 }
230}
231
232impl PartialEq for EvaluatorValue {
233 fn eq(&self, other: &Self) -> bool {
234 self.value_type == other.value_type
235 && self.bool_value == other.bool_value
236 && self.float_value == other.float_value
237 && self.string_value == other.string_value
238 && self.array_value == other.array_value
239 && self.object_value == other.object_value
240 }
241}
242
243fn try_parse_timestamp(s: &str) -> Option<i64> {
244 if let Ok(ts) = s.parse::<i64>() {
245 return Some(ts);
246 }
247
248 if let Ok(dt) = DateTime::parse_from_rfc3339(s) {
249 return Some(dt.timestamp_millis());
250 }
251
252 if let Ok(ndt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
253 return Some(ndt.and_utc().timestamp_millis());
254 }
255
256 None
257}