| //! A YAML mapping and its iterator types. | |
| use crate::{private, Value}; | |
| use indexmap::IndexMap; | |
| use serde::{Deserialize, Deserializer, Serialize}; | |
| use std::cmp::Ordering; | |
| use std::collections::hash_map::DefaultHasher; | |
| use std::fmt::{self, Display}; | |
| use std::hash::{Hash, Hasher}; | |
| use std::mem; | |
| /// A YAML mapping in which the keys and values are both `serde_yaml::Value`. | |
| #[derive(Clone, Default, Eq, PartialEq)] | |
| pub struct Mapping { | |
| map: IndexMap<Value, Value>, | |
| } | |
| impl Mapping { | |
| /// Creates an empty YAML map. | |
| #[inline] | |
| pub fn new() -> Self { | |
| Self::default() | |
| } | |
| /// Creates an empty YAML map with the given initial capacity. | |
| #[inline] | |
| pub fn with_capacity(capacity: usize) -> Self { | |
| Mapping { | |
| map: IndexMap::with_capacity(capacity), | |
| } | |
| } | |
| /// Reserves capacity for at least `additional` more elements to be inserted | |
| /// into the map. The map may reserve more space to avoid frequent | |
| /// allocations. | |
| /// | |
| /// # Panics | |
| /// | |
| /// Panics if the new allocation size overflows `usize`. | |
| #[inline] | |
| pub fn reserve(&mut self, additional: usize) { | |
| self.map.reserve(additional); | |
| } | |
| /// Shrinks the capacity of the map as much as possible. It will drop down | |
| /// as much as possible while maintaining the internal rules and possibly | |
| /// leaving some space in accordance with the resize policy. | |
| #[inline] | |
| pub fn shrink_to_fit(&mut self) { | |
| self.map.shrink_to_fit(); | |
| } | |
| /// Inserts a key-value pair into the map. If the key already existed, the | |
| /// old value is returned. | |
| #[inline] | |
| pub fn insert(&mut self, k: Value, v: Value) -> Option<Value> { | |
| self.map.insert(k, v) | |
| } | |
| /// Checks if the map contains the given key. | |
| #[inline] | |
| pub fn contains_key<I: Index>(&self, index: I) -> bool { | |
| index.is_key_into(self) | |
| } | |
| /// Returns the value corresponding to the key in the map. | |
| #[inline] | |
| pub fn get<I: Index>(&self, index: I) -> Option<&Value> { | |
| index.index_into(self) | |
| } | |
| /// Returns the mutable reference corresponding to the key in the map. | |
| #[inline] | |
| pub fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut Value> { | |
| index.index_into_mut(self) | |
| } | |
| /// Gets the given key's corresponding entry in the map for insertion and/or | |
| /// in-place manipulation. | |
| #[inline] | |
| pub fn entry(&mut self, k: Value) -> Entry { | |
| match self.map.entry(k) { | |
| indexmap::map::Entry::Occupied(occupied) => Entry::Occupied(OccupiedEntry { occupied }), | |
| indexmap::map::Entry::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant }), | |
| } | |
| } | |
| /// Removes and returns the value corresponding to the key from the map. | |
| /// | |
| /// This is equivalent to [`.swap_remove(index)`][Self::swap_remove], | |
| /// replacing this entry's position with the last element. If you need to | |
| /// preserve the relative order of the keys in the map, use | |
| /// [`.shift_remove(key)`][Self::shift_remove] instead. | |
| #[inline] | |
| pub fn remove<I: Index>(&mut self, index: I) -> Option<Value> { | |
| self.swap_remove(index) | |
| } | |
| /// Remove and return the key-value pair. | |
| /// | |
| /// This is equivalent to [`.swap_remove_entry(index)`][Self::swap_remove_entry], | |
| /// replacing this entry's position with the last element. If you need to | |
| /// preserve the relative order of the keys in the map, use | |
| /// [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead. | |
| #[inline] | |
| pub fn remove_entry<I: Index>(&mut self, index: I) -> Option<(Value, Value)> { | |
| self.swap_remove_entry(index) | |
| } | |
| /// Removes and returns the value corresponding to the key from the map. | |
| /// | |
| /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the | |
| /// last element of the map and popping it off. This perturbs the position | |
| /// of what used to be the last element! | |
| #[inline] | |
| pub fn swap_remove<I: Index>(&mut self, index: I) -> Option<Value> { | |
| index.swap_remove_from(self) | |
| } | |
| /// Remove and return the key-value pair. | |
| /// | |
| /// Like [`Vec::swap_remove`], the entry is removed by swapping it with the | |
| /// last element of the map and popping it off. This perturbs the position | |
| /// of what used to be the last element! | |
| #[inline] | |
| pub fn swap_remove_entry<I: Index>(&mut self, index: I) -> Option<(Value, Value)> { | |
| index.swap_remove_entry_from(self) | |
| } | |
| /// Removes and returns the value corresponding to the key from the map. | |
| /// | |
| /// Like [`Vec::remove`], the entry is removed by shifting all of the | |
| /// elements that follow it, preserving their relative order. This perturbs | |
| /// the index of all of those elements! | |
| #[inline] | |
| pub fn shift_remove<I: Index>(&mut self, index: I) -> Option<Value> { | |
| index.shift_remove_from(self) | |
| } | |
| /// Remove and return the key-value pair. | |
| /// | |
| /// Like [`Vec::remove`], the entry is removed by shifting all of the | |
| /// elements that follow it, preserving their relative order. This perturbs | |
| /// the index of all of those elements! | |
| #[inline] | |
| pub fn shift_remove_entry<I: Index>(&mut self, index: I) -> Option<(Value, Value)> { | |
| index.shift_remove_entry_from(self) | |
| } | |
| /// Scan through each key-value pair in the map and keep those where the | |
| /// closure `keep` returns true. | |
| #[inline] | |
| pub fn retain<F>(&mut self, keep: F) | |
| where | |
| F: FnMut(&Value, &mut Value) -> bool, | |
| { | |
| self.map.retain(keep); | |
| } | |
| /// Returns the maximum number of key-value pairs the map can hold without | |
| /// reallocating. | |
| #[inline] | |
| pub fn capacity(&self) -> usize { | |
| self.map.capacity() | |
| } | |
| /// Returns the number of key-value pairs in the map. | |
| #[inline] | |
| pub fn len(&self) -> usize { | |
| self.map.len() | |
| } | |
| /// Returns whether the map is currently empty. | |
| #[inline] | |
| pub fn is_empty(&self) -> bool { | |
| self.map.is_empty() | |
| } | |
| /// Clears the map of all key-value pairs. | |
| #[inline] | |
| pub fn clear(&mut self) { | |
| self.map.clear(); | |
| } | |
| /// Returns a double-ended iterator visiting all key-value pairs in order of | |
| /// insertion. Iterator element type is `(&'a Value, &'a Value)`. | |
| #[inline] | |
| pub fn iter(&self) -> Iter { | |
| Iter { | |
| iter: self.map.iter(), | |
| } | |
| } | |
| /// Returns a double-ended iterator visiting all key-value pairs in order of | |
| /// insertion. Iterator element type is `(&'a Value, &'a mut ValuE)`. | |
| #[inline] | |
| pub fn iter_mut(&mut self) -> IterMut { | |
| IterMut { | |
| iter: self.map.iter_mut(), | |
| } | |
| } | |
| /// Return an iterator over the keys of the map. | |
| pub fn keys(&self) -> Keys { | |
| Keys { | |
| iter: self.map.keys(), | |
| } | |
| } | |
| /// Return an owning iterator over the keys of the map. | |
| pub fn into_keys(self) -> IntoKeys { | |
| IntoKeys { | |
| iter: self.map.into_keys(), | |
| } | |
| } | |
| /// Return an iterator over the values of the map. | |
| pub fn values(&self) -> Values { | |
| Values { | |
| iter: self.map.values(), | |
| } | |
| } | |
| /// Return an iterator over mutable references to the values of the map. | |
| pub fn values_mut(&mut self) -> ValuesMut { | |
| ValuesMut { | |
| iter: self.map.values_mut(), | |
| } | |
| } | |
| /// Return an owning iterator over the values of the map. | |
| pub fn into_values(self) -> IntoValues { | |
| IntoValues { | |
| iter: self.map.into_values(), | |
| } | |
| } | |
| } | |
| /// A type that can be used to index into a `serde_yaml::Mapping`. See the | |
| /// methods `get`, `get_mut`, `contains_key`, and `remove` of `Value`. | |
| /// | |
| /// This trait is sealed and cannot be implemented for types outside of | |
| /// `serde_yaml`. | |
| pub trait Index: private::Sealed { | |
| #[doc(hidden)] | |
| fn is_key_into(&self, v: &Mapping) -> bool; | |
| #[doc(hidden)] | |
| fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value>; | |
| #[doc(hidden)] | |
| fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value>; | |
| #[doc(hidden)] | |
| fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value>; | |
| #[doc(hidden)] | |
| fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>; | |
| #[doc(hidden)] | |
| fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value>; | |
| #[doc(hidden)] | |
| fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>; | |
| } | |
| struct HashLikeValue<'a>(&'a str); | |
| impl<'a> indexmap::Equivalent<Value> for HashLikeValue<'a> { | |
| fn equivalent(&self, key: &Value) -> bool { | |
| match key { | |
| Value::String(string) => self.0 == string, | |
| _ => false, | |
| } | |
| } | |
| } | |
| // NOTE: This impl must be consistent with Value's Hash impl. | |
| impl<'a> Hash for HashLikeValue<'a> { | |
| fn hash<H: Hasher>(&self, state: &mut H) { | |
| const STRING: Value = Value::String(String::new()); | |
| mem::discriminant(&STRING).hash(state); | |
| self.0.hash(state); | |
| } | |
| } | |
| impl Index for Value { | |
| fn is_key_into(&self, v: &Mapping) -> bool { | |
| v.map.contains_key(self) | |
| } | |
| fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value> { | |
| v.map.get(self) | |
| } | |
| fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { | |
| v.map.get_mut(self) | |
| } | |
| fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> { | |
| v.map.swap_remove(self) | |
| } | |
| fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { | |
| v.map.swap_remove_entry(self) | |
| } | |
| fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> { | |
| v.map.shift_remove(self) | |
| } | |
| fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { | |
| v.map.shift_remove_entry(self) | |
| } | |
| } | |
| impl Index for str { | |
| fn is_key_into(&self, v: &Mapping) -> bool { | |
| v.map.contains_key(&HashLikeValue(self)) | |
| } | |
| fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value> { | |
| v.map.get(&HashLikeValue(self)) | |
| } | |
| fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { | |
| v.map.get_mut(&HashLikeValue(self)) | |
| } | |
| fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> { | |
| v.map.swap_remove(&HashLikeValue(self)) | |
| } | |
| fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { | |
| v.map.swap_remove_entry(&HashLikeValue(self)) | |
| } | |
| fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> { | |
| v.map.shift_remove(&HashLikeValue(self)) | |
| } | |
| fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { | |
| v.map.shift_remove_entry(&HashLikeValue(self)) | |
| } | |
| } | |
| impl Index for String { | |
| fn is_key_into(&self, v: &Mapping) -> bool { | |
| self.as_str().is_key_into(v) | |
| } | |
| fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value> { | |
| self.as_str().index_into(v) | |
| } | |
| fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { | |
| self.as_str().index_into_mut(v) | |
| } | |
| fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> { | |
| self.as_str().swap_remove_from(v) | |
| } | |
| fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { | |
| self.as_str().swap_remove_entry_from(v) | |
| } | |
| fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> { | |
| self.as_str().shift_remove_from(v) | |
| } | |
| fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { | |
| self.as_str().shift_remove_entry_from(v) | |
| } | |
| } | |
| impl<T> Index for &T | |
| where | |
| T: ?Sized + Index, | |
| { | |
| fn is_key_into(&self, v: &Mapping) -> bool { | |
| (**self).is_key_into(v) | |
| } | |
| fn index_into<'a>(&self, v: &'a Mapping) -> Option<&'a Value> { | |
| (**self).index_into(v) | |
| } | |
| fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> { | |
| (**self).index_into_mut(v) | |
| } | |
| fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> { | |
| (**self).swap_remove_from(v) | |
| } | |
| fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { | |
| (**self).swap_remove_entry_from(v) | |
| } | |
| fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> { | |
| (**self).shift_remove_from(v) | |
| } | |
| fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> { | |
| (**self).shift_remove_entry_from(v) | |
| } | |
| } | |
| #[allow(clippy::derived_hash_with_manual_eq)] | |
| impl Hash for Mapping { | |
| fn hash<H: Hasher>(&self, state: &mut H) { | |
| // Hash the kv pairs in a way that is not sensitive to their order. | |
| let mut xor = 0; | |
| for (k, v) in self { | |
| let mut hasher = DefaultHasher::new(); | |
| k.hash(&mut hasher); | |
| v.hash(&mut hasher); | |
| xor ^= hasher.finish(); | |
| } | |
| xor.hash(state); | |
| } | |
| } | |
| impl PartialOrd for Mapping { | |
| fn partial_cmp(&self, other: &Self) -> Option<Ordering> { | |
| let mut self_entries = Vec::from_iter(self); | |
| let mut other_entries = Vec::from_iter(other); | |
| // Sort in an arbitrary order that is consistent with Value's PartialOrd | |
| // impl. | |
| fn total_cmp(a: &Value, b: &Value) -> Ordering { | |
| match (a, b) { | |
| (Value::Null, Value::Null) => Ordering::Equal, | |
| (Value::Null, _) => Ordering::Less, | |
| (_, Value::Null) => Ordering::Greater, | |
| (Value::Bool(a), Value::Bool(b)) => a.cmp(b), | |
| (Value::Bool(_), _) => Ordering::Less, | |
| (_, Value::Bool(_)) => Ordering::Greater, | |
| (Value::Number(a), Value::Number(b)) => a.total_cmp(b), | |
| (Value::Number(_), _) => Ordering::Less, | |
| (_, Value::Number(_)) => Ordering::Greater, | |
| (Value::String(a), Value::String(b)) => a.cmp(b), | |
| (Value::String(_), _) => Ordering::Less, | |
| (_, Value::String(_)) => Ordering::Greater, | |
| (Value::Sequence(a), Value::Sequence(b)) => iter_cmp_by(a, b, total_cmp), | |
| (Value::Sequence(_), _) => Ordering::Less, | |
| (_, Value::Sequence(_)) => Ordering::Greater, | |
| (Value::Mapping(a), Value::Mapping(b)) => { | |
| iter_cmp_by(a, b, |(ak, av), (bk, bv)| { | |
| total_cmp(ak, bk).then_with(|| total_cmp(av, bv)) | |
| }) | |
| } | |
| (Value::Mapping(_), _) => Ordering::Less, | |
| (_, Value::Mapping(_)) => Ordering::Greater, | |
| (Value::Tagged(a), Value::Tagged(b)) => a | |
| .tag | |
| .cmp(&b.tag) | |
| .then_with(|| total_cmp(&a.value, &b.value)), | |
| } | |
| } | |
| fn iter_cmp_by<I, F>(this: I, other: I, mut cmp: F) -> Ordering | |
| where | |
| I: IntoIterator, | |
| F: FnMut(I::Item, I::Item) -> Ordering, | |
| { | |
| let mut this = this.into_iter(); | |
| let mut other = other.into_iter(); | |
| loop { | |
| let x = match this.next() { | |
| None => { | |
| if other.next().is_none() { | |
| return Ordering::Equal; | |
| } else { | |
| return Ordering::Less; | |
| } | |
| } | |
| Some(val) => val, | |
| }; | |
| let y = match other.next() { | |
| None => return Ordering::Greater, | |
| Some(val) => val, | |
| }; | |
| match cmp(x, y) { | |
| Ordering::Equal => {} | |
| non_eq => return non_eq, | |
| } | |
| } | |
| } | |
| // While sorting by map key, we get to assume that no two keys are | |
| // equal, otherwise they wouldn't both be in the map. This is not a safe | |
| // assumption outside of this situation. | |
| let total_cmp = |&(a, _): &_, &(b, _): &_| total_cmp(a, b); | |
| self_entries.sort_by(total_cmp); | |
| other_entries.sort_by(total_cmp); | |
| self_entries.partial_cmp(&other_entries) | |
| } | |
| } | |
| impl<I> std::ops::Index<I> for Mapping | |
| where | |
| I: Index, | |
| { | |
| type Output = Value; | |
| #[inline] | |
| #[track_caller] | |
| fn index(&self, index: I) -> &Value { | |
| index.index_into(self).unwrap() | |
| } | |
| } | |
| impl<I> std::ops::IndexMut<I> for Mapping | |
| where | |
| I: Index, | |
| { | |
| #[inline] | |
| #[track_caller] | |
| fn index_mut(&mut self, index: I) -> &mut Value { | |
| index.index_into_mut(self).unwrap() | |
| } | |
| } | |
| impl Extend<(Value, Value)> for Mapping { | |
| #[inline] | |
| fn extend<I: IntoIterator<Item = (Value, Value)>>(&mut self, iter: I) { | |
| self.map.extend(iter); | |
| } | |
| } | |
| impl FromIterator<(Value, Value)> for Mapping { | |
| #[inline] | |
| fn from_iter<I: IntoIterator<Item = (Value, Value)>>(iter: I) -> Self { | |
| Mapping { | |
| map: IndexMap::from_iter(iter), | |
| } | |
| } | |
| } | |
| macro_rules! delegate_iterator { | |
| (($name:ident $($generics:tt)*) => $item:ty) => { | |
| impl $($generics)* Iterator for $name $($generics)* { | |
| type Item = $item; | |
| #[inline] | |
| fn next(&mut self) -> Option<Self::Item> { | |
| self.iter.next() | |
| } | |
| #[inline] | |
| fn size_hint(&self) -> (usize, Option<usize>) { | |
| self.iter.size_hint() | |
| } | |
| } | |
| impl $($generics)* ExactSizeIterator for $name $($generics)* { | |
| #[inline] | |
| fn len(&self) -> usize { | |
| self.iter.len() | |
| } | |
| } | |
| } | |
| } | |
| /// Iterator over `&serde_yaml::Mapping`. | |
| pub struct Iter<'a> { | |
| iter: indexmap::map::Iter<'a, Value, Value>, | |
| } | |
| delegate_iterator!((Iter<'a>) => (&'a Value, &'a Value)); | |
| impl<'a> IntoIterator for &'a Mapping { | |
| type Item = (&'a Value, &'a Value); | |
| type IntoIter = Iter<'a>; | |
| #[inline] | |
| fn into_iter(self) -> Self::IntoIter { | |
| Iter { | |
| iter: self.map.iter(), | |
| } | |
| } | |
| } | |
| /// Iterator over `&mut serde_yaml::Mapping`. | |
| pub struct IterMut<'a> { | |
| iter: indexmap::map::IterMut<'a, Value, Value>, | |
| } | |
| delegate_iterator!((IterMut<'a>) => (&'a Value, &'a mut Value)); | |
| impl<'a> IntoIterator for &'a mut Mapping { | |
| type Item = (&'a Value, &'a mut Value); | |
| type IntoIter = IterMut<'a>; | |
| #[inline] | |
| fn into_iter(self) -> Self::IntoIter { | |
| IterMut { | |
| iter: self.map.iter_mut(), | |
| } | |
| } | |
| } | |
| /// Iterator over `serde_yaml::Mapping` by value. | |
| pub struct IntoIter { | |
| iter: indexmap::map::IntoIter<Value, Value>, | |
| } | |
| delegate_iterator!((IntoIter) => (Value, Value)); | |
| impl IntoIterator for Mapping { | |
| type Item = (Value, Value); | |
| type IntoIter = IntoIter; | |
| #[inline] | |
| fn into_iter(self) -> Self::IntoIter { | |
| IntoIter { | |
| iter: self.map.into_iter(), | |
| } | |
| } | |
| } | |
| /// Iterator of the keys of a `&serde_yaml::Mapping`. | |
| pub struct Keys<'a> { | |
| iter: indexmap::map::Keys<'a, Value, Value>, | |
| } | |
| delegate_iterator!((Keys<'a>) => &'a Value); | |
| /// Iterator of the keys of a `serde_yaml::Mapping`. | |
| pub struct IntoKeys { | |
| iter: indexmap::map::IntoKeys<Value, Value>, | |
| } | |
| delegate_iterator!((IntoKeys) => Value); | |
| /// Iterator of the values of a `&serde_yaml::Mapping`. | |
| pub struct Values<'a> { | |
| iter: indexmap::map::Values<'a, Value, Value>, | |
| } | |
| delegate_iterator!((Values<'a>) => &'a Value); | |
| /// Iterator of the values of a `&mut serde_yaml::Mapping`. | |
| pub struct ValuesMut<'a> { | |
| iter: indexmap::map::ValuesMut<'a, Value, Value>, | |
| } | |
| delegate_iterator!((ValuesMut<'a>) => &'a mut Value); | |
| /// Iterator of the values of a `serde_yaml::Mapping`. | |
| pub struct IntoValues { | |
| iter: indexmap::map::IntoValues<Value, Value>, | |
| } | |
| delegate_iterator!((IntoValues) => Value); | |
| /// Entry for an existing key-value pair or a vacant location to insert one. | |
| pub enum Entry<'a> { | |
| /// Existing slot with equivalent key. | |
| Occupied(OccupiedEntry<'a>), | |
| /// Vacant slot (no equivalent key in the map). | |
| Vacant(VacantEntry<'a>), | |
| } | |
| /// A view into an occupied entry in a [`Mapping`]. It is part of the [`Entry`] | |
| /// enum. | |
| pub struct OccupiedEntry<'a> { | |
| occupied: indexmap::map::OccupiedEntry<'a, Value, Value>, | |
| } | |
| /// A view into a vacant entry in a [`Mapping`]. It is part of the [`Entry`] | |
| /// enum. | |
| pub struct VacantEntry<'a> { | |
| vacant: indexmap::map::VacantEntry<'a, Value, Value>, | |
| } | |
| impl<'a> Entry<'a> { | |
| /// Returns a reference to this entry's key. | |
| pub fn key(&self) -> &Value { | |
| match self { | |
| Entry::Vacant(e) => e.key(), | |
| Entry::Occupied(e) => e.key(), | |
| } | |
| } | |
| /// Ensures a value is in the entry by inserting the default if empty, and | |
| /// returns a mutable reference to the value in the entry. | |
| pub fn or_insert(self, default: Value) -> &'a mut Value { | |
| match self { | |
| Entry::Vacant(entry) => entry.insert(default), | |
| Entry::Occupied(entry) => entry.into_mut(), | |
| } | |
| } | |
| /// Ensures a value is in the entry by inserting the result of the default | |
| /// function if empty, and returns a mutable reference to the value in the | |
| /// entry. | |
| pub fn or_insert_with<F>(self, default: F) -> &'a mut Value | |
| where | |
| F: FnOnce() -> Value, | |
| { | |
| match self { | |
| Entry::Vacant(entry) => entry.insert(default()), | |
| Entry::Occupied(entry) => entry.into_mut(), | |
| } | |
| } | |
| /// Provides in-place mutable access to an occupied entry before any | |
| /// potential inserts into the map. | |
| pub fn and_modify<F>(self, f: F) -> Self | |
| where | |
| F: FnOnce(&mut Value), | |
| { | |
| match self { | |
| Entry::Occupied(mut entry) => { | |
| f(entry.get_mut()); | |
| Entry::Occupied(entry) | |
| } | |
| Entry::Vacant(entry) => Entry::Vacant(entry), | |
| } | |
| } | |
| } | |
| impl<'a> OccupiedEntry<'a> { | |
| /// Gets a reference to the key in the entry. | |
| #[inline] | |
| pub fn key(&self) -> &Value { | |
| self.occupied.key() | |
| } | |
| /// Gets a reference to the value in the entry. | |
| #[inline] | |
| pub fn get(&self) -> &Value { | |
| self.occupied.get() | |
| } | |
| /// Gets a mutable reference to the value in the entry. | |
| #[inline] | |
| pub fn get_mut(&mut self) -> &mut Value { | |
| self.occupied.get_mut() | |
| } | |
| /// Converts the entry into a mutable reference to its value. | |
| #[inline] | |
| pub fn into_mut(self) -> &'a mut Value { | |
| self.occupied.into_mut() | |
| } | |
| /// Sets the value of the entry with the `OccupiedEntry`'s key, and returns | |
| /// the entry's old value. | |
| #[inline] | |
| pub fn insert(&mut self, value: Value) -> Value { | |
| self.occupied.insert(value) | |
| } | |
| /// Takes the value of the entry out of the map, and returns it. | |
| #[inline] | |
| pub fn remove(self) -> Value { | |
| self.occupied.swap_remove() | |
| } | |
| /// Remove and return the key, value pair stored in the map for this entry. | |
| #[inline] | |
| pub fn remove_entry(self) -> (Value, Value) { | |
| self.occupied.swap_remove_entry() | |
| } | |
| } | |
| impl<'a> VacantEntry<'a> { | |
| /// Gets a reference to the key that would be used when inserting a value | |
| /// through the VacantEntry. | |
| #[inline] | |
| pub fn key(&self) -> &Value { | |
| self.vacant.key() | |
| } | |
| /// Takes ownership of the key, leaving the entry vacant. | |
| #[inline] | |
| pub fn into_key(self) -> Value { | |
| self.vacant.into_key() | |
| } | |
| /// Sets the value of the entry with the VacantEntry's key, and returns a | |
| /// mutable reference to it. | |
| #[inline] | |
| pub fn insert(self, value: Value) -> &'a mut Value { | |
| self.vacant.insert(value) | |
| } | |
| } | |
| impl Serialize for Mapping { | |
| #[inline] | |
| fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { | |
| use serde::ser::SerializeMap; | |
| let mut map_serializer = serializer.serialize_map(Some(self.len()))?; | |
| for (k, v) in self { | |
| map_serializer.serialize_entry(k, v)?; | |
| } | |
| map_serializer.end() | |
| } | |
| } | |
| impl<'de> Deserialize<'de> for Mapping { | |
| fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | |
| where | |
| D: Deserializer<'de>, | |
| { | |
| struct Visitor; | |
| impl<'de> serde::de::Visitor<'de> for Visitor { | |
| type Value = Mapping; | |
| fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| formatter.write_str("a YAML mapping") | |
| } | |
| #[inline] | |
| fn visit_unit<E>(self) -> Result<Self::Value, E> | |
| where | |
| E: serde::de::Error, | |
| { | |
| Ok(Mapping::new()) | |
| } | |
| #[inline] | |
| fn visit_map<A>(self, mut data: A) -> Result<Self::Value, A::Error> | |
| where | |
| A: serde::de::MapAccess<'de>, | |
| { | |
| let mut mapping = Mapping::new(); | |
| while let Some(key) = data.next_key()? { | |
| match mapping.entry(key) { | |
| Entry::Occupied(entry) => { | |
| return Err(serde::de::Error::custom(DuplicateKeyError { entry })); | |
| } | |
| Entry::Vacant(entry) => { | |
| let value = data.next_value()?; | |
| entry.insert(value); | |
| } | |
| } | |
| } | |
| Ok(mapping) | |
| } | |
| } | |
| deserializer.deserialize_map(Visitor) | |
| } | |
| } | |
| struct DuplicateKeyError<'a> { | |
| entry: OccupiedEntry<'a>, | |
| } | |
| impl<'a> Display for DuplicateKeyError<'a> { | |
| fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { | |
| formatter.write_str("duplicate entry ")?; | |
| match self.entry.key() { | |
| Value::Null => formatter.write_str("with null key"), | |
| Value::Bool(boolean) => write!(formatter, "with key `{}`", boolean), | |
| Value::Number(number) => write!(formatter, "with key {}", number), | |
| Value::String(string) => write!(formatter, "with key {:?}", string), | |
| Value::Sequence(_) | Value::Mapping(_) | Value::Tagged(_) => { | |
| formatter.write_str("in YAML map") | |
| } | |
| } | |
| } | |
| } |