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}