1use fancy_regex::Regex as FancyRegex;
2use serde::{
3 ser::{SerializeMap, SerializeSeq},
4 Deserialize, Deserializer, Serialize, Serializer,
5};
6use serde_json::{
7 value::{to_raw_value, RawValue},
8 Value as JsonValue, Value,
9};
10use std::{borrow::Cow, collections::HashMap, sync::Arc};
11
12use crate::{
13 evaluation::evaluation_data::InternedStrRef,
14 hashing,
15 interned_string::InternedString,
16 interned_values::{
17 mmap_data_v2::{ArchivedMmapEvaluatorValue, ArchivedMmapEvaluatorValueType},
18 InternedStore,
19 },
20 log_e,
21 value_parsing::try_parse_timestamp,
22};
23use crate::{user::user_value::UserValueRef, DynamicValue};
24
25use super::dynamic_string::DynamicString;
26
27lazy_static::lazy_static! {
28 pub(crate) static ref EMPTY_EVALUATOR_VALUE: EvaluatorValue = EvaluatorValue {
29 hash: 0,
30 inner: EvaluatorValueInner::Pointer(Arc::new(MemoizedEvaluatorValue::new(EvaluatorValueType::Null))),
31 };
32}
33
34const TAG: &str = "EvaluatorValue";
35
36#[derive(Clone)]
37#[non_exhaustive]
38pub enum EvaluatorValueInner {
39 Pointer(Arc<MemoizedEvaluatorValue>),
40 Static(&'static MemoizedEvaluatorValue),
41 Mmap(MmapEvaluatorValueHandle),
42}
43
44#[derive(Clone, Copy)]
45pub struct MmapEvaluatorValueHandle {
46 value: &'static ArchivedMmapEvaluatorValue,
47 regex: Option<&'static FancyRegex>,
48}
49
50impl MmapEvaluatorValueHandle {
51 pub(crate) fn new(
52 value: &'static ArchivedMmapEvaluatorValue,
53 regex: Option<&'static FancyRegex>,
54 ) -> Self {
55 Self { value, regex }
56 }
57}
58
59impl std::fmt::Debug for EvaluatorValueInner {
60 fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
61 match self {
62 Self::Pointer(value) => formatter.debug_tuple("Pointer").field(value).finish(),
63 Self::Static(value) => formatter.debug_tuple("Static").field(value).finish(),
64 Self::Mmap(_) => formatter.write_str("Mmap"),
65 }
66 }
67}
68
69#[derive(Clone, Debug)]
70pub struct EvaluatorValue {
71 pub hash: u64,
72 pub inner: EvaluatorValueInner,
73}
74
75impl EvaluatorValue {
76 pub fn empty() -> &'static Self {
77 &EMPTY_EVALUATOR_VALUE
78 }
79
80 pub fn from_json_value(value: Value) -> Self {
81 let raw_value = match to_raw_value(&value) {
82 Ok(raw_value) => raw_value,
83 Err(e) => {
84 log_e!(TAG, "Failed to convert map to raw value: {}", e);
85 return Self::empty().clone();
86 }
87 };
88
89 InternedStore::get_or_intern_evaluator_value(Cow::Owned(raw_value))
90 }
91
92 pub fn compile_regex(&mut self) {
93 match &mut self.inner {
94 EvaluatorValueInner::Pointer(inner) => {
95 if inner.regex_value.is_some() {
96 return;
97 }
98
99 let mut_inner = Arc::make_mut(inner);
100 mut_inner.compile_regex();
101 InternedStore::replace_evaluator_value(self.hash, inner.clone());
102 }
103 EvaluatorValueInner::Static(inner) => {
104 if inner.regex_value.is_some() {
105 return;
106 }
107
108 log_e!(TAG, "Cannot compile regex for static EvaluatorValue");
110 }
111 EvaluatorValueInner::Mmap(handle) => {
112 if handle.regex.is_some() {
113 return;
114 }
115
116 let handle = *handle;
117 let mut materialized = InternedStore::materialize_mmap_evaluator_value_owned(
118 handle.value,
119 handle.regex,
120 );
121 materialized.compile_regex();
122 let inner = Arc::new(materialized);
123 InternedStore::replace_mmap_evaluator_value(self.hash, inner.clone());
124 self.inner = EvaluatorValueInner::Pointer(inner);
125 }
126 }
127 }
128}
129
130impl AsRef<MemoizedEvaluatorValue> for EvaluatorValue {
131 fn as_ref(&self) -> &MemoizedEvaluatorValue {
132 match &self.inner {
133 EvaluatorValueInner::Pointer(inner) => inner,
134 EvaluatorValueInner::Static(inner) => inner,
135 EvaluatorValueInner::Mmap(handle) => InternedStore::materialize_mmap_evaluator_value(
136 self.hash,
137 handle.value,
138 handle.regex,
139 ),
140 }
141 }
142}
143
144#[derive(Clone, Copy)]
145pub(crate) enum EvaluatorValueRef<'a> {
146 Owned(&'a MemoizedEvaluatorValue),
147 Mmap(&'a ArchivedMmapEvaluatorValue, Option<&'a FancyRegex>),
148}
149
150impl<'a> From<&'a MemoizedEvaluatorValue> for EvaluatorValueRef<'a> {
151 fn from(value: &'a MemoizedEvaluatorValue) -> Self {
152 Self::Owned(value)
153 }
154}
155
156impl EvaluatorValue {
157 pub(crate) fn as_value_ref(&self) -> EvaluatorValueRef<'_> {
158 match &self.inner {
159 EvaluatorValueInner::Pointer(value) => EvaluatorValueRef::Owned(value),
160 EvaluatorValueInner::Static(value) => EvaluatorValueRef::Owned(value),
161 EvaluatorValueInner::Mmap(handle) => {
162 EvaluatorValueRef::Mmap(handle.value, handle.regex)
163 }
164 }
165 }
166}
167
168impl<'a> EvaluatorValueRef<'a> {
169 pub(crate) fn bool_value(self) -> Option<bool> {
170 match self {
171 Self::Owned(value) => value.bool_value,
172 Self::Mmap(value, _) => value.bool_value.as_ref().copied(),
173 }
174 }
175
176 pub(crate) fn float_value(self) -> Option<f64> {
177 match self {
178 Self::Owned(value) => value.float_value,
179 Self::Mmap(value, _) => value.float_value.as_ref().map(|value| value.to_native()),
180 }
181 }
182
183 pub(crate) fn string_value(self) -> Option<&'a str> {
184 match self {
185 Self::Owned(value) => value
186 .string_value
187 .as_ref()
188 .map(|value| value.value.as_str()),
189 Self::Mmap(value, _) => {
190 let hash = value.string_value.as_ref().map(|hash| hash.to_native())?;
191 InternedStore::get_mmap_string(hash)
192 }
193 }
194 }
195
196 pub(crate) fn interned_string_value(self) -> Option<InternedStrRef<'a>> {
197 match self {
198 Self::Owned(value) => value
199 .string_value
200 .as_ref()
201 .map(|value| (&value.value).into()),
202 Self::Mmap(value, _) => value
203 .string_value
204 .as_ref()
205 .map(|hash| InternedStrRef::from_mmap(hash.to_native())),
206 }
207 }
208
209 pub(crate) fn regex_value(self) -> Option<&'a FancyRegex> {
210 match self {
211 Self::Owned(value) => value.regex_value.as_ref(),
212 Self::Mmap(_, regex) => regex,
213 }
214 }
215
216 pub(crate) fn timestamp_value(self) -> Option<i64> {
217 match self {
218 Self::Owned(value) => value.timestamp_value,
219 Self::Mmap(value, _) => value
220 .timestamp_value
221 .as_ref()
222 .map(|value| value.to_native()),
223 }
224 }
225
226 pub(crate) fn array_len(self) -> Option<usize> {
227 match self {
228 Self::Owned(value) => value.array_value.as_ref().map(HashMap::len),
229 Self::Mmap(value, _) => value.array_value.as_ref().map(|value| value.len()),
230 }
231 }
232
233 pub(crate) fn object_len(self) -> Option<usize> {
234 match self {
235 Self::Owned(value) => value.object_value.as_ref().map(HashMap::len),
236 Self::Mmap(value, _) => value.object_value.as_ref().map(|value| value.len()),
237 }
238 }
239
240 pub(crate) fn array_contains_key(self, key: &InternedString) -> bool {
241 match self {
242 Self::Owned(value) => value
243 .array_value
244 .as_ref()
245 .is_some_and(|array| array.contains_key(key)),
246 Self::Mmap(value, _) => value.array_value.as_ref().is_some_and(|array| {
247 array.contains_key(&rkyv::primitive::ArchivedU64::from_native(key.hash))
248 }),
249 }
250 }
251
252 pub(crate) fn array_contains_lowercase(self, key: &str) -> bool {
253 match self {
254 Self::Owned(value) => value
255 .array_value
256 .as_ref()
257 .is_some_and(|array| array.keys().any(|candidate| candidate.as_str() == key)),
258 Self::Mmap(value, _) => value.array_value.as_ref().is_some_and(|array| {
259 let hash = hashing::hash_one(key.as_bytes());
260 array.contains_key(&rkyv::primitive::ArchivedU64::from_native(hash))
261 }),
262 }
263 }
264
265 pub(crate) fn object_contains_key(self, key: &InternedString) -> bool {
266 match self {
267 Self::Owned(value) => value
268 .object_value
269 .as_ref()
270 .is_some_and(|object| object.contains_key(key)),
271 Self::Mmap(value, _) => value.object_value.as_ref().is_some_and(|object| {
272 object.contains_key(&rkyv::primitive::ArchivedU64::from_native(key.hash))
273 }),
274 }
275 }
276
277 pub(crate) fn object_contains_key_str(self, key: &str) -> bool {
278 match self {
279 Self::Owned(value) => value
280 .object_value
281 .as_ref()
282 .is_some_and(|object| object.keys().any(|candidate| candidate.as_str() == key)),
283 Self::Mmap(value, _) => value.object_value.as_ref().is_some_and(|object| {
284 let hash = hashing::hash_one(key.as_bytes());
285 object.contains_key(&rkyv::primitive::ArchivedU64::from_native(hash))
286 }),
287 }
288 }
289
290 pub(crate) fn any_array_entry(
291 self,
292 mut predicate: impl FnMut(&str, usize, &str) -> bool,
293 ) -> bool {
294 match self {
295 Self::Owned(value) => value.array_value.as_ref().is_some_and(|array| {
296 array.iter().any(|(lowercase, (index, original))| {
297 predicate(lowercase.as_str(), *index, original.as_str())
298 })
299 }),
300 Self::Mmap(value, _) => value.array_value.as_ref().is_some_and(|array| {
301 array.iter().any(|(lowercase, entry)| {
302 let Some(lowercase) = InternedStore::get_mmap_string(lowercase.to_native())
303 else {
304 return false;
305 };
306 let Some(original) = InternedStore::get_mmap_string(entry.1.to_native()) else {
307 return false;
308 };
309 predicate(lowercase, entry.0.to_native() as usize, original)
310 })
311 }),
312 }
313 }
314
315 fn all_array_entries(self, mut predicate: impl FnMut(&str, usize, &str) -> bool) -> bool {
316 match self {
317 Self::Owned(value) => value.array_value.as_ref().is_some_and(|array| {
318 array.iter().all(|(lowercase, (index, original))| {
319 predicate(lowercase.as_str(), *index, original.as_str())
320 })
321 }),
322 Self::Mmap(value, _) => value.array_value.as_ref().is_some_and(|array| {
323 array.iter().all(|(lowercase, entry)| {
324 let Some(lowercase) = InternedStore::get_mmap_string(lowercase.to_native())
325 else {
326 return false;
327 };
328 let Some(original) = InternedStore::get_mmap_string(entry.1.to_native()) else {
329 return false;
330 };
331 predicate(lowercase, entry.0.to_native() as usize, original)
332 })
333 }),
334 }
335 }
336
337 fn all_object_entries(self, mut predicate: impl FnMut(&str, &str) -> bool) -> bool {
338 match self {
339 Self::Owned(value) => value.object_value.as_ref().is_some_and(|object| {
340 object
341 .iter()
342 .all(|(key, value)| predicate(key.as_str(), value.value.as_str()))
343 }),
344 Self::Mmap(value, _) => value.object_value.as_ref().is_some_and(|object| {
345 object.iter().all(|(key, value)| {
346 let Some(key) = InternedStore::get_mmap_string(key.to_native()) else {
347 return false;
348 };
349 let Some(value) = InternedStore::get_mmap_string(value.to_native()) else {
350 return false;
351 };
352 predicate(key, value)
353 })
354 }),
355 }
356 }
357
358 fn value_type(self) -> EvaluatorValueType {
359 match self {
360 Self::Owned(value) => value.value_type,
361 Self::Mmap(value, _) => match value.value_type {
362 ArchivedMmapEvaluatorValueType::Null => EvaluatorValueType::Null,
363 ArchivedMmapEvaluatorValueType::Bool => EvaluatorValueType::Bool,
364 ArchivedMmapEvaluatorValueType::Number => EvaluatorValueType::Number,
365 ArchivedMmapEvaluatorValueType::String => EvaluatorValueType::String,
366 ArchivedMmapEvaluatorValueType::Array => EvaluatorValueType::Array,
367 ArchivedMmapEvaluatorValueType::Object => EvaluatorValueType::Object,
368 },
369 }
370 }
371
372 pub(crate) fn is_equal_to_user_value(self, other: UserValueRef<'_>) -> bool {
373 match self.value_type() {
374 EvaluatorValueType::Null => other.is_null(),
375 EvaluatorValueType::Bool => self.bool_value() == other.bool_value(),
376 EvaluatorValueType::Number => self.float_value() == other.float_value(),
377 EvaluatorValueType::String => self.string_value() == other.string_value(),
378 EvaluatorValueType::Array => {
379 let Some(len) = self.array_len() else {
380 return other.array_len().is_none();
381 };
382 if other.array_len() != Some(len) {
383 return false;
384 }
385 self.all_array_entries(|_, index, expected| {
386 other.array_item(index).and_then(UserValueRef::string_value) == Some(expected)
387 })
388 }
389 EvaluatorValueType::Object => {
390 let Some(len) = self.object_len() else {
391 return other.object_len().is_none();
392 };
393 if other.object_len() != Some(len) {
394 return false;
395 }
396 self.all_object_entries(|key, expected| {
397 other.object_get(key).and_then(UserValueRef::string_value) == Some(expected)
398 })
399 }
400 }
401 }
402
403 fn array_entry(self, lowercase: &str) -> Option<(usize, &'a str)> {
404 match self {
405 Self::Owned(value) => {
406 value
407 .array_value
408 .as_ref()?
409 .iter()
410 .find_map(|(candidate, (index, original))| {
411 (candidate.as_str() == lowercase).then_some((*index, original.as_str()))
412 })
413 }
414 Self::Mmap(value, _) => {
415 let hash = hashing::hash_one(lowercase.as_bytes());
416 let entry = value
417 .array_value
418 .as_ref()?
419 .get(&rkyv::primitive::ArchivedU64::from_native(hash))?;
420 Some((
421 entry.0.to_native() as usize,
422 InternedStore::get_mmap_string(entry.1.to_native())?,
423 ))
424 }
425 }
426 }
427
428 fn object_entry(self, key: &str) -> Option<&'a str> {
429 match self {
430 Self::Owned(value) => {
431 value
432 .object_value
433 .as_ref()?
434 .iter()
435 .find_map(|(candidate, value)| {
436 (candidate.as_str() == key).then_some(value.value.as_str())
437 })
438 }
439 Self::Mmap(value, _) => {
440 let hash = hashing::hash_one(key.as_bytes());
441 let value = value
442 .object_value
443 .as_ref()?
444 .get(&rkyv::primitive::ArchivedU64::from_native(hash))?;
445 InternedStore::get_mmap_string(value.to_native())
446 }
447 }
448 }
449
450 fn is_equal_to_evaluator_value(self, other: EvaluatorValueRef<'_>) -> bool {
451 if let (EvaluatorValueRef::Owned(left), EvaluatorValueRef::Owned(right)) = (self, other) {
452 return left == right;
453 }
454 let iterate_other = matches!(
455 (self, other),
456 (EvaluatorValueRef::Mmap(_, _), EvaluatorValueRef::Owned(_))
457 );
458
459 if self.value_type() != other.value_type() {
460 return false;
461 }
462
463 match self.value_type() {
464 EvaluatorValueType::Null => true,
465 EvaluatorValueType::Bool => self.bool_value() == other.bool_value(),
466 EvaluatorValueType::Number => self.float_value() == other.float_value(),
467 EvaluatorValueType::String => self.string_value() == other.string_value(),
468 EvaluatorValueType::Array => match (self.array_len(), other.array_len()) {
469 (None, None) => true,
470 (Some(left), Some(right)) if left == right => {
471 if iterate_other {
472 other.all_array_entries(|lowercase, index, original| {
473 self.array_entry(lowercase) == Some((index, original))
474 })
475 } else {
476 self.all_array_entries(|lowercase, index, original| {
477 other.array_entry(lowercase) == Some((index, original))
478 })
479 }
480 }
481 _ => false,
482 },
483 EvaluatorValueType::Object => match (self.object_len(), other.object_len()) {
484 (None, None) => true,
485 (Some(left), Some(right)) if left == right => {
486 if iterate_other {
487 other.all_object_entries(|key, value| self.object_entry(key) == Some(value))
488 } else {
489 self.all_object_entries(|key, value| other.object_entry(key) == Some(value))
490 }
491 }
492 _ => false,
493 },
494 }
495 }
496}
497
498struct SerializedDynamicString<'a>(&'a str);
499
500impl Serialize for SerializedDynamicString<'_> {
501 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
502 where
503 S: Serializer,
504 {
505 match self.0.parse::<bool>() {
506 Ok(value) => serializer.serialize_bool(value),
507 Err(_) => serializer.serialize_str(self.0),
508 }
509 }
510}
511
512impl Serialize for EvaluatorValueRef<'_> {
513 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
514 where
515 S: Serializer,
516 {
517 let value = match *self {
518 Self::Owned(value) => return value.serialize(serializer),
519 Self::Mmap(value, _) => value,
520 };
521
522 match value.value_type {
523 ArchivedMmapEvaluatorValueType::Null => serializer.serialize_unit(),
524 ArchivedMmapEvaluatorValueType::Bool => {
525 value.bool_value.as_ref().copied().serialize(serializer)
526 }
527 ArchivedMmapEvaluatorValueType::Number => value
528 .float_value
529 .as_ref()
530 .map(|value| value.to_native())
531 .serialize(serializer),
532 ArchivedMmapEvaluatorValueType::String => {
533 let Some(hash) = value.string_value.as_ref() else {
534 return serializer.serialize_none();
535 };
536 let raw = mmap_string_for_serialization::<S>(hash.to_native())?;
537 SerializedDynamicString(raw).serialize(serializer)
538 }
539 ArchivedMmapEvaluatorValueType::Array => {
540 let Some(array) = value.array_value.as_ref() else {
541 return serializer.serialize_none();
542 };
543 let mut entries = Vec::with_capacity(array.len());
544 for (_, entry) in array.iter() {
545 let raw = mmap_string_for_serialization::<S>(entry.1.to_native())?;
546 entries.push((entry.0.to_native(), raw));
547 }
548 entries.sort_unstable_by_key(|(index, _)| *index);
549
550 let mut sequence = serializer.serialize_seq(Some(entries.len()))?;
551 for (_, raw) in entries {
552 sequence.serialize_element(raw)?;
553 }
554 sequence.end()
555 }
556 ArchivedMmapEvaluatorValueType::Object => {
557 let Some(object) = value.object_value.as_ref() else {
558 return serializer.serialize_none();
559 };
560 let mut map = serializer.serialize_map(Some(object.len()))?;
561 for (key, value) in object.iter() {
562 let key = mmap_string_for_serialization::<S>(key.to_native())?;
563 let value = mmap_string_for_serialization::<S>(value.to_native())?;
564 map.serialize_entry(key, &SerializedDynamicString(value))?;
565 }
566 map.end()
567 }
568 }
569 }
570}
571
572fn mmap_string_for_serialization<S: Serializer>(hash: u64) -> Result<&'static str, S::Error> {
573 InternedStore::get_mmap_string(hash).ok_or_else(|| {
574 serde::ser::Error::custom(format!(
575 "Interned mmap evaluator value references missing string hash {hash}"
576 ))
577 })
578}
579
580impl<'de> Deserialize<'de> for EvaluatorValue {
581 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
582 where
583 D: Deserializer<'de>,
584 {
585 let raw_value_ref: Box<RawValue> = Deserialize::deserialize(deserializer)?;
586 Ok(InternedStore::get_or_intern_evaluator_value(Cow::Owned(
587 raw_value_ref,
588 )))
589 }
590}
591
592impl Serialize for EvaluatorValue {
593 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
594 where
595 S: Serializer,
596 {
597 self.as_value_ref().serialize(serializer)
598 }
599}
600
601impl PartialEq for EvaluatorValue {
602 fn eq(&self, other: &Self) -> bool {
603 self.as_value_ref()
604 .is_equal_to_evaluator_value(other.as_value_ref())
605 }
606}
607
608#[derive(Debug, PartialEq, Eq, Clone, Copy)]
611pub enum EvaluatorValueType {
612 Null,
613
614 Bool,
615 Number,
616 String,
617 Array,
618 Object,
619}
620
621#[derive(Debug, Clone)]
622pub struct MemoizedEvaluatorValue {
623 pub value_type: EvaluatorValueType,
624 pub bool_value: Option<bool>,
625 pub float_value: Option<f64>,
626 pub string_value: Option<DynamicString>,
627 pub regex_value: Option<FancyRegex>,
628 pub timestamp_value: Option<i64>,
629 pub object_value: Option<HashMap<InternedString, DynamicString>>,
630
631 pub array_value: Option<HashMap<InternedString, (usize, InternedString)>>,
637}
638
639impl MemoizedEvaluatorValue {
640 pub fn from_raw_value(raw_value: Cow<'_, RawValue>) -> Self {
641 match serde_json::from_str(raw_value.get()) {
642 Ok(value) => value,
643 Err(e) => {
644 log_e!(
645 TAG,
646 "Failed to convert raw value to MemoizedEvaluatorValue: {}",
647 e
648 );
649 Self::null()
650 }
651 }
652 }
653}
654
655impl MemoizedEvaluatorValue {
656 pub fn new(value_type: EvaluatorValueType) -> Self {
657 Self {
658 value_type,
659 bool_value: None,
660 float_value: None,
661 string_value: None,
662 regex_value: None,
663 timestamp_value: None,
664 array_value: None,
665 object_value: None,
666 }
667 }
668
669 pub fn null() -> Self {
670 Self::new(EvaluatorValueType::Null)
671 }
672
673 pub fn compile_regex(&mut self) {
674 let str_value = match &self.string_value {
675 Some(dyn_str) => &dyn_str.value,
676 None => return,
677 };
678
679 if let Ok(regex) = FancyRegex::new(str_value) {
680 self.regex_value = Some(regex);
681 }
682 }
683
684 pub fn is_equal_to_user_value(&self, other: UserValueRef<'_>) -> bool {
685 EvaluatorValueRef::from(self).is_equal_to_user_value(other)
686 }
687
688 pub fn is_equal_to_dynamic_value(&self, other: &DynamicValue) -> bool {
689 self.is_equal_to_user_value(UserValueRef::Dynamic(other))
690 }
691}
692
693impl From<String> for MemoizedEvaluatorValue {
696 fn from(value: String) -> Self {
697 let int_value = value.parse::<i64>().ok();
698 MemoizedEvaluatorValue {
699 timestamp_value: try_parse_timestamp(&value, int_value),
700 float_value: value.parse::<f64>().ok(),
701 string_value: Some(DynamicString::from(value)),
702 ..MemoizedEvaluatorValue::new(EvaluatorValueType::String)
703 }
704 }
705}
706
707impl From<JsonValue> for MemoizedEvaluatorValue {
709 fn from(value: JsonValue) -> Self {
710 match value {
711 JsonValue::Null => MemoizedEvaluatorValue::new(EvaluatorValueType::Null),
712
713 JsonValue::Bool(b) => MemoizedEvaluatorValue {
714 bool_value: Some(b),
715 ..MemoizedEvaluatorValue::new(EvaluatorValueType::Bool)
716 },
717
718 JsonValue::Number(n) => MemoizedEvaluatorValue {
719 float_value: n.as_f64(),
720 ..MemoizedEvaluatorValue::new(EvaluatorValueType::Number)
721 },
722
723 JsonValue::String(s) => MemoizedEvaluatorValue::from(s),
724
725 JsonValue::Array(arr) => {
726 let keyed_array: HashMap<InternedString, (usize, InternedString)> = arr
727 .into_iter()
728 .enumerate()
729 .map(|(idx, val)| {
730 let str_value = match val.as_str() {
731 Some(s) => s.to_string(), None => val.to_string(), };
734
735 let interned_lowercased_str =
736 InternedString::from_string(str_value.to_lowercase());
737 let interned_str = InternedString::from_string(str_value);
738
739 (interned_lowercased_str, (idx, interned_str))
740 })
741 .collect();
742
743 MemoizedEvaluatorValue {
744 array_value: Some(keyed_array),
745 ..MemoizedEvaluatorValue::new(EvaluatorValueType::Array)
746 }
747 }
748
749 JsonValue::Object(obj) => MemoizedEvaluatorValue {
750 object_value: Some(
751 obj.into_iter()
752 .map(|(k, v)| (InternedString::from_string(k), DynamicString::from(v)))
753 .collect(),
754 ),
755 ..MemoizedEvaluatorValue::new(EvaluatorValueType::Object)
756 },
757 }
758 }
759}
760
761impl Serialize for MemoizedEvaluatorValue {
762 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
763 where
764 S: Serializer,
765 {
766 match &self.value_type {
767 EvaluatorValueType::Null => JsonValue::Null.serialize(serializer),
768 EvaluatorValueType::Bool => self.bool_value.serialize(serializer),
769 EvaluatorValueType::Number => self.float_value.serialize(serializer),
770 EvaluatorValueType::String => self.string_value.serialize(serializer),
771 EvaluatorValueType::Array => {
772 let array_map = match &self.array_value {
773 Some(a) => a,
774 None => return JsonValue::Null.serialize(serializer),
775 };
776
777 let mut entries: Vec<(usize, String)> = array_map
778 .values()
779 .map(|(idx, val)| (*idx, val.unperformant_to_string()))
780 .collect();
781 entries.sort_by_key(|(idx, _)| *idx);
782 let result: Vec<String> = entries.into_iter().map(|(_, val)| val).collect();
783
784 result.serialize(serializer)
785 }
786 EvaluatorValueType::Object => self.object_value.serialize(serializer),
787 }
788 }
789}
790
791impl<'de> Deserialize<'de> for MemoizedEvaluatorValue {
792 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
793 where
794 D: Deserializer<'de>,
795 {
796 let json_value = JsonValue::deserialize(deserializer)?;
797 Ok(MemoizedEvaluatorValue::from(json_value))
798 }
799}
800
801impl PartialEq for MemoizedEvaluatorValue {
802 fn eq(&self, other: &Self) -> bool {
803 self.value_type == other.value_type
804 && self.bool_value == other.bool_value
805 && self.float_value == other.float_value
806 && self.string_value == other.string_value
807 && self.array_value == other.array_value
808 && self.object_value == other.object_value
809 }
810}
811
812#[macro_export]
813macro_rules! test_only_make_eval_value {
814 ($x:expr) => {
815 $crate::evaluation::evaluator_value::MemoizedEvaluatorValue::from(serde_json::json!($x))
816 };
817}
818
819#[cfg(test)]
820mod tests {
821 use super::MemoizedEvaluatorValue;
822 use serde_json::json;
823
824 #[test]
825 fn serialize_array_with_case_collision_is_safe() {
826 let value = MemoizedEvaluatorValue::from(json!(["A", "a"]));
827 let serialized = serde_json::to_value(&value).expect("serialize MemoizedEvaluatorValue");
828 assert_eq!(serialized, json!(["a"]));
829 }
830}