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