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}