Skip to main content

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