1#[cfg(feature = "ordered_user_data_maps")]
2use ahash::RandomState as AHashState;
3#[cfg(feature = "ordered_user_data_maps")]
4use indexmap::IndexMap;
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use serde_json::{
7 value::{to_raw_value, RawValue},
8 Number as JsonNumber, Value as JsonValue,
9};
10use std::borrow::Cow;
11#[cfg(not(feature = "ordered_user_data_maps"))]
12use std::collections::HashMap;
13
14use crate::{
15 hashing::ahash_str,
16 interned_string::InternedString,
17 log_w,
18 value_parsing::{maybe_parse_f64, maybe_parse_i64, try_parse_timestamp},
19 DynamicValue,
20};
21
22const TAG: &str = "UserValue";
23
24lazy_static::lazy_static! {
25 static ref TRUE_HASH: u64 = ahash_str("true");
26 static ref FALSE_HASH: u64 = ahash_str("false");
27}
28
29#[cfg(feature = "ordered_user_data_maps")]
30pub type UserValueMap = IndexMap<String, UserValue, AHashState>;
31#[cfg(not(feature = "ordered_user_data_maps"))]
32pub type UserValueMap = HashMap<String, UserValue>;
33
34#[derive(Clone, Debug, PartialEq)]
35pub struct UserString {
36 pub value: InternedString,
37 pub lowercased_value: InternedString,
38 pub int_value: Option<i64>,
39 pub float_value: Option<f64>,
40 pub timestamp_value: Option<i64>,
41}
42
43impl UserString {
44 pub fn new(value: String) -> Self {
45 let int_value = maybe_parse_i64(&value);
46 let float_value = maybe_parse_f64(&value);
47 let timestamp_value = try_parse_timestamp(&value, int_value);
48 let value = InternedString::from_string_uninterned(value);
49 let lowercased_value = if value.as_str().bytes().any(|byte| byte.is_ascii_uppercase()) {
50 InternedString::from_string_uninterned(value.as_str().to_lowercase())
51 } else {
52 value.clone()
53 };
54
55 Self {
56 int_value,
57 float_value,
58 timestamp_value,
59 value,
60 lowercased_value,
61 }
62 }
63}
64
65#[derive(Clone, Debug)]
70pub enum UserValue {
71 Null,
72 Bool(bool),
73 Int {
74 value: i128,
75 string_value: String,
76 },
77 Float {
78 value: f64,
79 int_value: Option<i64>,
80 string_value: String,
81 hash_string: String,
82 },
83 String(UserString),
84 Array {
85 values: Vec<UserValue>,
86 string_value: UserString,
87 },
88 Object {
89 values: UserValueMap,
90 serialized_value: Box<RawValue>,
91 },
92}
93
94impl PartialEq for UserValue {
95 fn eq(&self, other: &Self) -> bool {
96 match (self, other) {
97 (Self::Null, Self::Null) => true,
98 (Self::Bool(left), Self::Bool(right)) => left == right,
99 (
100 Self::Int {
101 value: left_value,
102 string_value: left_string,
103 },
104 Self::Int {
105 value: right_value,
106 string_value: right_string,
107 },
108 ) => left_value == right_value && left_string == right_string,
109 (
110 Self::Float {
111 value: left_value,
112 int_value: left_int,
113 string_value: left_string,
114 hash_string: left_hash,
115 },
116 Self::Float {
117 value: right_value,
118 int_value: right_int,
119 string_value: right_string,
120 hash_string: right_hash,
121 },
122 ) => {
123 left_value == right_value
124 && left_int == right_int
125 && left_string == right_string
126 && left_hash == right_hash
127 }
128 (Self::String(left), Self::String(right)) => left == right,
129 (
130 Self::Array {
131 values: left_values,
132 string_value: left_string,
133 },
134 Self::Array {
135 values: right_values,
136 string_value: right_string,
137 },
138 ) => left_values == right_values && left_string == right_string,
139 (
140 Self::Object {
141 values: left_values,
142 serialized_value: left_serialized,
143 },
144 Self::Object {
145 values: right_values,
146 serialized_value: right_serialized,
147 },
148 ) => left_values == right_values && left_serialized.get() == right_serialized.get(),
149 _ => false,
150 }
151 }
152}
153
154impl UserValue {
155 #[must_use]
156 pub fn new() -> Self {
157 Self::Null
158 }
159
160 #[must_use]
161 pub fn from_string(value: impl Into<String>) -> Self {
162 Self::String(UserString::new(value.into()))
163 }
164
165 #[must_use]
166 pub fn from_bool(value: bool) -> Self {
167 Self::Bool(value)
168 }
169
170 #[must_use]
171 pub fn from_i64(value: i64) -> Self {
172 Self::from_i128(value.into())
173 }
174
175 #[must_use]
176 pub fn from_u64(value: u64) -> Self {
177 Self::from_i128(value.into())
178 }
179
180 #[must_use]
181 fn from_i128(value: i128) -> Self {
182 Self::Int {
183 value,
184 string_value: value.to_string(),
185 }
186 }
187
188 #[must_use]
189 pub fn from_f64(value: f64) -> Self {
190 let num = match JsonNumber::from_f64(value) {
191 Some(num) => num,
192 None => {
193 log_w!(
194 TAG,
195 "Failed to convert f64 to serde_json::Number: {}",
196 value
197 );
198 return Self::from_i64(value as i64);
199 }
200 };
201
202 let mut float_value = num.as_f64().unwrap_or(value);
203 let mut int_value = num.as_i64();
204 if let Some(i) = int_value {
205 float_value = i as f64;
206 } else {
207 let i = float_value as i64;
208 if i as f64 == float_value {
209 int_value = Some(i);
210 }
211 }
212
213 Self::Float {
214 value: float_value,
215 int_value,
216 string_value: float_value.to_string(),
217 hash_string: JsonValue::Number(num).to_string(),
218 }
219 }
220
221 #[must_use]
222 pub fn from_array(values: Vec<UserValue>) -> Self {
223 let serialized = serde_json::to_string(&values).unwrap_or_else(|_| "[]".to_string());
224 Self::Array {
225 values,
226 string_value: UserString::new(serialized),
227 }
228 }
229
230 #[must_use]
231 pub fn from_object(values: UserValueMap) -> Self {
232 let serialized_value = to_raw_value(&values).unwrap_or_else(|error| {
233 log_w!(TAG, "Failed to serialize object UserValue: {}", error);
234 to_raw_value(&JsonValue::Object(Default::default()))
235 .expect("empty JSON object should always serialize")
236 });
237 Self::Object {
238 values,
239 serialized_value,
240 }
241 }
242
243 #[must_use]
244 pub fn from_json_value(value: JsonValue) -> Self {
245 match value {
246 JsonValue::Null => Self::Null,
247 JsonValue::Bool(value) => Self::from_bool(value),
248 JsonValue::Number(value) => {
249 if let Some(value) = value.as_i64() {
250 Self::from_i64(value)
251 } else if let Some(value) = value.as_u64() {
252 Self::from_u64(value)
253 } else if let Some(value) = value.as_f64() {
254 Self::from_f64(value)
255 } else {
256 Self::Null
257 }
258 }
259 JsonValue::String(value) => Self::from_string(value),
260 JsonValue::Array(values) => {
261 Self::from_array(values.into_iter().map(Self::from_json_value).collect())
262 }
263 JsonValue::Object(values) => Self::from_object(
264 values
265 .into_iter()
266 .map(|(key, value)| (key, Self::from_json_value(value)))
267 .collect(),
268 ),
269 }
270 }
271
272 #[must_use]
273 pub fn hash_value(&self) -> u64 {
274 match self {
275 Self::Null => 0,
276 Self::Bool(true) => *TRUE_HASH,
277 Self::Bool(false) => *FALSE_HASH,
278 Self::Int { string_value, .. } => ahash_str(string_value),
279 Self::Float { hash_string, .. } => ahash_str(hash_string),
280 Self::String(value)
281 | Self::Array {
282 string_value: value,
283 ..
284 } => ahash_str(value.value.as_str()),
285 Self::Object {
286 serialized_value, ..
287 } => ahash_str(serialized_value.get()),
288 }
289 }
290
291 #[must_use]
292 pub fn string_value(&self) -> Option<&str> {
293 match self {
294 Self::Null | Self::Object { .. } => None,
295 Self::Bool(true) => Some("true"),
296 Self::Bool(false) => Some("false"),
297 Self::Int { string_value, .. } | Self::Float { string_value, .. } => {
298 Some(string_value.as_str())
299 }
300 Self::String(value)
301 | Self::Array {
302 string_value: value,
303 ..
304 } => Some(value.value.as_str()),
305 }
306 }
307}
308
309impl Default for UserValue {
310 fn default() -> Self {
311 Self::new()
312 }
313}
314
315impl Serialize for UserValue {
316 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
317 where
318 S: Serializer,
319 {
320 match self {
321 Self::Null => serializer.serialize_unit(),
322 Self::Bool(value) => serializer.serialize_bool(*value),
323 Self::Int { value, .. } => {
324 if let Ok(value) = i64::try_from(*value) {
325 serializer.serialize_i64(value)
326 } else if let Ok(value) = u64::try_from(*value) {
327 serializer.serialize_u64(value)
328 } else {
329 serializer.serialize_i128(*value)
330 }
331 }
332 Self::Float { value, .. } => serializer.serialize_f64(*value),
333 Self::String(value) => serializer.serialize_str(value.value.as_str()),
334 Self::Array { values, .. } => values.serialize(serializer),
335 Self::Object {
336 serialized_value, ..
337 } => serialized_value.serialize(serializer),
338 }
339 }
340}
341
342impl<'de> Deserialize<'de> for UserValue {
343 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
344 where
345 D: Deserializer<'de>,
346 {
347 Ok(Self::from_json_value(JsonValue::deserialize(deserializer)?))
348 }
349}
350
351impl From<JsonValue> for UserValue {
352 fn from(value: JsonValue) -> Self {
353 Self::from_json_value(value)
354 }
355}
356
357impl From<DynamicValue> for UserValue {
358 fn from(value: DynamicValue) -> Self {
359 Self::from_json_value(value.json_value)
360 }
361}
362
363impl From<String> for UserValue {
364 fn from(value: String) -> Self {
365 Self::from_string(value)
366 }
367}
368
369impl From<&str> for UserValue {
370 fn from(value: &str) -> Self {
371 Self::from_string(value)
372 }
373}
374
375impl From<i64> for UserValue {
376 fn from(value: i64) -> Self {
377 Self::from_i64(value)
378 }
379}
380
381impl From<i32> for UserValue {
382 fn from(value: i32) -> Self {
383 Self::from_i64(value as i64)
384 }
385}
386
387impl From<usize> for UserValue {
388 fn from(value: usize) -> Self {
389 Self::from_u64(value as u64)
390 }
391}
392
393impl From<f64> for UserValue {
394 fn from(value: f64) -> Self {
395 Self::from_f64(value)
396 }
397}
398
399impl From<bool> for UserValue {
400 fn from(value: bool) -> Self {
401 Self::from_bool(value)
402 }
403}
404
405#[derive(Clone, Copy)]
406pub enum UserValueRef<'a> {
409 Dynamic(&'a DynamicValue),
410 User(&'a UserValue),
411}
412
413impl<'a> From<&'a DynamicValue> for UserValueRef<'a> {
414 fn from(value: &'a DynamicValue) -> Self {
415 Self::Dynamic(value)
416 }
417}
418
419impl<'a> From<&'a UserValue> for UserValueRef<'a> {
420 fn from(value: &'a UserValue) -> Self {
421 Self::User(value)
422 }
423}
424
425impl<'a> UserValueRef<'a> {
426 pub fn is_null(self) -> bool {
427 match self {
428 Self::Dynamic(value) => value.null.is_some() || value.json_value.is_null(),
429 Self::User(UserValue::Null) => true,
430 Self::User(_) => false,
431 }
432 }
433
434 pub fn bool_value(self) -> Option<bool> {
435 match self {
436 Self::Dynamic(value) => value.bool_value,
437 Self::User(UserValue::Bool(value)) => Some(*value),
438 Self::User(_) => None,
439 }
440 }
441
442 pub fn int_value(self) -> Option<i64> {
443 match self {
444 Self::Dynamic(value) => value.int_value,
445 Self::User(UserValue::Int { value, .. }) => i64::try_from(*value).ok(),
446 Self::User(UserValue::Float { int_value, .. }) => *int_value,
447 Self::User(UserValue::String(value)) => value.int_value,
448 Self::User(_) => None,
449 }
450 }
451
452 pub fn float_value(self) -> Option<f64> {
453 match self {
454 Self::Dynamic(value) => value.float_value,
455 Self::User(UserValue::Int { value, .. }) => Some(*value as f64),
456 Self::User(UserValue::Float { value, .. }) => Some(*value),
457 Self::User(UserValue::String(value)) => value.float_value,
458 Self::User(_) => None,
459 }
460 }
461
462 pub fn timestamp_value(self) -> Option<i64> {
463 match self {
464 Self::Dynamic(value) => value.timestamp_value,
465 Self::User(UserValue::String(value)) => value.timestamp_value,
466 Self::User(_) => None,
467 }
468 }
469
470 pub fn string_value(self) -> Option<&'a str> {
471 match self {
472 Self::Dynamic(value) => value
473 .string_value
474 .as_ref()
475 .map(|value| value.value.as_str()),
476 Self::User(value) => value.string_value(),
477 }
478 }
479
480 pub fn lowercased_lookup_key(self) -> Option<&'a InternedString> {
481 match self {
482 Self::Dynamic(value) => value
483 .string_value
484 .as_ref()
485 .map(|value| &value.lowercased_value),
486 Self::User(UserValue::String(value)) => Some(&value.lowercased_value),
487 Self::User(UserValue::Array { string_value, .. }) => {
488 Some(&string_value.lowercased_value)
489 }
490 Self::User(_) => None,
491 }
492 }
493
494 pub fn lowercased_string_value(self) -> Option<Cow<'a, str>> {
495 match self {
496 Self::Dynamic(value) => value
497 .string_value
498 .as_ref()
499 .map(|value| Cow::Borrowed(value.lowercased_value.as_str())),
500 Self::User(UserValue::Bool(true)) => Some(Cow::Borrowed("true")),
501 Self::User(UserValue::Bool(false)) => Some(Cow::Borrowed("false")),
502 Self::User(UserValue::Int { string_value, .. }) => {
503 Some(Cow::Borrowed(string_value.as_str()))
504 }
505 Self::User(UserValue::Float { string_value, .. }) => {
506 Some(Cow::Borrowed(string_value.as_str()))
507 }
508 Self::User(UserValue::String(value)) => {
509 Some(Cow::Borrowed(value.lowercased_value.as_str()))
510 }
511 Self::User(UserValue::Array { string_value, .. }) => {
512 Some(Cow::Borrowed(string_value.lowercased_value.as_str()))
513 }
514 Self::User(UserValue::Null | UserValue::Object { .. }) => None,
515 }
516 }
517
518 pub fn serialized_value(self) -> Cow<'a, str> {
519 match self {
520 Self::Dynamic(value) => match &value.string_value {
521 Some(value) => Cow::Borrowed(value.value.as_str()),
522 None => Cow::Owned(value.json_value.to_string()),
523 },
524 Self::User(UserValue::Null) => Cow::Borrowed("null"),
525 Self::User(UserValue::Object {
526 serialized_value, ..
527 }) => Cow::Borrowed(serialized_value.get()),
528 Self::User(_) => Cow::Borrowed(self.string_value().unwrap_or_default()),
529 }
530 }
531
532 pub fn array_len(self) -> Option<usize> {
533 match self {
534 Self::Dynamic(value) => value.array_value.as_ref().map(Vec::len),
535 Self::User(UserValue::Array { values, .. }) => Some(values.len()),
536 Self::User(_) => None,
537 }
538 }
539
540 pub fn array_item(self, index: usize) -> Option<Self> {
541 match self {
542 Self::Dynamic(value) => value
543 .array_value
544 .as_ref()?
545 .get(index)
546 .map(UserValueRef::Dynamic),
547 Self::User(UserValue::Array { values, .. }) => {
548 values.get(index).map(UserValueRef::User)
549 }
550 Self::User(_) => None,
551 }
552 }
553
554 pub fn object_len(self) -> Option<usize> {
555 match self {
556 Self::Dynamic(value) => value.object_value.as_ref().map(|values| values.len()),
557 Self::User(UserValue::Object { values, .. }) => Some(values.len()),
558 Self::User(_) => None,
559 }
560 }
561
562 pub fn object_get(self, key: &str) -> Option<Self> {
563 match self {
564 Self::Dynamic(value) => value
565 .object_value
566 .as_ref()?
567 .get(key)
568 .map(UserValueRef::Dynamic),
569 Self::User(UserValue::Object { values, .. }) => values.get(key).map(UserValueRef::User),
570 Self::User(_) => None,
571 }
572 }
573}