summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serde_yaml/src/mapping.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/serde_yaml/src/mapping.rs')
-rw-r--r--third_party/rust/serde_yaml/src/mapping.rs512
1 files changed, 512 insertions, 0 deletions
diff --git a/third_party/rust/serde_yaml/src/mapping.rs b/third_party/rust/serde_yaml/src/mapping.rs
new file mode 100644
index 0000000000..89f6e413a0
--- /dev/null
+++ b/third_party/rust/serde_yaml/src/mapping.rs
@@ -0,0 +1,512 @@
+//! A YAML mapping and its iterator types.
+
+use crate::Value;
+use indexmap::IndexMap;
+use serde::{Deserialize, Deserializer, Serialize};
+use std::cmp::Ordering;
+use std::collections::hash_map::DefaultHasher;
+use std::fmt;
+use std::hash::{Hash, Hasher};
+use std::iter::FromIterator;
+use std::ops::{Index, IndexMut};
+
+/// A YAML mapping in which the keys and values are both `serde_yaml::Value`.
+#[derive(Clone, Debug, 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(&self, k: &Value) -> bool {
+ self.map.contains_key(k)
+ }
+
+ /// Returns the value corresponding to the key in the map.
+ #[inline]
+ pub fn get(&self, k: &Value) -> Option<&Value> {
+ self.map.get(k)
+ }
+
+ /// Returns the mutable reference corresponding to the key in the map.
+ #[inline]
+ pub fn get_mut(&mut self, k: &Value) -> Option<&mut Value> {
+ self.map.get_mut(k)
+ }
+
+ /// 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.
+ #[inline]
+ pub fn remove(&mut self, k: &Value) -> Option<Value> {
+ self.map.remove(k)
+ }
+
+ /// 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(),
+ }
+ }
+}
+
+#[allow(clippy::derive_hash_xor_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))
+ })
+ }
+ }
+ }
+
+ 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<'a> Index<&'a Value> for Mapping {
+ type Output = Value;
+ #[inline]
+ fn index(&self, index: &'a Value) -> &Value {
+ self.map.index(index)
+ }
+}
+
+impl<'a> IndexMut<&'a Value> for Mapping {
+ #[inline]
+ fn index_mut(&mut self, index: &'a Value) -> &mut Value {
+ self.map.index_mut(index)
+ }
+}
+
+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(),
+ }
+ }
+}
+
+/// 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()
+ }
+}
+
+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()
+ }
+
+ /// 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<V>(self, mut visitor: V) -> Result<Self::Value, V::Error>
+ where
+ V: serde::de::MapAccess<'de>,
+ {
+ let mut values = Mapping::new();
+ while let Some((k, v)) = visitor.next_entry()? {
+ values.insert(k, v);
+ }
+ Ok(values)
+ }
+ }
+
+ deserializer.deserialize_map(Visitor)
+ }
+}