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