Skip to main content

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