serde_yaml/value/
mod.rs

1//! The Value enum, a loosely typed way of representing any valid YAML value.
2
3mod de;
4mod debug;
5mod from;
6mod index;
7mod partial_eq;
8mod ser;
9pub(crate) mod tagged;
10
11use crate::error::{
12  self,
13  Error,
14  ErrorImpl,
15};
16use serde::de::{
17  Deserialize,
18  DeserializeOwned,
19  IntoDeserializer,
20};
21use serde::Serialize;
22use std::hash::{
23  Hash,
24  Hasher,
25};
26use std::mem;
27
28pub use self::index::Index;
29pub use self::ser::Serializer;
30pub use self::tagged::{
31  Tag,
32  TaggedValue,
33};
34#[doc(inline)]
35pub use crate::mapping::Mapping;
36pub use crate::number::Number;
37
38/// Represents any valid YAML value.
39#[derive(Clone, PartialEq, PartialOrd)]
40pub enum Value {
41  /// Represents a YAML null value.
42  Null,
43  /// Represents a YAML boolean.
44  Bool(bool),
45  /// Represents a YAML numerical value, whether integer or floating point.
46  Number(Number),
47  /// Represents a YAML string.
48  String(String),
49  /// Represents a YAML sequence in which the elements are
50  /// `serde_yaml::Value`.
51  Sequence(Sequence),
52  /// Represents a YAML mapping in which the keys and values are both
53  /// `serde_yaml::Value`.
54  Mapping(Mapping),
55  /// A representation of YAML's `!Tag` syntax, used for enums.
56  Tagged(Box<TaggedValue>),
57}
58
59/// The default value is `Value::Null`.
60///
61/// This is useful for handling omitted `Value` fields when deserializing.
62///
63/// # Examples
64///
65/// ```
66/// # use serde_derive::Deserialize;
67/// use serde::Deserialize;
68/// use serde_yaml::Value;
69///
70/// #[derive(Deserialize)]
71/// struct Settings {
72///     level: i32,
73///     #[serde(default)]
74///     extras: Value,
75/// }
76///
77/// # fn try_main() -> Result<(), serde_yaml::Error> {
78/// let data = r#" { "level": 42 } "#;
79/// let s: Settings = serde_yaml::from_str(data)?;
80///
81/// assert_eq!(s.level, 42);
82/// assert_eq!(s.extras, Value::Null);
83/// #
84/// #     Ok(())
85/// # }
86/// #
87/// # try_main().unwrap()
88/// ```
89impl Default for Value {
90  fn default() -> Value {
91    Value::Null
92  }
93}
94
95/// A YAML sequence in which the elements are `serde_yaml::Value`.
96pub type Sequence = Vec<Value>;
97
98/// Convert a `T` into `serde_yaml::Value` which is an enum that can represent
99/// any valid YAML data.
100///
101/// This conversion can fail if `T`'s implementation of `Serialize` decides to
102/// return an error.
103///
104/// ```
105/// # use serde_yaml::Value;
106/// let val = serde_yaml::to_value("s").unwrap();
107/// assert_eq!(val, Value::String("s".to_owned()));
108/// ```
109pub fn to_value<T>(value: T) -> Result<Value, Error>
110where
111  T: Serialize,
112{
113  value.serialize(Serializer)
114}
115
116/// Interpret a `serde_yaml::Value` as an instance of type `T`.
117///
118/// This conversion can fail if the structure of the Value does not match the
119/// structure expected by `T`, for example if `T` is a struct type but the Value
120/// contains something other than a YAML map. It can also fail if the structure
121/// is correct but `T`'s implementation of `Deserialize` decides that something
122/// is wrong with the data, for example required struct fields are missing from
123/// the YAML map or some number is too big to fit in the expected primitive
124/// type.
125///
126/// ```
127/// # use serde_yaml::Value;
128/// let val = Value::String("foo".to_owned());
129/// let s: String = serde_yaml::from_value(val).unwrap();
130/// assert_eq!("foo", s);
131/// ```
132pub fn from_value<T>(value: Value) -> Result<T, Error>
133where
134  T: DeserializeOwned,
135{
136  Deserialize::deserialize(value)
137}
138
139impl Value {
140  /// Index into a YAML sequence or map. A string index can be used to access
141  /// a value in a map, and a usize index can be used to access an element of
142  /// an sequence.
143  ///
144  /// Returns `None` if the type of `self` does not match the type of the
145  /// index, for example if the index is a string and `self` is a sequence or
146  /// a number. Also returns `None` if the given key does not exist in the map
147  /// or the given index is not within the bounds of the sequence.
148  ///
149  /// ```
150  /// # fn main() -> serde_yaml::Result<()> {
151  /// use serde_yaml::Value;
152  ///
153  /// let object: Value = serde_yaml::from_str(r#"{ A: 65, B: 66, C: 67 }"#)?;
154  /// let x = object.get("A").unwrap();
155  /// assert_eq!(x, 65);
156  ///
157  /// let sequence: Value = serde_yaml::from_str(r#"[ "A", "B", "C" ]"#)?;
158  /// let x = sequence.get(2).unwrap();
159  /// assert_eq!(x, &Value::String("C".into()));
160  ///
161  /// assert_eq!(sequence.get("A"), None);
162  /// # Ok(())
163  /// # }
164  /// ```
165  ///
166  /// Square brackets can also be used to index into a value in a more concise
167  /// way. This returns `Value::Null` in cases where `get` would have returned
168  /// `None`.
169  ///
170  /// ```
171  /// # use serde_yaml::Value;
172  /// #
173  /// # fn main() -> serde_yaml::Result<()> {
174  /// let object: Value = serde_yaml::from_str(r#"
175  /// A: [a, á, à]
176  /// B: [b, b́]
177  /// C: [c, ć, ć̣, ḉ]
178  /// 42: true
179  /// "#)?;
180  /// assert_eq!(object["B"][0], Value::String("b".into()));
181  ///
182  /// assert_eq!(object[Value::String("D".into())], Value::Null);
183  /// assert_eq!(object["D"], Value::Null);
184  /// assert_eq!(object[0]["x"]["y"]["z"], Value::Null);
185  ///
186  /// assert_eq!(object[42], Value::Bool(true));
187  /// # Ok(())
188  /// # }
189  /// ```
190  pub fn get<I: Index>(&self, index: I) -> Option<&Value> {
191    index.index_into(self)
192  }
193
194  /// Index into a YAML sequence or map. A string index can be used to access
195  /// a value in a map, and a usize index can be used to access an element of
196  /// an sequence.
197  ///
198  /// Returns `None` if the type of `self` does not match the type of the
199  /// index, for example if the index is a string and `self` is a sequence or
200  /// a number. Also returns `None` if the given key does not exist in the map
201  /// or the given index is not within the bounds of the sequence.
202  pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Value> {
203    index.index_into_mut(self)
204  }
205
206  /// Returns true if the `Value` is a Null. Returns false otherwise.
207  ///
208  /// For any Value on which `is_null` returns true, `as_null` is guaranteed
209  /// to return `Some(())`.
210  ///
211  /// ```
212  /// # use serde_yaml::Value;
213  /// let v: Value = serde_yaml::from_str("null").unwrap();
214  /// assert!(v.is_null());
215  /// ```
216  ///
217  /// ```
218  /// # use serde_yaml::Value;
219  /// let v: Value = serde_yaml::from_str("false").unwrap();
220  /// assert!(!v.is_null());
221  /// ```
222  pub fn is_null(&self) -> bool {
223    if let Value::Null = self.untag_ref() {
224      true
225    } else {
226      false
227    }
228  }
229
230  /// If the `Value` is a Null, returns (). Returns None otherwise.
231  ///
232  /// ```
233  /// # use serde_yaml::Value;
234  /// let v: Value = serde_yaml::from_str("null").unwrap();
235  /// assert_eq!(v.as_null(), Some(()));
236  /// ```
237  ///
238  /// ```
239  /// # use serde_yaml::Value;
240  /// let v: Value = serde_yaml::from_str("false").unwrap();
241  /// assert_eq!(v.as_null(), None);
242  /// ```
243  pub fn as_null(&self) -> Option<()> {
244    match self.untag_ref() {
245      Value::Null => Some(()),
246      _ => None,
247    }
248  }
249
250  /// Returns true if the `Value` is a Boolean. Returns false otherwise.
251  ///
252  /// For any Value on which `is_boolean` returns true, `as_bool` is
253  /// guaranteed to return the boolean value.
254  ///
255  /// ```
256  /// # use serde_yaml::Value;
257  /// let v: Value = serde_yaml::from_str("true").unwrap();
258  /// assert!(v.is_bool());
259  /// ```
260  ///
261  /// ```
262  /// # use serde_yaml::Value;
263  /// let v: Value = serde_yaml::from_str("42").unwrap();
264  /// assert!(!v.is_bool());
265  /// ```
266  pub fn is_bool(&self) -> bool {
267    self.as_bool().is_some()
268  }
269
270  /// If the `Value` is a Boolean, returns the associated bool. Returns None
271  /// otherwise.
272  ///
273  /// ```
274  /// # use serde_yaml::Value;
275  /// let v: Value = serde_yaml::from_str("true").unwrap();
276  /// assert_eq!(v.as_bool(), Some(true));
277  /// ```
278  ///
279  /// ```
280  /// # use serde_yaml::Value;
281  /// let v: Value = serde_yaml::from_str("42").unwrap();
282  /// assert_eq!(v.as_bool(), None);
283  /// ```
284  pub fn as_bool(&self) -> Option<bool> {
285    match self.untag_ref() {
286      Value::Bool(b) => Some(*b),
287      _ => None,
288    }
289  }
290
291  /// Returns true if the `Value` is a Number. Returns false otherwise.
292  ///
293  /// ```
294  /// # use serde_yaml::Value;
295  /// let v: Value = serde_yaml::from_str("5").unwrap();
296  /// assert!(v.is_number());
297  /// ```
298  ///
299  /// ```
300  /// # use serde_yaml::Value;
301  /// let v: Value = serde_yaml::from_str("true").unwrap();
302  /// assert!(!v.is_number());
303  /// ```
304  pub fn is_number(&self) -> bool {
305    match self.untag_ref() {
306      Value::Number(_) => true,
307      _ => false,
308    }
309  }
310
311  /// Returns true if the `Value` is an integer between `i64::MIN` and
312  /// `i64::MAX`.
313  ///
314  /// For any Value on which `is_i64` returns true, `as_i64` is guaranteed to
315  /// return the integer value.
316  ///
317  /// ```
318  /// # use serde_yaml::Value;
319  /// let v: Value = serde_yaml::from_str("1337").unwrap();
320  /// assert!(v.is_i64());
321  /// ```
322  ///
323  /// ```
324  /// # use serde_yaml::Value;
325  /// let v: Value = serde_yaml::from_str("null").unwrap();
326  /// assert!(!v.is_i64());
327  /// ```
328  pub fn is_i64(&self) -> bool {
329    self.as_i64().is_some()
330  }
331
332  /// If the `Value` is an integer, represent it as i64 if possible. Returns
333  /// None otherwise.
334  ///
335  /// ```
336  /// # use serde_yaml::Value;
337  /// let v: Value = serde_yaml::from_str("1337").unwrap();
338  /// assert_eq!(v.as_i64(), Some(1337));
339  /// ```
340  ///
341  /// ```
342  /// # use serde_yaml::Value;
343  /// let v: Value = serde_yaml::from_str("false").unwrap();
344  /// assert_eq!(v.as_i64(), None);
345  /// ```
346  pub fn as_i64(&self) -> Option<i64> {
347    match self.untag_ref() {
348      Value::Number(n) => n.as_i64(),
349      _ => None,
350    }
351  }
352
353  /// Returns true if the `Value` is an integer between `u64::MIN` and
354  /// `u64::MAX`.
355  ///
356  /// For any Value on which `is_u64` returns true, `as_u64` is guaranteed to
357  /// return the integer value.
358  ///
359  /// ```
360  /// # use serde_yaml::Value;
361  /// let v: Value = serde_yaml::from_str("1337").unwrap();
362  /// assert!(v.is_u64());
363  /// ```
364  ///
365  /// ```
366  /// # use serde_yaml::Value;
367  /// let v: Value = serde_yaml::from_str("null").unwrap();
368  /// assert!(!v.is_u64());
369  /// ```
370  pub fn is_u64(&self) -> bool {
371    self.as_u64().is_some()
372  }
373
374  /// If the `Value` is an integer, represent it as u64 if possible. Returns
375  /// None otherwise.
376  ///
377  /// ```
378  /// # use serde_yaml::Value;
379  /// let v: Value = serde_yaml::from_str("1337").unwrap();
380  /// assert_eq!(v.as_u64(), Some(1337));
381  /// ```
382  ///
383  /// ```
384  /// # use serde_yaml::Value;
385  /// let v: Value = serde_yaml::from_str("false").unwrap();
386  /// assert_eq!(v.as_u64(), None);
387  /// ```
388  pub fn as_u64(&self) -> Option<u64> {
389    match self.untag_ref() {
390      Value::Number(n) => n.as_u64(),
391      _ => None,
392    }
393  }
394
395  /// Returns true if the `Value` is a number that can be represented by f64.
396  ///
397  /// For any Value on which `is_f64` returns true, `as_f64` is guaranteed to
398  /// return the floating point value.
399  ///
400  /// Currently this function returns true if and only if both `is_i64` and
401  /// `is_u64` return false but this is not a guarantee in the future.
402  ///
403  /// ```
404  /// # use serde_yaml::Value;
405  /// let v: Value = serde_yaml::from_str("256.01").unwrap();
406  /// assert!(v.is_f64());
407  /// ```
408  ///
409  /// ```
410  /// # use serde_yaml::Value;
411  /// let v: Value = serde_yaml::from_str("true").unwrap();
412  /// assert!(!v.is_f64());
413  /// ```
414  pub fn is_f64(&self) -> bool {
415    match self.untag_ref() {
416      Value::Number(n) => n.is_f64(),
417      _ => false,
418    }
419  }
420
421  /// If the `Value` is a number, represent it as f64 if possible. Returns
422  /// None otherwise.
423  ///
424  /// ```
425  /// # use serde_yaml::Value;
426  /// let v: Value = serde_yaml::from_str("13.37").unwrap();
427  /// assert_eq!(v.as_f64(), Some(13.37));
428  /// ```
429  ///
430  /// ```
431  /// # use serde_yaml::Value;
432  /// let v: Value = serde_yaml::from_str("false").unwrap();
433  /// assert_eq!(v.as_f64(), None);
434  /// ```
435  pub fn as_f64(&self) -> Option<f64> {
436    match self.untag_ref() {
437      Value::Number(i) => i.as_f64(),
438      _ => None,
439    }
440  }
441
442  /// Returns true if the `Value` is a String. Returns false otherwise.
443  ///
444  /// For any Value on which `is_string` returns true, `as_str` is guaranteed
445  /// to return the string slice.
446  ///
447  /// ```
448  /// # use serde_yaml::Value;
449  /// let v: Value = serde_yaml::from_str("'lorem ipsum'").unwrap();
450  /// assert!(v.is_string());
451  /// ```
452  ///
453  /// ```
454  /// # use serde_yaml::Value;
455  /// let v: Value = serde_yaml::from_str("42").unwrap();
456  /// assert!(!v.is_string());
457  /// ```
458  pub fn is_string(&self) -> bool {
459    self.as_str().is_some()
460  }
461
462  /// If the `Value` is a String, returns the associated str. Returns None
463  /// otherwise.
464  ///
465  /// ```
466  /// # use serde_yaml::Value;
467  /// let v: Value = serde_yaml::from_str("'lorem ipsum'").unwrap();
468  /// assert_eq!(v.as_str(), Some("lorem ipsum"));
469  /// ```
470  ///
471  /// ```
472  /// # use serde_yaml::Value;
473  /// let v: Value = serde_yaml::from_str("false").unwrap();
474  /// assert_eq!(v.as_str(), None);
475  /// ```
476  pub fn as_str(&self) -> Option<&str> {
477    match self.untag_ref() {
478      Value::String(s) => Some(s),
479      _ => None,
480    }
481  }
482
483  /// Returns true if the `Value` is a sequence. Returns false otherwise.
484  ///
485  /// ```
486  /// # use serde_yaml::Value;
487  /// let v: Value = serde_yaml::from_str("[1, 2, 3]").unwrap();
488  /// assert!(v.is_sequence());
489  /// ```
490  ///
491  /// ```
492  /// # use serde_yaml::Value;
493  /// let v: Value = serde_yaml::from_str("true").unwrap();
494  /// assert!(!v.is_sequence());
495  /// ```
496  pub fn is_sequence(&self) -> bool {
497    self.as_sequence().is_some()
498  }
499
500  /// If the `Value` is a sequence, return a reference to it if possible.
501  /// Returns None otherwise.
502  ///
503  /// ```
504  /// # use serde_yaml::{Value, Number};
505  /// let v: Value = serde_yaml::from_str("[1, 2]").unwrap();
506  /// assert_eq!(v.as_sequence(), Some(&vec![Value::Number(Number::from(1)), Value::Number(Number::from(2))]));
507  /// ```
508  ///
509  /// ```
510  /// # use serde_yaml::Value;
511  /// let v: Value = serde_yaml::from_str("false").unwrap();
512  /// assert_eq!(v.as_sequence(), None);
513  /// ```
514  pub fn as_sequence(&self) -> Option<&Sequence> {
515    match self.untag_ref() {
516      Value::Sequence(seq) => Some(seq),
517      _ => None,
518    }
519  }
520
521  /// If the `Value` is a sequence, return a mutable reference to it if
522  /// possible. Returns None otherwise.
523  ///
524  /// ```
525  /// # use serde_yaml::{Value, Number};
526  /// let mut v: Value = serde_yaml::from_str("[1]").unwrap();
527  /// let s = v.as_sequence_mut().unwrap();
528  /// s.push(Value::Number(Number::from(2)));
529  /// assert_eq!(s, &vec![Value::Number(Number::from(1)), Value::Number(Number::from(2))]);
530  /// ```
531  ///
532  /// ```
533  /// # use serde_yaml::Value;
534  /// let mut v: Value = serde_yaml::from_str("false").unwrap();
535  /// assert_eq!(v.as_sequence_mut(), None);
536  /// ```
537  pub fn as_sequence_mut(&mut self) -> Option<&mut Sequence> {
538    match self.untag_mut() {
539      Value::Sequence(seq) => Some(seq),
540      _ => None,
541    }
542  }
543
544  /// Returns true if the `Value` is a mapping. Returns false otherwise.
545  ///
546  /// ```
547  /// # use serde_yaml::Value;
548  /// let v: Value = serde_yaml::from_str("a: 42").unwrap();
549  /// assert!(v.is_mapping());
550  /// ```
551  ///
552  /// ```
553  /// # use serde_yaml::Value;
554  /// let v: Value = serde_yaml::from_str("true").unwrap();
555  /// assert!(!v.is_mapping());
556  /// ```
557  pub fn is_mapping(&self) -> bool {
558    self.as_mapping().is_some()
559  }
560
561  /// If the `Value` is a mapping, return a reference to it if possible.
562  /// Returns None otherwise.
563  ///
564  /// ```
565  /// # use serde_yaml::{Value, Mapping, Number};
566  /// let v: Value = serde_yaml::from_str("a: 42").unwrap();
567  ///
568  /// let mut expected = Mapping::new();
569  /// expected.insert(Value::String("a".into()),Value::Number(Number::from(42)));
570  ///
571  /// assert_eq!(v.as_mapping(), Some(&expected));
572  /// ```
573  ///
574  /// ```
575  /// # use serde_yaml::Value;
576  /// let v: Value = serde_yaml::from_str("false").unwrap();
577  /// assert_eq!(v.as_mapping(), None);
578  /// ```
579  pub fn as_mapping(&self) -> Option<&Mapping> {
580    match self.untag_ref() {
581      Value::Mapping(map) => Some(map),
582      _ => None,
583    }
584  }
585
586  /// If the `Value` is a mapping, return a reference to it if possible.
587  /// Returns None otherwise.
588  ///
589  /// ```
590  /// # use serde_yaml::{Value, Mapping, Number};
591  /// let mut v: Value = serde_yaml::from_str("a: 42").unwrap();
592  /// let m = v.as_mapping_mut().unwrap();
593  /// m.insert(Value::String("b".into()), Value::Number(Number::from(21)));
594  ///
595  /// let mut expected = Mapping::new();
596  /// expected.insert(Value::String("a".into()), Value::Number(Number::from(42)));
597  /// expected.insert(Value::String("b".into()), Value::Number(Number::from(21)));
598  ///
599  /// assert_eq!(m, &expected);
600  /// ```
601  ///
602  /// ```
603  /// # use serde_yaml::{Value, Mapping};
604  /// let mut v: Value = serde_yaml::from_str("false").unwrap();
605  /// assert_eq!(v.as_mapping_mut(), None);
606  /// ```
607  pub fn as_mapping_mut(&mut self) -> Option<&mut Mapping> {
608    match self.untag_mut() {
609      Value::Mapping(map) => Some(map),
610      _ => None,
611    }
612  }
613
614  /// Performs merging of `<<` keys into the surrounding mapping.
615  ///
616  /// The intended use of this in YAML is described in
617  /// <https://yaml.org/type/merge.html>.
618  ///
619  /// ```
620  /// use serde_yaml::Value;
621  ///
622  /// let config = "\
623  /// tasks:
624  ///   build: &webpack_shared
625  ///     command: webpack
626  ///     args: build
627  ///     inputs:
628  ///       - 'src/**/*'
629  ///   start:
630  ///     <<: *webpack_shared
631  ///     args: start
632  /// ";
633  ///
634  /// let mut value: Value = serde_yaml::from_str(config).unwrap();
635  /// value.apply_merge().unwrap();
636  ///
637  /// assert_eq!(value["tasks"]["start"]["command"], "webpack");
638  /// assert_eq!(value["tasks"]["start"]["args"], "start");
639  /// ```
640  pub fn apply_merge(&mut self) -> Result<(), Error> {
641    let mut stack = Vec::new();
642    stack.push(self);
643    while let Some(node) = stack.pop() {
644      match node {
645        Value::Mapping(mapping) => {
646          match mapping.remove("<<") {
647            Some(Value::Mapping(merge)) => {
648              for (k, v) in merge {
649                mapping.entry(k).or_insert(v);
650              }
651            },
652            Some(Value::Sequence(sequence)) => {
653              for value in sequence {
654                match value {
655                  Value::Mapping(merge) => {
656                    for (k, v) in merge {
657                      mapping.entry(k).or_insert(v);
658                    }
659                  },
660                  Value::Sequence(_) => {
661                    return Err(error::new(ErrorImpl::SequenceInMergeElement));
662                  },
663                  Value::Tagged(_) => {
664                    return Err(error::new(ErrorImpl::TaggedInMerge));
665                  },
666                  _unexpected => {
667                    return Err(error::new(ErrorImpl::ScalarInMergeElement));
668                  },
669                }
670              }
671            },
672            None => {},
673            Some(Value::Tagged(_)) => return Err(error::new(ErrorImpl::TaggedInMerge)),
674            Some(_unexpected) => return Err(error::new(ErrorImpl::ScalarInMerge)),
675          }
676          stack.extend(mapping.values_mut());
677        },
678        Value::Sequence(sequence) => stack.extend(sequence),
679        Value::Tagged(tagged) => stack.push(&mut tagged.value),
680        _ => {},
681      }
682    }
683    Ok(())
684  }
685}
686
687impl Eq for Value {}
688
689// NOTE: This impl must be kept consistent with HashLikeValue's Hash impl in
690// mapping.rs in order for value[str] indexing to work.
691impl Hash for Value {
692  fn hash<H: Hasher>(&self, state: &mut H) {
693    mem::discriminant(self).hash(state);
694    match self {
695      Value::Null => {},
696      Value::Bool(v) => v.hash(state),
697      Value::Number(v) => v.hash(state),
698      Value::String(v) => v.hash(state),
699      Value::Sequence(v) => v.hash(state),
700      Value::Mapping(v) => v.hash(state),
701      Value::Tagged(v) => v.hash(state),
702    }
703  }
704}
705
706impl IntoDeserializer<'_, Error> for Value {
707  type Deserializer = Self;
708
709  fn into_deserializer(self) -> Self::Deserializer {
710    self
711  }
712}