1use chrono::{DateTime, NaiveDateTime};
2use fancy_regex::Regex as FancyRegex;
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use serde_json::{
5 value::{to_raw_value, RawValue},
6 Value as JsonValue, Value,
7};
8use std::{borrow::Cow, collections::HashMap, sync::Arc};
9
10use crate::{
11 impl_interned_value, interned_string::InternedString, interned_value_store::FromRawValue,
12 log_e, unwrap_or_return, DynamicValue,
13};
14
15use super::dynamic_string::DynamicString;
16
17lazy_static::lazy_static! {
18 pub(crate) static ref EMPTY_EVALUATOR_VALUE: EvaluatorValue = EvaluatorValue {
19 hash: 0,
20 inner: Arc::new(MemoizedEvaluatorValue::new(EvaluatorValueType::Null)),
21 };
22}
23
24const TAG: &str = "EvaluatorValue";
25
26#[derive(Clone, Debug)]
27pub struct EvaluatorValue {
28 pub hash: u64,
29 pub inner: Arc<MemoizedEvaluatorValue>,
30}
31
32impl_interned_value!(EvaluatorValue, MemoizedEvaluatorValue);
33
34impl EvaluatorValue {
35 pub fn empty() -> &'static Self {
36 &EMPTY_EVALUATOR_VALUE
37 }
38
39 pub fn from_json_value(value: Value) -> Self {
40 let raw_value = match to_raw_value(&value) {
41 Ok(raw_value) => raw_value,
42 Err(e) => {
43 log_e!(TAG, "Failed to convert map to raw value: {}", e);
44 return Self::empty().clone();
45 }
46 };
47
48 let (hash, value) = EvaluatorValue::get_or_create_memoized(Cow::Owned(raw_value));
49 Self { hash, inner: value }
50 }
51
52 pub fn compile_regex(&mut self) {
53 let mut_inner = Arc::make_mut(&mut self.inner);
54 mut_inner.compile_regex();
55 }
56}
57
58impl<'de> Deserialize<'de> for EvaluatorValue {
59 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
60 where
61 D: Deserializer<'de>,
62 {
63 let raw_value_ref: Box<RawValue> = Deserialize::deserialize(deserializer)?;
64 let (hash, value) = EvaluatorValue::get_or_create_memoized(Cow::Owned(raw_value_ref));
65 Ok(EvaluatorValue { hash, inner: value })
66 }
67}
68
69impl Serialize for EvaluatorValue {
70 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
71 where
72 S: Serializer,
73 {
74 self.inner.serialize(serializer)
75 }
76}
77
78impl PartialEq for EvaluatorValue {
79 fn eq(&self, other: &Self) -> bool {
80 self.inner == other.inner
81 }
82}
83
84#[derive(Debug, PartialEq, Clone)]
85pub enum EvaluatorValueType {
86 Null,
87
88 Bool,
89 Number,
90 String,
91 Array,
92 Object,
93}
94
95#[derive(Debug, Clone)]
96pub struct MemoizedEvaluatorValue {
97 pub value_type: EvaluatorValueType,
98 pub bool_value: Option<bool>,
99 pub float_value: Option<f64>,
100 pub string_value: Option<DynamicString>,
101 pub regex_value: Option<FancyRegex>,
102 pub timestamp_value: Option<i64>,
103 pub array_value: Option<HashMap<InternedString, (usize, InternedString)>>,
105 pub object_value: Option<HashMap<InternedString, DynamicString>>,
106}
107
108impl FromRawValue for MemoizedEvaluatorValue {
109 fn from_raw_value(raw_value: Cow<'_, RawValue>) -> Self {
110 match serde_json::from_str(raw_value.get()) {
111 Ok(value) => value,
112 Err(e) => {
113 log_e!(
114 TAG,
115 "Failed to convert raw value to MemoizedEvaluatorValue: {}",
116 e
117 );
118 Self::null()
119 }
120 }
121 }
122}
123
124impl MemoizedEvaluatorValue {
125 pub fn new(value_type: EvaluatorValueType) -> Self {
126 Self {
127 value_type,
128 bool_value: None,
129 float_value: None,
130 string_value: None,
131 regex_value: None,
132 timestamp_value: None,
133 array_value: None,
134 object_value: None,
135 }
136 }
137
138 pub fn null() -> Self {
139 Self::new(EvaluatorValueType::Null)
140 }
141
142 pub fn compile_regex(&mut self) {
143 let str_value = match &self.string_value {
144 Some(dyn_str) => &dyn_str.value,
145 None => return,
146 };
147
148 if let Ok(regex) = FancyRegex::new(str_value) {
149 self.regex_value = Some(regex);
150 }
151 }
152
153 pub fn is_equal_to_dynamic_value(&self, other: &DynamicValue) -> bool {
154 match self.value_type {
155 EvaluatorValueType::Null => other.json_value == Value::Null,
156 EvaluatorValueType::Bool => self.bool_value == other.bool_value,
157 EvaluatorValueType::Number => self.float_value == other.float_value,
158 EvaluatorValueType::String => self.string_value == other.string_value,
159 EvaluatorValueType::Array => {
160 let self_keyed_arr = match &self.array_value {
161 Some(map) => map,
162 None => return other.array_value.is_none(),
163 };
164
165 let other_arr = match &other.array_value {
166 Some(arr) => arr,
167 None => return false,
168 };
169
170 if self_keyed_arr.len() != other_arr.len() {
171 return false;
172 }
173
174 for (i, self_value) in self_keyed_arr.values() {
175 let other_dyn_str = unwrap_or_return!(&other_arr[*i].string_value, false);
176 if *self_value != other_dyn_str.value {
177 return false;
178 }
179 }
180
181 true
182 }
183 EvaluatorValueType::Object => {
184 let self_obj = match &self.object_value {
185 Some(map) => map,
186 None => return other.object_value.is_none(),
187 };
188
189 let other_obj = match &other.object_value {
190 Some(arr) => arr,
191 None => return false,
192 };
193
194 if self_obj.len() != other_obj.len() {
195 return false;
196 }
197
198 for (k, v) in self_obj {
199 let other_dyn_val = unwrap_or_return!(other_obj.get(k.as_str()), false);
200 let other_str_val = unwrap_or_return!(&other_dyn_val.string_value, false);
201 if other_str_val.value != v.value {
202 return false;
203 }
204 }
205
206 true
207 }
208 }
209 }
210}
211
212impl From<String> for MemoizedEvaluatorValue {
215 fn from(value: String) -> Self {
216 MemoizedEvaluatorValue {
217 timestamp_value: try_parse_timestamp(&value),
218 float_value: value.parse::<f64>().ok(),
219 string_value: Some(DynamicString::from(value)),
220 ..MemoizedEvaluatorValue::new(EvaluatorValueType::String)
221 }
222 }
223}
224
225impl From<JsonValue> for MemoizedEvaluatorValue {
227 fn from(value: JsonValue) -> Self {
228 match value {
229 JsonValue::Null => MemoizedEvaluatorValue::new(EvaluatorValueType::Null),
230
231 JsonValue::Bool(b) => MemoizedEvaluatorValue {
232 bool_value: Some(b),
233 ..MemoizedEvaluatorValue::new(EvaluatorValueType::Bool)
234 },
235
236 JsonValue::Number(n) => MemoizedEvaluatorValue {
237 float_value: n.as_f64(),
238 ..MemoizedEvaluatorValue::new(EvaluatorValueType::Number)
239 },
240
241 JsonValue::String(s) => MemoizedEvaluatorValue::from(s),
242
243 JsonValue::Array(arr) => {
244 let keyed_array: HashMap<InternedString, (usize, InternedString)> = arr
245 .into_iter()
246 .enumerate()
247 .map(|(idx, val)| {
248 let str_value = match val.as_str() {
249 Some(s) => s.to_string(), None => val.to_string(), };
252
253 let interned_lowercased_str =
254 InternedString::from_string(str_value.to_lowercase());
255 let interned_str = InternedString::from_string(str_value);
256
257 (interned_lowercased_str, (idx, interned_str))
258 })
259 .collect();
260
261 MemoizedEvaluatorValue {
262 array_value: Some(keyed_array),
263 ..MemoizedEvaluatorValue::new(EvaluatorValueType::Array)
264 }
265 }
266
267 JsonValue::Object(obj) => MemoizedEvaluatorValue {
268 object_value: Some(
269 obj.into_iter()
270 .map(|(k, v)| (InternedString::from_string(k), DynamicString::from(v)))
271 .collect(),
272 ),
273 ..MemoizedEvaluatorValue::new(EvaluatorValueType::Object)
274 },
275 }
276 }
277}
278
279impl Serialize for MemoizedEvaluatorValue {
280 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
281 where
282 S: Serializer,
283 {
284 match &self.value_type {
285 EvaluatorValueType::Null => JsonValue::Null.serialize(serializer),
286 EvaluatorValueType::Bool => self.bool_value.serialize(serializer),
287 EvaluatorValueType::Number => self.float_value.serialize(serializer),
288 EvaluatorValueType::String => self.string_value.serialize(serializer),
289 EvaluatorValueType::Array => {
290 let array_map = match &self.array_value {
291 Some(a) => a,
292 None => return JsonValue::Null.serialize(serializer),
293 };
294
295 let mut result = vec![String::new(); array_map.len()];
296
297 for (idx, val) in array_map.values() {
298 result[*idx] = val.unperformant_to_string();
299 }
300
301 result.serialize(serializer)
302 }
303 EvaluatorValueType::Object => self.object_value.serialize(serializer),
304 }
305 }
306}
307
308impl<'de> Deserialize<'de> for MemoizedEvaluatorValue {
309 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
310 where
311 D: Deserializer<'de>,
312 {
313 let json_value = JsonValue::deserialize(deserializer)?;
314 Ok(MemoizedEvaluatorValue::from(json_value))
315 }
316}
317
318impl PartialEq for MemoizedEvaluatorValue {
319 fn eq(&self, other: &Self) -> bool {
320 self.value_type == other.value_type
321 && self.bool_value == other.bool_value
322 && self.float_value == other.float_value
323 && self.string_value == other.string_value
324 && self.array_value == other.array_value
325 && self.object_value == other.object_value
326 }
327}
328
329fn try_parse_timestamp(s: &str) -> Option<i64> {
330 if let Ok(ts) = s.parse::<i64>() {
331 return Some(ts);
332 }
333
334 if let Ok(dt) = DateTime::parse_from_rfc3339(s) {
335 return Some(dt.timestamp_millis());
336 }
337
338 if let Ok(ndt) = NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S") {
339 return Some(ndt.and_utc().timestamp_millis());
340 }
341
342 None
343}
344
345#[macro_export]
346macro_rules! test_only_make_eval_value {
347 ($x:expr) => {
348 $crate::evaluation::evaluator_value::MemoizedEvaluatorValue::from(serde_json::json!($x))
349 };
350}