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