// Copyright 2017 Serde Developers // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! A map of `String` to [Value][crate::Value]. //! //! By default the map is backed by a [`BTreeMap`]. Enable the `preserve_order` //! feature of toml-rs to use [`IndexMap`] instead. //! //! [`BTreeMap`]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html //! [`IndexMap`]: https://docs.rs/indexmap #[cfg(not(feature = "preserve_order"))] use alloc::collections::{btree_map, BTreeMap}; use core::borrow::Borrow; use core::fmt::{self, Debug}; use core::hash::Hash; use core::iter::FromIterator; use core::ops; #[cfg(feature = "preserve_order")] use indexmap::{self, IndexMap}; /// Represents a TOML key/value type. pub struct Map { map: MapImpl, dotted: bool, implicit: bool, inline: bool, } #[cfg(not(feature = "preserve_order"))] type MapImpl = BTreeMap; #[cfg(all(feature = "preserve_order", not(feature = "fast_hash")))] type RandomState = std::collections::hash_map::RandomState; #[cfg(all(feature = "preserve_order", feature = "fast_hash"))] type RandomState = foldhash::fast::RandomState; #[cfg(feature = "preserve_order")] type MapImpl = IndexMap; impl Map where K: Ord + Hash, { /// Makes a new empty Map. #[inline] pub fn new() -> Self { Self { #[cfg(feature = "preserve_order")] map: MapImpl::with_hasher(RandomState::default()), #[cfg(not(feature = "preserve_order"))] map: MapImpl::new(), dotted: false, implicit: false, inline: false, } } #[cfg(not(feature = "preserve_order"))] /// Makes a new empty Map with the given initial capacity. #[inline] pub fn with_capacity(capacity: usize) -> Self { // does not support with_capacity let _ = capacity; Self::new() } #[cfg(feature = "preserve_order")] /// Makes a new empty Map with the given initial capacity. #[inline] pub fn with_capacity(capacity: usize) -> Self { Self { map: IndexMap::with_capacity_and_hasher(capacity, RandomState::default()), dotted: false, implicit: false, inline: false, } } /// Clears the map, removing all values. #[inline] pub fn clear(&mut self) { self.map.clear(); } /// Returns a reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. #[inline] pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Ord + Eq + Hash + ?Sized, { self.map.get(key) } /// Returns true if the map contains a value for the specified key. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. #[inline] pub fn contains_key(&self, key: &Q) -> bool where K: Borrow, Q: Ord + Eq + Hash + ?Sized, { self.map.contains_key(key) } /// Returns a mutable reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. #[inline] pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: Ord + Eq + Hash + ?Sized, { self.map.get_mut(key) } /// Returns the key-value pair matching the given key. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. #[inline] pub fn get_key_value(&self, key: &Q) -> Option<(&K, &V)> where K: Borrow, Q: ?Sized + Ord + Eq + Hash, { self.map.get_key_value(key) } /// Inserts a key-value pair into the map. /// /// If the map did not have this key present, `None` is returned. /// /// If the map did have this key present, the value is updated, and the old /// value is returned. The key is not updated, though; this matters for /// types that can be `==` without being identical. #[inline] pub fn insert(&mut self, k: K, v: V) -> Option { self.map.insert(k, v) } /// Removes a key from the map, returning the value at the key if the key /// was previously in the map. /// /// The key may be any borrowed form of the map's key type, but the ordering /// on the borrowed form *must* match the ordering on the key type. #[inline] pub fn remove(&mut self, key: &Q) -> Option where K: Borrow, Q: Ord + Eq + Hash + ?Sized, { #[cfg(not(feature = "preserve_order"))] { self.map.remove(key) } #[cfg(feature = "preserve_order")] { self.map.shift_remove(key) } } /// Removes a key from the map, returning the stored key and value if the key was previously in the map. #[inline] pub fn remove_entry(&mut self, key: &Q) -> Option<(K, V)> where K: Borrow, Q: Ord + Eq + Hash + ?Sized, { #[cfg(not(feature = "preserve_order"))] { self.map.remove_entry(key) } #[cfg(feature = "preserve_order")] { self.map.shift_remove_entry(key) } } /// Retains only the elements specified by the `keep` predicate. /// /// In other words, remove all pairs `(k, v)` for which `keep(&k, &mut v)` /// returns `false`. /// /// The elements are visited in iteration order. #[inline] pub fn retain(&mut self, mut keep: F) where K: AsRef, F: FnMut(&str, &mut V) -> bool, { self.map.retain(|key, value| keep(key.as_ref(), value)); } /// Gets the given key's corresponding entry in the map for in-place /// manipulation. pub fn entry(&mut self, key: S) -> Entry<'_, K, V> where S: Into, { #[cfg(not(feature = "preserve_order"))] use alloc::collections::btree_map::Entry as EntryImpl; #[cfg(feature = "preserve_order")] use indexmap::map::Entry as EntryImpl; match self.map.entry(key.into()) { EntryImpl::Vacant(vacant) => Entry::Vacant(VacantEntry { vacant }), EntryImpl::Occupied(occupied) => Entry::Occupied(OccupiedEntry { occupied }), } } /// Returns the number of elements in the map. #[inline] pub fn len(&self) -> usize { self.map.len() } /// Returns true if the map contains no elements. #[inline] pub fn is_empty(&self) -> bool { self.map.is_empty() } /// Gets an iterator over the entries of the map. #[inline] pub fn iter(&self) -> Iter<'_, K, V> { Iter { iter: self.map.iter(), } } /// Gets a mutable iterator over the entries of the map. #[inline] pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { IterMut { iter: self.map.iter_mut(), } } /// Gets an iterator over the keys of the map. #[inline] pub fn keys(&self) -> Keys<'_, K, V> { Keys { iter: self.map.keys(), } } /// Gets an iterator over the values of the map. #[inline] pub fn values(&self) -> Values<'_, K, V> { Values { iter: self.map.values(), } } /// Scan through each key-value pair in the map and keep those where the /// closure `keep` returns `true`. /// /// The elements are visited in order, and remaining elements keep their /// order. /// /// Computes in **O(n)** time (average). #[allow(unused_mut)] pub(crate) fn mut_entries(&mut self, mut op: F) where F: FnMut(&mut K, &mut V), { #[cfg(feature = "preserve_order")] { use indexmap::map::MutableKeys as _; for (key, value) in self.map.iter_mut2() { op(key, value); } } #[cfg(not(feature = "preserve_order"))] { self.map = core::mem::take(&mut self.map) .into_iter() .map(move |(mut k, mut v)| { op(&mut k, &mut v); (k, v) }) .collect(); } } } impl Map where K: Ord, { pub(crate) fn is_dotted(&self) -> bool { self.dotted } pub(crate) fn is_implicit(&self) -> bool { self.implicit } pub(crate) fn is_inline(&self) -> bool { self.inline } pub(crate) fn set_implicit(&mut self, yes: bool) { self.implicit = yes; } pub(crate) fn set_dotted(&mut self, yes: bool) { self.dotted = yes; } pub(crate) fn set_inline(&mut self, yes: bool) { self.inline = yes; } } impl Default for Map where K: Ord + Hash, { #[inline] fn default() -> Self { Self::new() } } impl Clone for Map { #[inline] fn clone(&self) -> Self { Self { map: self.map.clone(), dotted: self.dotted, implicit: self.implicit, inline: self.inline, } } } impl PartialEq for Map { #[inline] fn eq(&self, other: &Self) -> bool { self.map.eq(&other.map) } } /// Access an element of this map. Panics if the given key is not present in the /// map. impl ops::Index<&Q> for Map where K: Borrow + Ord, Q: Ord + Eq + Hash + ?Sized, { type Output = V; fn index(&self, index: &Q) -> &V { self.map.index(index) } } /// Mutably access an element of this map. Panics if the given key is not /// present in the map. impl ops::IndexMut<&Q> for Map where K: Borrow + Ord, Q: Ord + Eq + Hash + ?Sized, { fn index_mut(&mut self, index: &Q) -> &mut V { self.map.get_mut(index).expect("no entry found for key") } } impl Debug for Map { #[inline] fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { self.map.fmt(formatter) } } impl FromIterator<(K, V)> for Map { fn from_iter(iter: T) -> Self where T: IntoIterator, { Self { map: FromIterator::from_iter(iter), dotted: false, implicit: false, inline: false, } } } impl Extend<(K, V)> for Map { fn extend(&mut self, iter: T) where T: IntoIterator, { self.map.extend(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.iter.next() } #[inline] fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } impl $($generics)* DoubleEndedIterator for $name $($generics)* { #[inline] fn next_back(&mut self) -> Option { self.iter.next_back() } } impl $($generics)* ExactSizeIterator for $name $($generics)* { #[inline] fn len(&self) -> usize { self.iter.len() } } } } ////////////////////////////////////////////////////////////////////////////// /// A view into a single entry in a map, which may either be vacant or occupied. /// This enum is constructed from the [`entry`] method on [`Map`]. /// /// [`entry`]: struct.Map.html#method.entry /// [`Map`]: struct.Map.html pub enum Entry<'a, K, V> { /// A vacant Entry. Vacant(VacantEntry<'a, K, V>), /// An occupied Entry. Occupied(OccupiedEntry<'a, K, V>), } /// A vacant Entry. It is part of the [`Entry`] enum. /// /// [`Entry`]: enum.Entry.html pub struct VacantEntry<'a, K, V> { vacant: VacantEntryImpl<'a, K, V>, } /// An occupied Entry. It is part of the [`Entry`] enum. /// /// [`Entry`]: enum.Entry.html pub struct OccupiedEntry<'a, K, V> { occupied: OccupiedEntryImpl<'a, K, V>, } #[cfg(not(feature = "preserve_order"))] type VacantEntryImpl<'a, K, V> = btree_map::VacantEntry<'a, K, V>; #[cfg(feature = "preserve_order")] type VacantEntryImpl<'a, K, V> = indexmap::map::VacantEntry<'a, K, V>; #[cfg(not(feature = "preserve_order"))] type OccupiedEntryImpl<'a, K, V> = btree_map::OccupiedEntry<'a, K, V>; #[cfg(feature = "preserve_order")] type OccupiedEntryImpl<'a, K, V> = indexmap::map::OccupiedEntry<'a, K, V>; impl<'a, K: Ord, V> Entry<'a, K, V> { /// Returns a reference to this entry's key. pub fn key(&self) -> &K { match *self { Entry::Vacant(ref e) => e.key(), Entry::Occupied(ref 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: V) -> &'a mut V { 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(self, default: F) -> &'a mut V where F: FnOnce() -> V, { match self { Entry::Vacant(entry) => entry.insert(default()), Entry::Occupied(entry) => entry.into_mut(), } } } impl<'a, K: Ord, V> VacantEntry<'a, K, V> { /// Gets a reference to the key that would be used when inserting a value /// through the `VacantEntry`. #[inline] pub fn key(&self) -> &K { 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: V) -> &'a mut V { self.vacant.insert(value) } } impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> { /// Gets a reference to the key in the entry. #[inline] pub fn key(&self) -> &K { self.occupied.key() } /// Gets a reference to the value in the entry. #[inline] pub fn get(&self) -> &V { self.occupied.get() } /// Gets a mutable reference to the value in the entry. #[inline] pub fn get_mut(&mut self) -> &mut V { self.occupied.get_mut() } /// Converts the entry into a mutable reference to its value. #[inline] pub fn into_mut(self) -> &'a mut V { 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: V) -> V { self.occupied.insert(value) } /// Takes the value of the entry out of the map, and returns it. #[inline] pub fn remove(self) -> V { #[cfg(not(feature = "preserve_order"))] { self.occupied.remove() } #[cfg(feature = "preserve_order")] { self.occupied.shift_remove() } } } ////////////////////////////////////////////////////////////////////////////// impl<'a, K, V> IntoIterator for &'a Map { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V>; #[inline] fn into_iter(self) -> Self::IntoIter { Iter { iter: self.map.iter(), } } } /// An iterator over a `toml::Map`'s entries. pub struct Iter<'a, K, V> { iter: IterImpl<'a, K, V>, } #[cfg(not(feature = "preserve_order"))] type IterImpl<'a, K, V> = btree_map::Iter<'a, K, V>; #[cfg(feature = "preserve_order")] type IterImpl<'a, K, V> = indexmap::map::Iter<'a, K, V>; delegate_iterator!((Iter<'a, K, V>) => (&'a K, &'a V)); ////////////////////////////////////////////////////////////////////////////// impl<'a, K, V> IntoIterator for &'a mut Map { type Item = (&'a K, &'a mut V); type IntoIter = IterMut<'a, K, V>; #[inline] fn into_iter(self) -> Self::IntoIter { IterMut { iter: self.map.iter_mut(), } } } /// A mutable iterator over a `toml::Map`'s entries. pub struct IterMut<'a, K, V> { iter: IterMutImpl<'a, K, V>, } #[cfg(not(feature = "preserve_order"))] type IterMutImpl<'a, K, V> = btree_map::IterMut<'a, K, V>; #[cfg(feature = "preserve_order")] type IterMutImpl<'a, K, V> = indexmap::map::IterMut<'a, K, V>; delegate_iterator!((IterMut<'a, K, V>) => (&'a K, &'a mut V)); ////////////////////////////////////////////////////////////////////////////// impl IntoIterator for Map { type Item = (K, V); type IntoIter = IntoIter; #[inline] fn into_iter(self) -> Self::IntoIter { IntoIter { iter: self.map.into_iter(), } } } /// An owning iterator over a `toml::Map`'s entries. pub struct IntoIter { iter: IntoIterImpl, } #[cfg(not(feature = "preserve_order"))] type IntoIterImpl = btree_map::IntoIter; #[cfg(feature = "preserve_order")] type IntoIterImpl = indexmap::map::IntoIter; delegate_iterator!((IntoIter) => (K, V)); ////////////////////////////////////////////////////////////////////////////// /// An iterator over a `toml::Map`'s keys. pub struct Keys<'a, K, V> { iter: KeysImpl<'a, K, V>, } #[cfg(not(feature = "preserve_order"))] type KeysImpl<'a, K, V> = btree_map::Keys<'a, K, V>; #[cfg(feature = "preserve_order")] type KeysImpl<'a, K, V> = indexmap::map::Keys<'a, K, V>; delegate_iterator!((Keys<'a, K, V>) => &'a K); ////////////////////////////////////////////////////////////////////////////// /// An iterator over a `toml::Map`'s values. pub struct Values<'a, K, V> { iter: ValuesImpl<'a, K, V>, } #[cfg(not(feature = "preserve_order"))] type ValuesImpl<'a, K, V> = btree_map::Values<'a, K, V>; #[cfg(feature = "preserve_order")] type ValuesImpl<'a, K, V> = indexmap::map::Values<'a, K, V>; delegate_iterator!((Values<'a, K, V>) => &'a V);