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