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