1use std::collections::BTreeMap;
7
8use crate::{Error, Path, PathError};
9
10#[derive(Clone, Debug, Default, PartialEq)]
21#[non_exhaustive]
22pub enum Value {
23 #[default]
25 Null,
26 Bool(bool),
28 Integer(i64),
30 Unsigned(u64),
32 Float(f64),
34 String(String),
36 Bytes(Vec<u8>),
38 Array(Vec<Value>),
40 Map(BTreeMap<String, Value>),
42}
43
44impl Value {
45 pub fn normalize(&mut self) {
47 match self {
48 Self::Unsigned(n) if *n <= i64::MAX as u64 => *self = Self::Integer(*n as i64),
49 Self::Float(f) if f.is_nan() => *f = f64::from_bits(0x7ff8_0000_0000_0000),
50 Self::Array(a) => a.iter_mut().for_each(Self::normalize),
51 Self::Map(m) => m.values_mut().for_each(Self::normalize),
52 _ => {}
53 }
54 }
55
56 pub fn semantic_eq(&self, other: &Self) -> bool {
58 match (self, other) {
59 (Self::Integer(a), Self::Unsigned(b)) | (Self::Unsigned(b), Self::Integer(a)) => {
60 *a >= 0 && *a as u64 == *b
61 }
62 (Self::Float(a), Self::Float(b)) => {
63 (a.is_nan() && b.is_nan()) || a.to_bits() == b.to_bits()
64 }
65 (Self::Array(a), Self::Array(b)) => {
66 a.len() == b.len() && a.iter().zip(b).all(|(a, b)| a.semantic_eq(b))
67 }
68 (Self::Map(a), Self::Map(b)) => {
69 a.len() == b.len()
70 && a.iter()
71 .zip(b)
72 .all(|((k, a), (l, b))| k == l && a.semantic_eq(b))
73 }
74 _ => self == other,
75 }
76 }
77
78 pub fn null() -> Self {
80 Value::Null
81 }
82
83 pub fn map() -> Self {
85 Value::Map(BTreeMap::new())
86 }
87
88 pub fn array() -> Self {
90 Value::Array(Vec::new())
91 }
92
93 pub fn is_null(&self) -> bool {
95 matches!(self, Value::Null)
96 }
97
98 pub fn is_map(&self) -> bool {
100 matches!(self, Value::Map(_))
101 }
102
103 pub fn is_array(&self) -> bool {
105 matches!(self, Value::Array(_))
106 }
107
108 pub fn get(&self, path: &Path) -> Option<&Value> {
113 let mut current = self;
114 for component in path.iter() {
115 current = match current {
116 Value::Map(map) => map.get(component)?,
117 Value::Array(arr) => {
118 let index: usize = component.parse().ok()?;
119 arr.get(index)?
120 }
121 _ => return None,
122 };
123 }
124 Some(current)
125 }
126
127 pub fn get_mut(&mut self, path: &Path) -> Option<&mut Value> {
129 let mut current = self;
130 for component in path.iter() {
131 current = match current {
132 Value::Map(map) => map.get_mut(component)?,
133 Value::Array(arr) => {
134 let index: usize = component.parse().ok()?;
135 arr.get_mut(index)?
136 }
137 _ => return None,
138 };
139 }
140 Some(current)
141 }
142
143 pub fn set(&mut self, path: &Path, value: Value) -> Result<(), Error> {
150 if path.is_empty() {
151 *self = value;
152 return Ok(());
153 }
154
155 let mut current = self;
156
157 for (i, component) in path.iter().enumerate() {
159 let is_last = i == path.len() - 1;
160
161 if is_last {
162 match current {
164 Value::Map(map) => {
165 map.insert(component.to_string(), value);
166 return Ok(());
167 }
168 Value::Array(arr) => {
169 let index: usize = component.parse().map_err(|_| {
170 Error::Path(PathError::InvalidPath {
171 message: format!("invalid array index: {}", component),
172 })
173 })?;
174 if index < arr.len() {
175 arr[index] = value;
176 } else if index == arr.len() {
177 arr.push(value);
178 } else {
179 return Err(Error::Path(PathError::InvalidPath {
180 message: format!("array index {} out of bounds", index),
181 }));
182 }
183 return Ok(());
184 }
185 _ => {
186 return Err(Error::Path(PathError::InvalidPath {
187 message: format!(
188 "cannot set child '{}' on non-container value",
189 component
190 ),
191 }));
192 }
193 }
194 } else {
195 match current {
197 Value::Map(map) => {
198 current = map
199 .entry(component.to_string())
200 .or_insert_with(|| Value::Map(BTreeMap::new()));
201 }
202 Value::Array(arr) => {
203 let index: usize = component.parse().map_err(|_| {
204 Error::Path(PathError::InvalidPath {
205 message: format!("invalid array index: {}", component),
206 })
207 })?;
208 current = arr.get_mut(index).ok_or_else(|| {
209 Error::Path(PathError::InvalidPath {
210 message: format!("array index {} out of bounds", index),
211 })
212 })?;
213 }
214 _ => {
215 return Err(Error::Path(PathError::InvalidPath {
216 message: format!(
217 "cannot navigate through non-container at '{}'",
218 component
219 ),
220 }));
221 }
222 }
223 }
224 }
225
226 Ok(())
227 }
228
229 pub fn remove(&mut self, path: &Path) -> Result<Option<Value>, Error> {
231 if path.is_empty() {
232 let old = std::mem::replace(self, Value::Null);
233 return Ok(Some(old));
234 }
235
236 let parent_path = path.slice(0, path.len() - 1);
238 let last_component = &path[path.len() - 1];
239
240 let parent = match self.get_mut(&parent_path) {
241 Some(p) => p,
242 None => return Ok(None),
243 };
244
245 match parent {
246 Value::Map(map) => Ok(map.remove(last_component)),
247 Value::Array(arr) => {
248 let index: usize = last_component.parse().map_err(|_| {
249 Error::Path(PathError::InvalidPath {
250 message: format!("invalid array index: {}", last_component),
251 })
252 })?;
253 if index < arr.len() {
254 Ok(Some(arr.remove(index)))
255 } else {
256 Ok(None)
257 }
258 }
259 _ => Ok(None),
260 }
261 }
262}
263
264impl From<bool> for Value {
267 fn from(v: bool) -> Self {
268 Value::Bool(v)
269 }
270}
271
272impl From<i64> for Value {
273 fn from(v: i64) -> Self {
274 Value::Integer(v)
275 }
276}
277
278impl From<i32> for Value {
279 fn from(v: i32) -> Self {
280 Value::Integer(v as i64)
281 }
282}
283
284impl From<f64> for Value {
285 fn from(v: f64) -> Self {
286 Value::Float(if v.is_nan() {
287 f64::from_bits(0x7ff8_0000_0000_0000)
288 } else {
289 v
290 })
291 }
292}
293
294impl From<u64> for Value {
295 fn from(v: u64) -> Self {
296 if v <= i64::MAX as u64 {
297 Self::Integer(v as i64)
298 } else {
299 Self::Unsigned(v)
300 }
301 }
302}
303
304impl From<String> for Value {
305 fn from(v: String) -> Self {
306 Value::String(v)
307 }
308}
309
310impl From<&str> for Value {
311 fn from(v: &str) -> Self {
312 Value::String(v.to_string())
313 }
314}
315
316impl From<Vec<u8>> for Value {
317 fn from(v: Vec<u8>) -> Self {
318 Value::Bytes(v)
319 }
320}
321
322impl<T: Into<Value>> From<Vec<T>> for Value {
323 fn from(v: Vec<T>) -> Self {
324 Value::Array(v.into_iter().map(Into::into).collect())
325 }
326}
327
328#[cfg(test)]
329mod tests {
330 use super::*;
331 use crate::path;
332
333 #[test]
334 fn get_nested_value() {
335 let mut value = Value::map();
336 value.set(&path!("foo/bar"), Value::from("hello")).unwrap();
337
338 assert_eq!(value.get(&path!("foo/bar")), Some(&Value::from("hello")));
339 let foo = value.get(&path!("foo")).unwrap();
341 assert!(foo.is_map());
342 assert_eq!(foo.get(&path!("bar")), Some(&Value::from("hello")));
343 assert_eq!(value.get(&path!("nonexistent")), None);
344 }
345
346 #[test]
347 fn set_creates_intermediate_maps() {
348 let mut value = Value::map();
349 value.set(&path!("a/b/c/d"), Value::from(42i64)).unwrap();
350
351 assert_eq!(value.get(&path!("a/b/c/d")), Some(&Value::from(42i64)));
352 assert!(value.get(&path!("a")).unwrap().is_map());
353 assert!(value.get(&path!("a/b")).unwrap().is_map());
354 }
355
356 #[test]
357 fn remove_works() {
358 let mut value = Value::map();
359 value.set(&path!("foo/bar"), Value::from("hello")).unwrap();
360
361 let removed = value.remove(&path!("foo/bar")).unwrap();
362 assert_eq!(removed, Some(Value::from("hello")));
363 assert_eq!(value.get(&path!("foo/bar")), None);
364
365 assert!(value.get(&path!("foo")).is_some());
367 }
368
369 #[test]
370 fn array_access_works() {
371 let mut value = Value::map();
372 value
373 .set(
374 &path!("items"),
375 Value::Array(vec![Value::from("a"), Value::from("b"), Value::from("c")]),
376 )
377 .unwrap();
378
379 assert_eq!(value.get(&path!("items/0")), Some(&Value::from("a")));
380 assert_eq!(value.get(&path!("items/1")), Some(&Value::from("b")));
381 assert_eq!(value.get(&path!("items/2")), Some(&Value::from("c")));
382 assert_eq!(value.get(&path!("items/3")), None);
383 }
384
385 #[test]
386 fn value_constructors() {
387 assert!(Value::null().is_null());
388 assert!(Value::map().is_map());
389 assert!(Value::array().is_array());
390 }
391
392 #[test]
393 fn value_default_is_null() {
394 let value = Value::default();
395 assert!(value.is_null());
396 }
397
398 #[test]
399 fn value_type_checks() {
400 assert!(Value::Null.is_null());
401 assert!(!Value::Null.is_map());
402 assert!(!Value::Null.is_array());
403
404 assert!(!Value::Bool(true).is_null());
405 assert!(!Value::Bool(true).is_map());
406 assert!(!Value::Bool(true).is_array());
407
408 assert!(Value::Map(BTreeMap::new()).is_map());
409 assert!(!Value::Map(BTreeMap::new()).is_null());
410
411 assert!(Value::Array(vec![]).is_array());
412 assert!(!Value::Array(vec![]).is_null());
413 }
414
415 #[test]
416 fn get_on_empty_path_returns_self() {
417 let value = Value::from("hello");
418 assert_eq!(value.get(&path!("")), Some(&value));
419 }
420
421 #[test]
422 fn get_on_primitive_returns_none() {
423 let value = Value::from("hello");
424 assert_eq!(value.get(&path!("foo")), None);
425 }
426
427 #[test]
428 fn get_mut_works() {
429 let mut value = Value::map();
430 value.set(&path!("foo"), Value::from("bar")).unwrap();
431
432 let foo = value.get_mut(&path!("foo")).unwrap();
433 *foo = Value::from("baz");
434
435 assert_eq!(value.get(&path!("foo")), Some(&Value::from("baz")));
436 }
437
438 #[test]
439 fn get_mut_on_array() {
440 let mut value = Value::Array(vec![Value::from(1i64), Value::from(2i64)]);
441
442 let first = value.get_mut(&path!("0")).unwrap();
443 *first = Value::from(100i64);
444
445 assert_eq!(value.get(&path!("0")), Some(&Value::from(100i64)));
446 }
447
448 #[test]
449 fn get_mut_on_primitive_returns_none() {
450 let mut value = Value::from("hello");
451 assert!(value.get_mut(&path!("foo")).is_none());
452 }
453
454 #[test]
455 fn set_at_empty_path_replaces_self() {
456 let mut value = Value::from("old");
457 value.set(&path!(""), Value::from("new")).unwrap();
458 assert_eq!(value, Value::from("new"));
459 }
460
461 #[test]
462 fn set_array_element() {
463 let mut value = Value::Array(vec![Value::from("a"), Value::from("b")]);
464 value.set(&path!("0"), Value::from("x")).unwrap();
465 assert_eq!(value.get(&path!("0")), Some(&Value::from("x")));
466 }
467
468 #[test]
469 fn set_array_append() {
470 let mut value = Value::Array(vec![Value::from("a")]);
471 value.set(&path!("1"), Value::from("b")).unwrap();
472 assert_eq!(value.get(&path!("1")), Some(&Value::from("b")));
473 }
474
475 #[test]
476 fn set_array_out_of_bounds_error() {
477 let mut value = Value::Array(vec![Value::from("a")]);
478 let result = value.set(&path!("5"), Value::from("x"));
479 assert!(result.is_err());
480 }
481
482 #[test]
483 fn set_on_primitive_error() {
484 let mut value = Value::from("hello");
485 let result = value.set(&path!("foo"), Value::from("bar"));
486 assert!(result.is_err());
487 }
488
489 #[test]
490 fn set_invalid_array_index_error() {
491 let mut value = Value::Array(vec![Value::from("a")]);
492 let result = value.set(&path!("not_a_number"), Value::from("x"));
493 assert!(result.is_err());
494 }
495
496 #[test]
497 fn set_through_array() {
498 let mut value = Value::map();
499 value
500 .set(
501 &path!("items"),
502 Value::Array(vec![Value::map(), Value::map()]),
503 )
504 .unwrap();
505 value
506 .set(&path!("items/0/name"), Value::from("first"))
507 .unwrap();
508
509 assert_eq!(
510 value.get(&path!("items/0/name")),
511 Some(&Value::from("first"))
512 );
513 }
514
515 #[test]
516 fn set_through_array_invalid_index_error() {
517 let mut value = Value::map();
518 value.set(&path!("items"), Value::Array(vec![])).unwrap();
519 let result = value.set(&path!("items/0/name"), Value::from("x"));
520 assert!(result.is_err());
521 }
522
523 #[test]
524 fn set_through_primitive_error() {
525 let mut value = Value::map();
526 value.set(&path!("foo"), Value::from("primitive")).unwrap();
527 let result = value.set(&path!("foo/bar"), Value::from("x"));
528 assert!(result.is_err());
529 }
530
531 #[test]
532 fn remove_at_empty_path() {
533 let mut value = Value::from("hello");
534 let removed = value.remove(&path!("")).unwrap();
535 assert_eq!(removed, Some(Value::from("hello")));
536 assert!(value.is_null());
537 }
538
539 #[test]
540 fn remove_nonexistent() {
541 let mut value = Value::map();
542 let removed = value.remove(&path!("nonexistent")).unwrap();
543 assert_eq!(removed, None);
544 }
545
546 #[test]
547 fn remove_from_array() {
548 let mut value = Value::Array(vec![Value::from("a"), Value::from("b"), Value::from("c")]);
549 let removed = value.remove(&path!("1")).unwrap();
550 assert_eq!(removed, Some(Value::from("b")));
551
552 match &value {
554 Value::Array(arr) => assert_eq!(arr.len(), 2),
555 _ => panic!("Expected array"),
556 }
557 }
558
559 #[test]
560 fn remove_from_array_out_of_bounds() {
561 let mut value = Value::Array(vec![Value::from("a")]);
562 let removed = value.remove(&path!("5")).unwrap();
563 assert_eq!(removed, None);
564 }
565
566 #[test]
567 fn remove_invalid_array_index_error() {
568 let mut value = Value::Array(vec![Value::from("a")]);
569 let result = value.remove(&path!("not_a_number"));
570 assert!(result.is_err());
571 }
572
573 #[test]
574 fn remove_from_primitive() {
575 let mut value = Value::map();
576 value.set(&path!("foo"), Value::from("primitive")).unwrap();
577 let removed = value.remove(&path!("foo/bar")).unwrap();
578 assert_eq!(removed, None);
579 }
580
581 #[test]
582 fn from_bool() {
583 assert_eq!(Value::from(true), Value::Bool(true));
584 assert_eq!(Value::from(false), Value::Bool(false));
585 }
586
587 #[test]
588 fn from_i64() {
589 assert_eq!(Value::from(42i64), Value::Integer(42));
590 assert_eq!(Value::from(-100i64), Value::Integer(-100));
591 }
592
593 #[test]
594 fn from_i32() {
595 assert_eq!(Value::from(42i32), Value::Integer(42));
596 }
597
598 #[test]
599 fn from_f64() {
600 assert_eq!(Value::from(2.75f64), Value::Float(2.75));
601 }
602
603 #[test]
604 fn from_string() {
605 assert_eq!(
606 Value::from("hello".to_string()),
607 Value::String("hello".to_string())
608 );
609 }
610
611 #[test]
612 fn from_str() {
613 assert_eq!(Value::from("hello"), Value::String("hello".to_string()));
614 }
615
616 #[test]
617 fn from_vec_u8() {
618 assert_eq!(Value::from(vec![1u8, 2, 3]), Value::Bytes(vec![1u8, 2, 3]));
619 }
620
621 #[test]
622 fn from_vec_values() {
623 let values: Vec<i64> = vec![1, 2, 3];
624 let value = Value::from(values);
625 match value {
626 Value::Array(arr) => {
627 assert_eq!(arr.len(), 3);
628 assert_eq!(arr[0], Value::Integer(1));
629 }
630 _ => panic!("Expected array"),
631 }
632 }
633
634 #[test]
635 fn value_equality() {
636 assert_eq!(Value::Null, Value::Null);
637 assert_eq!(Value::Bool(true), Value::Bool(true));
638 assert_ne!(Value::Bool(true), Value::Bool(false));
639 assert_eq!(Value::Integer(42), Value::Integer(42));
640 assert_ne!(Value::Integer(42), Value::Integer(43));
641 assert_eq!(
642 Value::String("a".to_string()),
643 Value::String("a".to_string())
644 );
645 assert_ne!(
646 Value::String("a".to_string()),
647 Value::String("b".to_string())
648 );
649 }
650
651 #[test]
652 fn value_clone() {
653 let original = Value::Map({
654 let mut m = BTreeMap::new();
655 m.insert("key".to_string(), Value::from("value"));
656 m
657 });
658 let cloned = original.clone();
659 assert_eq!(original, cloned);
660 }
661
662 #[test]
663 fn value_debug() {
664 let value = Value::from("test");
665 let debug = format!("{:?}", value);
666 assert!(debug.contains("String"));
667 assert!(debug.contains("test"));
668 }
669}