imbl_value/lib.rs
1use imbl::Vector;
2use index::Index;
3use serde::{de::DeserializeOwned, Serialize};
4
5use std::{
6 fmt::{self, Debug, Display},
7 io,
8 sync::Arc,
9};
10
11pub mod de;
12mod from;
13pub mod in_order_map;
14pub mod index;
15pub mod macros;
16pub mod ser;
17
18#[cfg(feature = "arbitrary")]
19mod arbitrary;
20
21pub use imbl;
22pub use in_order_map::InOMap;
23pub use serde_json::Error as ErrorSource;
24pub use serde_json::Number;
25pub use yasi::InternedString;
26
27pub const NULL: Value = Value::Null;
28
29#[derive(Debug)]
30pub enum ErrorKind {
31 Serialization,
32 Deserialization,
33}
34
35#[derive(Debug)]
36pub struct Error {
37 pub kind: ErrorKind,
38 pub source: ErrorSource,
39}
40impl std::fmt::Display for Error {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 write!(f, "{:?} Error: {}", self.kind, self.source)
43 }
44}
45impl std::error::Error for Error {}
46
47/// See the [`serde_json::value` module documentation](self) for usage examples.
48#[derive(Clone)]
49#[cfg_attr(feature = "arbitrary", derive(proptest_derive::Arbitrary))]
50pub enum Value {
51 /// Represents a JSON null value.
52 ///
53 /// ```
54 /// use imbl_value::json;
55 ///
56 /// let v = json!(null);
57 /// ```
58 Null,
59
60 /// Represents a JSON boolean.
61 ///
62 /// ```
63 /// use imbl_value::json;
64 ///
65 /// let v = json!(true);
66 /// ```
67 Bool(bool),
68
69 /// Represents a JSON number, whether integer or floating point.
70 ///
71 /// ```
72 /// use imbl_value::json;
73 ///
74 /// let v = json!(12.5);
75 /// ```
76 #[cfg_attr(
77 feature = "arbitrary",
78 proptest(strategy = "arbitrary::number_strategy()")
79 )]
80 Number(Number),
81
82 /// Represents a JSON string.
83 ///
84 /// ```
85 /// use imbl_value::json;
86 ///
87 /// let v = json!("a string");
88 /// ```
89 String(Arc<String>),
90
91 /// Represents a JSON array.
92 ///
93 /// ```
94 /// use imbl_value::json;
95 ///
96 /// let v = json!(["an", "array"]);
97 /// ```
98 #[cfg_attr(
99 feature = "arbitrary",
100 proptest(strategy = "arbitrary::array_strategy()")
101 )]
102 Array(Vector<Value>),
103
104 /// Represents a JSON object.
105 ///
106 /// By default the map is backed by a BTreeMap. Enable the `preserve_order`
107 /// feature of serde_json to use IndexMap instead, which preserves
108 /// entries in the order they are inserted into the map. In particular, this
109 /// allows JSON data to be deserialized into a Value and serialized to a
110 /// string while retaining the order of map keys in the input.
111 ///
112 /// ```
113 /// use imbl_value::json;
114 ///
115 /// let v = json!({ "an": "object" });
116 /// ```
117 #[cfg_attr(
118 feature = "arbitrary",
119 proptest(strategy = "arbitrary::object_strategy()")
120 )]
121 Object(InOMap<InternedString, Value>),
122}
123
124impl Debug for Value {
125 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
126 match self {
127 Value::Null => formatter.write_str("Null"),
128 Value::Bool(boolean) => write!(formatter, "Bool({})", boolean),
129 Value::Number(number) => Debug::fmt(number, formatter),
130 Value::String(string) => write!(formatter, "String({:?})", string),
131 Value::Array(vec) => {
132 formatter.write_str("Array ")?;
133 Debug::fmt(vec, formatter)
134 }
135 Value::Object(map) => {
136 formatter.write_str("Object ")?;
137 Debug::fmt(map, formatter)
138 }
139 }
140 }
141}
142
143impl Display for Value {
144 /// Display a JSON value as a string.
145 ///
146 /// ```
147 /// use imbl_value::json;
148 ///
149 /// let json = json!({ "city": "London", "street": "10 Downing Street" });
150 ///
151 /// // Compact format:
152 /// //
153 /// // {"city":"London","street":"10 Downing Street"}
154 /// let compact = format!("{}", json);
155 /// assert_eq!(compact,
156 /// "{\"city\":\"London\",\"street\":\"10 Downing Street\"}");
157 ///
158 /// // Pretty format:
159 /// //
160 /// // {
161 /// // "city": "London",
162 /// // "street": "10 Downing Street"
163 /// // }
164 /// let pretty = format!("{:#}", json);
165 /// assert_eq!(pretty,
166 /// "{\n \"city\": \"London\",\n \"street\": \"10 Downing Street\"\n}");
167 /// ```
168 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
169 struct WriterFormatter<'a, 'b: 'a> {
170 inner: &'a mut fmt::Formatter<'b>,
171 }
172
173 impl<'a, 'b> io::Write for WriterFormatter<'a, 'b> {
174 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
175 // Safety: the serializer below only emits valid utf8 when using
176 // the default formatter.
177 let s = unsafe { String::from_utf8_unchecked(buf.to_owned()) };
178 self.inner.write_str(&s).map_err(io_error)?;
179 Ok(buf.len())
180 }
181
182 fn flush(&mut self) -> io::Result<()> {
183 Ok(())
184 }
185 }
186
187 fn io_error(_: fmt::Error) -> io::Error {
188 // Error value does not matter because Display impl just maps it
189 // back to fmt::Error.
190 io::Error::new(io::ErrorKind::Other, "fmt error")
191 }
192
193 let alternate = f.alternate();
194 let mut wr = WriterFormatter { inner: f };
195 if alternate {
196 // {:#}
197 serde_json::ser::to_writer_pretty(&mut wr, self).map_err(|_| fmt::Error)
198 } else {
199 // {}
200 serde_json::ser::to_writer(&mut wr, self).map_err(|_| fmt::Error)
201 }
202 }
203}
204
205fn parse_index(s: &str) -> Option<usize> {
206 if s.starts_with('+') || (s.starts_with('0') && s.len() != 1) {
207 return None;
208 }
209 s.parse().ok()
210}
211
212impl Value {
213 /// Index into a JSON array or map. A string index can be used to access a
214 /// value in a map, and a usize index can be used to access an element of an
215 /// array.
216 ///
217 /// Returns `None` if the type of `self` does not match the type of the
218 /// index, for example if the index is a string and `self` is an array or a
219 /// number. Also returns `None` if the given key does not exist in the map
220 /// or the given index is not within the bounds of the array.
221 ///
222 /// ```
223 /// use imbl_value::json;
224 ///
225 /// let object = json!({ "A": 65, "B": 66, "C": 67 });
226 /// assert_eq!(*object.get("A").unwrap(), json!(65));
227 ///
228 /// let array = json!([ "A", "B", "C" ]);
229 /// assert_eq!(*array.get(2).unwrap(), json!("C"));
230 ///
231 /// assert_eq!(array.get("A"), None);
232 /// ```
233 ///
234 /// Square brackets can also be used to index into a value in a more concise
235 /// way. This returns `Value::Null` in cases where `get` would have returned
236 /// `None`.
237 ///
238 /// ```
239 /// use imbl_value::json;
240 ///
241 /// let object = json!({
242 /// "A": ["a", "á", "à"],
243 /// "B": ["b", "b́"],
244 /// "C": ["c", "ć", "ć̣", "ḉ"],
245 /// });
246 /// assert_eq!(object["B"][0], json!("b"));
247 ///
248 /// assert_eq!(object["D"], json!(null));
249 /// assert_eq!(object[0]["x"]["y"]["z"], json!(null));
250 /// ```
251 pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
252 index.index_into(self)
253 }
254
255 /// Mutably index into a JSON array or map. A string index can be used to
256 /// access a value in a map, and a usize index can be used to access an
257 /// element of an array.
258 ///
259 /// Returns `None` if the type of `self` does not match the type of the
260 /// index, for example if the index is a string and `self` is an array or a
261 /// number. Also returns `None` if the given key does not exist in the map
262 /// or the given index is not within the bounds of the array.
263 ///
264 /// ```
265 /// use imbl_value::json;
266 ///
267 /// let mut object = json!({ "A": 65, "B": 66, "C": 67 });
268 /// *object.get_mut("A").unwrap() = json!(69);
269 ///
270 /// let mut array = json!([ "A", "B", "C" ]);
271 /// *array.get_mut(2).unwrap() = json!("D");
272 /// ```
273 pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Value> {
274 index.index_into_mut(self)
275 }
276
277 /// Returns true if the `Value` is an Object. Returns false otherwise.
278 ///
279 /// For any Value on which `is_object` returns true, `as_object` and
280 /// `as_object_mut` are guaranteed to return the map representation of the
281 /// object.
282 ///
283 /// ```
284 /// use imbl_value::json;
285 ///
286 /// let obj = json!({ "a": { "nested": true }, "b": ["an", "array"] });
287 ///
288 /// assert!(obj.is_object());
289 /// assert!(obj["a"].is_object());
290 ///
291 /// // array, not an object
292 /// assert!(!obj["b"].is_object());
293 /// ```
294 pub fn is_object(&self) -> bool {
295 self.as_object().is_some()
296 }
297
298 /// If the `Value` is an Object, returns the associated Map. Returns None
299 /// otherwise.
300 ///
301 /// ```
302 /// use imbl_value::json;
303 ///
304 /// let v = json!({ "a": { "nested": true }, "b": ["an", "array"] });
305 ///
306 /// // The length of `{"nested": true}` is 1 entry.
307 /// assert_eq!(v["a"].as_object().unwrap().len(), 1);
308 ///
309 /// // The array `["an", "array"]` is not an object.
310 /// assert_eq!(v["b"].as_object(), None);
311 /// ```
312 pub fn as_object(&self) -> Option<&InOMap<InternedString, Value>> {
313 match self {
314 Value::Object(map) => Some(map),
315 _ => None,
316 }
317 }
318
319 /// If the `Value` is an Object, returns the associated mutable Map.
320 /// Returns None otherwise.
321 ///
322 /// ```
323 /// use imbl_value::json;
324 ///
325 /// let mut v = json!({ "a": { "nested": true } });
326 ///
327 /// v["a"].as_object_mut().unwrap().clear();
328 /// assert_eq!(v, json!({ "a": {} }));
329 /// ```
330 pub fn as_object_mut(&mut self) -> Option<&mut InOMap<InternedString, Value>> {
331 match self {
332 Value::Object(map) => Some(map),
333 _ => None,
334 }
335 }
336
337 /// Returns true if the `Value` is an Array. Returns false otherwise.
338 ///
339 /// For any Value on which `is_array` returns true, `as_array` and
340 /// `as_array_mut` are guaranteed to return the vector representing the
341 /// array.
342 ///
343 /// ```
344 /// use imbl_value::json;
345 ///
346 /// let obj = json!({ "a": ["an", "array"], "b": { "an": "object" } });
347 ///
348 /// assert!(obj["a"].is_array());
349 ///
350 /// // an object, not an array
351 /// assert!(!obj["b"].is_array());
352 /// ```
353 pub fn is_array(&self) -> bool {
354 self.as_array().is_some()
355 }
356
357 /// If the `Value` is an Array, returns the associated vector. Returns None
358 /// otherwise.
359 ///
360 /// ```
361 /// use imbl_value::json;
362 ///
363 /// let v = json!({ "a": ["an", "array"], "b": { "an": "object" } });
364 ///
365 /// // The length of `["an", "array"]` is 2 elements.
366 /// assert_eq!(v["a"].as_array().unwrap().len(), 2);
367 ///
368 /// // The object `{"an": "object"}` is not an array.
369 /// assert_eq!(v["b"].as_array(), None);
370 /// ```
371 pub fn as_array(&self) -> Option<&Vector<Value>> {
372 match self {
373 Value::Array(array) => Some(array),
374 _ => None,
375 }
376 }
377
378 /// If the `Value` is an Array, returns the associated mutable vector.
379 /// Returns None otherwise.
380 ///
381 /// ```
382 /// use imbl_value::json;
383 ///
384 /// let mut v = json!({ "a": ["an", "array"] });
385 ///
386 /// v["a"].as_array_mut().unwrap().clear();
387 /// assert_eq!(v, json!({ "a": [] }));
388 /// ```
389 pub fn as_array_mut(&mut self) -> Option<&mut Vector<Value>> {
390 match self {
391 Value::Array(list) => Some(list),
392 _ => None,
393 }
394 }
395
396 /// Returns true if the `Value` is a String. Returns false otherwise.
397 ///
398 /// For any Value on which `is_string` returns true, `as_str` is guaranteed
399 /// to return the string slice.
400 ///
401 /// ```
402 /// use imbl_value::json;
403 ///
404 /// let v = json!({ "a": "some string", "b": false });
405 ///
406 /// assert!(v["a"].is_string());
407 ///
408 /// // The boolean `false` is not a string.
409 /// assert!(!v["b"].is_string());
410 /// ```
411 pub fn is_string(&self) -> bool {
412 self.as_str().is_some()
413 }
414
415 /// If the `Value` is a String, returns the associated str. Returns None
416 /// otherwise.
417 ///
418 /// ```
419 /// use imbl_value::json;
420 ///
421 /// let v = json!({ "a": "some string", "b": false });
422 ///
423 /// assert_eq!(v["a"].as_str(), Some("some string"));
424 ///
425 /// // The boolean `false` is not a string.
426 /// assert_eq!(v["b"].as_str(), None);
427 ///
428 /// // JSON values are printed in JSON representation, so strings are in quotes.
429 /// //
430 /// // The value is: "some string"
431 /// println!("The value is: {}", v["a"]);
432 ///
433 /// // Rust strings are printed without quotes.
434 /// //
435 /// // The value is: some string
436 /// println!("The value is: {}", v["a"].as_str().unwrap());
437 /// ```
438 pub fn as_str(&self) -> Option<&str> {
439 match self {
440 Value::String(s) => Some(s),
441 _ => None,
442 }
443 }
444
445 /// Returns true if the `Value` is a Number. Returns false otherwise.
446 ///
447 /// ```
448 /// use imbl_value::json;
449 ///
450 /// let v = json!({ "a": 1, "b": "2" });
451 ///
452 /// assert!(v["a"].is_number());
453 ///
454 /// // The string `"2"` is a string, not a number.
455 /// assert!(!v["b"].is_number());
456 /// ```
457 pub fn is_number(&self) -> bool {
458 match *self {
459 Value::Number(_) => true,
460 _ => false,
461 }
462 }
463
464 /// Returns true if the `Value` is an integer between `i64::MIN` and
465 /// `i64::MAX`.
466 ///
467 /// For any Value on which `is_i64` returns true, `as_i64` is guaranteed to
468 /// return the integer value.
469 ///
470 /// ```
471 /// use imbl_value::json;
472 ///
473 /// let big = i64::max_value() as u64 + 10;
474 /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
475 ///
476 /// assert!(v["a"].is_i64());
477 ///
478 /// // Greater than i64::MAX.
479 /// assert!(!v["b"].is_i64());
480 ///
481 /// // Numbers with a decimal point are not considered integers.
482 /// assert!(!v["c"].is_i64());
483 /// ```
484 pub fn is_i64(&self) -> bool {
485 match self {
486 Value::Number(n) => n.is_i64(),
487 _ => false,
488 }
489 }
490
491 /// Returns true if the `Value` is an integer between zero and `u64::MAX`.
492 ///
493 /// For any Value on which `is_u64` returns true, `as_u64` is guaranteed to
494 /// return the integer value.
495 ///
496 /// ```
497 /// use imbl_value::json;
498 ///
499 /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
500 ///
501 /// assert!(v["a"].is_u64());
502 ///
503 /// // Negative integer.
504 /// assert!(!v["b"].is_u64());
505 ///
506 /// // Numbers with a decimal point are not considered integers.
507 /// assert!(!v["c"].is_u64());
508 /// ```
509 pub fn is_u64(&self) -> bool {
510 match self {
511 Value::Number(n) => n.is_u64(),
512 _ => false,
513 }
514 }
515
516 /// Returns true if the `Value` is a number that can be represented by f64.
517 ///
518 /// For any Value on which `is_f64` returns true, `as_f64` is guaranteed to
519 /// return the floating point value.
520 ///
521 /// Currently this function returns true if and only if both `is_i64` and
522 /// `is_u64` return false but this is not a guarantee in the future.
523 ///
524 /// ```
525 /// use imbl_value::json;
526 ///
527 /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
528 ///
529 /// assert!(v["a"].is_f64());
530 ///
531 /// // Integers.
532 /// assert!(!v["b"].is_f64());
533 /// assert!(!v["c"].is_f64());
534 /// ```
535 pub fn is_f64(&self) -> bool {
536 match self {
537 Value::Number(n) => n.is_f64(),
538 _ => false,
539 }
540 }
541
542 /// If the `Value` is an integer, represent it as i64 if possible. Returns
543 /// None otherwise.
544 ///
545 /// ```
546 /// use imbl_value::json;
547 ///
548 /// let big = i64::max_value() as u64 + 10;
549 /// let v = json!({ "a": 64, "b": big, "c": 256.0 });
550 ///
551 /// assert_eq!(v["a"].as_i64(), Some(64));
552 /// assert_eq!(v["b"].as_i64(), None);
553 /// assert_eq!(v["c"].as_i64(), None);
554 /// ```
555 pub fn as_i64(&self) -> Option<i64> {
556 match self {
557 Value::Number(n) => n.as_i64(),
558 _ => None,
559 }
560 }
561
562 /// If the `Value` is an integer, represent it as u64 if possible. Returns
563 /// None otherwise.
564 ///
565 /// ```
566 /// use imbl_value::json;
567 ///
568 /// let v = json!({ "a": 64, "b": -64, "c": 256.0 });
569 ///
570 /// assert_eq!(v["a"].as_u64(), Some(64));
571 /// assert_eq!(v["b"].as_u64(), None);
572 /// assert_eq!(v["c"].as_u64(), None);
573 /// ```
574 pub fn as_u64(&self) -> Option<u64> {
575 match self {
576 Value::Number(n) => n.as_u64(),
577 _ => None,
578 }
579 }
580
581 /// If the `Value` is a number, represent it as f64 if possible. Returns
582 /// None otherwise.
583 ///
584 /// ```
585 /// use imbl_value::json;
586 ///
587 /// let v = json!({ "a": 256.0, "b": 64, "c": -64 });
588 ///
589 /// assert_eq!(v["a"].as_f64(), Some(256.0));
590 /// assert_eq!(v["b"].as_f64(), Some(64.0));
591 /// assert_eq!(v["c"].as_f64(), Some(-64.0));
592 /// ```
593 pub fn as_f64(&self) -> Option<f64> {
594 match self {
595 Value::Number(n) => n.as_f64(),
596 _ => None,
597 }
598 }
599
600 /// Returns true if the `Value` is a Boolean. Returns false otherwise.
601 ///
602 /// For any Value on which `is_boolean` returns true, `as_bool` is
603 /// guaranteed to return the boolean value.
604 ///
605 /// ```
606 /// use imbl_value::json;
607 ///
608 /// let v = json!({ "a": false, "b": "false" });
609 ///
610 /// assert!(v["a"].is_boolean());
611 ///
612 /// // The string `"false"` is a string, not a boolean.
613 /// assert!(!v["b"].is_boolean());
614 /// ```
615 pub fn is_boolean(&self) -> bool {
616 self.as_bool().is_some()
617 }
618
619 /// If the `Value` is a Boolean, returns the associated bool. Returns None
620 /// otherwise.
621 ///
622 /// ```
623 /// use imbl_value::json;
624 ///
625 /// let v = json!({ "a": false, "b": "false" });
626 ///
627 /// assert_eq!(v["a"].as_bool(), Some(false));
628 ///
629 /// // The string `"false"` is a string, not a boolean.
630 /// assert_eq!(v["b"].as_bool(), None);
631 /// ```
632 pub fn as_bool(&self) -> Option<bool> {
633 match *self {
634 Value::Bool(b) => Some(b),
635 _ => None,
636 }
637 }
638
639 /// Returns true if the `Value` is a Null. Returns false otherwise.
640 ///
641 /// For any Value on which `is_null` returns true, `as_null` is guaranteed
642 /// to return `Some(())`.
643 ///
644 /// ```
645 /// use imbl_value::json;
646 ///
647 /// let v = json!({ "a": null, "b": false });
648 ///
649 /// assert!(v["a"].is_null());
650 ///
651 /// // The boolean `false` is not null.
652 /// assert!(!v["b"].is_null());
653 /// ```
654 pub fn is_null(&self) -> bool {
655 self.as_null().is_some()
656 }
657
658 /// If the `Value` is a Null, returns (). Returns None otherwise.
659 ///
660 /// ```
661 /// use imbl_value::json;
662 ///
663 /// let v = json!({ "a": null, "b": false });
664 ///
665 /// assert_eq!(v["a"].as_null(), Some(()));
666 ///
667 /// // The boolean `false` is not null.
668 /// assert_eq!(v["b"].as_null(), None);
669 /// ```
670 pub fn as_null(&self) -> Option<()> {
671 match *self {
672 Value::Null => Some(()),
673 _ => None,
674 }
675 }
676
677 /// Looks up a value by a JSON Pointer.
678 ///
679 /// JSON Pointer defines a string syntax for identifying a specific value
680 /// within a JavaScript Object Notation (JSON) document.
681 ///
682 /// A Pointer is a Unicode string with the reference tokens separated by `/`.
683 /// Inside tokens `/` is replaced by `~1` and `~` is replaced by `~0`. The
684 /// addressed value is returned and if there is no such value `None` is
685 /// returned.
686 ///
687 /// For more information read [RFC6901](https://tools.ietf.org/html/rfc6901).
688 ///
689 /// # Examples
690 ///
691 /// ```
692 /// use imbl_value::json;
693 ///
694 /// let data = json!({
695 /// "x": {
696 /// "y": ["z", "zz"]
697 /// }
698 /// });
699 ///
700 /// assert_eq!(data.pointer("/x/y/1").unwrap(), &json!("zz"));
701 /// assert_eq!(data.pointer("/a/b/c"), None);
702 /// ```
703 pub fn pointer(&self, pointer: &str) -> Option<&Value> {
704 if pointer.is_empty() {
705 return Some(self);
706 }
707 if !pointer.starts_with('/') {
708 return None;
709 }
710 pointer
711 .split('/')
712 .skip(1)
713 .map(|x| x.replace("~1", "/").replace("~0", "~"))
714 .map(Arc::new)
715 .try_fold(self, |target, token| match target {
716 Value::Object(map) => map.get(&**token),
717 Value::Array(list) => parse_index(&token).and_then(|x| list.get(x)),
718 _ => None,
719 })
720 }
721
722 /// Looks up a value by a JSON Pointer and returns a mutable reference to
723 /// that value.
724 ///
725 /// JSON Pointer defines a string syntax for identifying a specific value
726 /// within a JavaScript Object Notation (JSON) document.
727 ///
728 /// A Pointer is a Unicode string with the reference tokens separated by `/`.
729 /// Inside tokens `/` is replaced by `~1` and `~` is replaced by `~0`. The
730 /// addressed value is returned and if there is no such value `None` is
731 /// returned.
732 ///
733 /// For more information read [RFC6901](https://tools.ietf.org/html/rfc6901).
734 ///
735 /// # Example of Use
736 ///
737 /// ```
738 /// use imbl_value::Value;
739 ///
740 /// fn main() {
741 /// let s = r#"{"x": 1.0, "y": 2.0}"#;
742 /// let mut value: Value = serde_json::from_str(s).unwrap();
743 ///
744 /// // Check value using read-only pointer
745 /// assert_eq!(value.pointer("/x"), Some(&1.0.into()));
746 /// // Change value with direct assignment
747 /// *value.pointer_mut("/x").unwrap() = 1.5.into();
748 /// // Check that new value was written
749 /// assert_eq!(value.pointer("/x"), Some(&1.5.into()));
750 /// // Or change the value only if it exists
751 /// value.pointer_mut("/x").map(|v| *v = 1.5.into());
752 ///
753 /// // "Steal" ownership of a value. Can replace with any valid Value.
754 /// let old_x = value.pointer_mut("/x").map(Value::take).unwrap();
755 /// assert_eq!(old_x, 1.5);
756 /// assert_eq!(value.pointer("/x").unwrap(), &Value::Null);
757 /// }
758 /// ```
759 pub fn pointer_mut(&mut self, pointer: &str) -> Option<&mut Value> {
760 if pointer.is_empty() {
761 return Some(self);
762 }
763 if !pointer.starts_with('/') {
764 return None;
765 }
766 pointer
767 .split('/')
768 .skip(1)
769 .map(|x| x.replace("~1", "/").replace("~0", "~"))
770 .map(Arc::new)
771 .try_fold(self, |target, token| match target {
772 Value::Object(map) => map.get_mut(&**token),
773 Value::Array(list) => parse_index(&token).and_then(move |x| list.get_mut(x)),
774 _ => None,
775 })
776 }
777
778 /// Takes the value out of the `Value`, leaving a `Null` in its place.
779 ///
780 /// ```
781 /// use serde_json::json;
782 ///
783 /// let mut v = json!({ "x": "y" });
784 /// assert_eq!(v["x"].take(), json!("y"));
785 /// assert_eq!(v, json!({ "x": null }));
786 /// ```
787 pub fn take(&mut self) -> Value {
788 ::std::mem::replace(self, Value::Null)
789 }
790
791 /// Compares whether the values refer to the same data in memory
792 ///
793 /// ```
794 /// use imbl_value::json;
795 ///
796 /// let a = json!({ "x": "y" });
797 /// let b = a.clone();
798 /// let c = json!({ "x": "y" });
799 /// assert!(a.ptr_eq(&b));
800 /// assert!(!a.ptr_eq(&c));
801 /// ```
802 pub fn ptr_eq(&self, other: &Value) -> bool {
803 match (self, other) {
804 (Self::Array(a), Self::Array(b)) => a.ptr_eq(b),
805 (Self::Object(a), Self::Object(b)) => a.ptr_eq(b),
806 (Self::String(a), Self::String(b)) => Arc::ptr_eq(a, b),
807 (a, b) => a == b, // primitive - trivial comparison
808 }
809 }
810}
811
812/// The default value is `Value::Null`.
813///
814/// This is useful for handling omitted `Value` fields when deserializing.
815///
816/// # Examples
817///
818/// ```
819/// # use serde::Deserialize;
820/// use imbl_value::Value;
821///
822/// #[derive(Deserialize)]
823/// struct Settings {
824/// level: i32,
825/// #[serde(default)]
826/// extras: Value,
827/// }
828///
829/// # fn try_main() -> Result<(), serde_json::Error> {
830/// let data = r#" { "level": 42 } "#;
831/// let s: Settings = serde_json::from_str(data)?;
832///
833/// assert_eq!(s.level, 42);
834/// assert_eq!(s.extras, Value::Null);
835/// #
836/// # Ok(())
837/// # }
838/// #
839/// # try_main().unwrap()
840/// ```
841impl Default for Value {
842 fn default() -> Value {
843 Value::Null
844 }
845}
846
847impl PartialEq for Value {
848 fn eq(&self, other: &Self) -> bool {
849 match (self, other) {
850 (Value::Array(a), Value::Array(b)) => a.ptr_eq(b) || a == b,
851 (Value::Bool(a), Value::Bool(b)) => a == b,
852 (Value::Null, Value::Null) => true,
853 (Value::Number(a), Value::Number(b)) => a == b,
854
855 (Value::Object(a), Value::Object(b)) => a.ptr_eq(b) || a == b,
856 (Value::String(a), Value::String(b)) => Arc::ptr_eq(a, b) || a == b,
857 _ => false,
858 }
859 }
860}
861impl Eq for Value {}
862
863impl PartialEq<f64> for Value {
864 fn eq(&self, other: &f64) -> bool {
865 match self {
866 Value::Number(n) => n.as_f64() == Some(*other),
867 _ => false,
868 }
869 }
870}
871impl PartialEq<i64> for Value {
872 fn eq(&self, other: &i64) -> bool {
873 match self {
874 Value::Number(n) => n.as_i64() == Some(*other),
875 _ => false,
876 }
877 }
878}
879impl PartialEq<u64> for Value {
880 fn eq(&self, other: &u64) -> bool {
881 match self {
882 Value::Number(n) => n.as_u64() == Some(*other),
883 _ => false,
884 }
885 }
886}
887impl PartialEq<str> for Value {
888 fn eq(&self, other: &str) -> bool {
889 match self {
890 Value::String(s) => &**s == other,
891 _ => false,
892 }
893 }
894}
895
896pub fn to_value<T>(value: &T) -> Result<Value, Error>
897where
898 T: Serialize,
899{
900 value.serialize(ser::Serializer).map_err(|e| Error {
901 kind: ErrorKind::Serialization,
902 source: e,
903 })
904}
905
906pub fn from_value<T>(value: Value) -> Result<T, Error>
907where
908 T: DeserializeOwned,
909{
910 T::deserialize(value).map_err(|e| Error {
911 kind: ErrorKind::Deserialization,
912 source: e,
913 })
914}
915
916#[test]
917fn test_serialize_loop() {
918 let value = json!({
919 "a": "hello I'm a",
920 "b": 1,
921 "c": true,
922 "d": null,
923 "e": [123, "testing"],
924 "f": { "h": 'i'}
925 });
926 assert_eq!(
927 &serde_json::to_string(&value)
928 .unwrap(),
929 "{\"a\":\"hello I'm a\",\"b\":1,\"c\":true,\"d\":null,\"e\":[123,\"testing\"],\"f\":{\"h\":\"i\"}}"
930 );
931 assert_eq!(
932 value,
933 serde_json::from_str::<Value>(&serde_json::to_string(&value).unwrap()).unwrap(),
934 );
935
936 assert_eq!(value["f"]["h"].as_str().unwrap(), "i");
937}