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