// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//! An unordered map.
//!
//! An immutable hash map using [hash array mapped tries][1].
//!
//! Most operations on this map are O(logx n) for a
//! suitably high *x* that it should be nearly O(1) for most maps.
//! Because of this, it's a great choice for a generic map as long as
//! you don't mind that keys will need to implement
//! [`Hash`][std::hash::Hash] and [`Eq`][std::cmp::Eq].
//!
//! Map entries will have a predictable order based on the hasher
//! being used. Unless otherwise specified, this will be the standard
//! [`RandomState`][std::collections::hash_map::RandomState] hasher.
//!
//! [1]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie
//! [std::cmp::Eq]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
//! [std::hash::Hash]: https://doc.rust-lang.org/std/hash/trait.Hash.html
//! [std::collections::hash_map::RandomState]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
use std::borrow::Borrow;
use std::cmp::Ordering;
use std::collections;
use std::collections::hash_map::RandomState;
use std::fmt::{Debug, Error, Formatter};
use std::hash::{BuildHasher, Hash, Hasher};
use std::iter::{FromIterator, FusedIterator, Sum};
use std::mem;
use std::ops::{Add, Index, IndexMut};
use crate::nodes::hamt::{
hash_key, Drain as NodeDrain, HashBits, HashValue, Iter as NodeIter, IterMut as NodeIterMut,
Node,
};
use crate::util::{Pool, PoolRef, Ref};
/// Construct a hash map from a sequence of key/value pairs.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// # fn main() {
/// assert_eq!(
/// hashmap!{
/// 1 => 11,
/// 2 => 22,
/// 3 => 33
/// },
/// HashMap::from(vec![(1, 11), (2, 22), (3, 33)])
/// );
/// # }
/// ```
#[macro_export]
macro_rules! hashmap {
() => { $crate::hashmap::HashMap::new() };
( $( $key:expr => $value:expr ),* ) => {{
let mut map = $crate::hashmap::HashMap::new();
$({
map.insert($key, $value);
})*;
map
}};
( $( $key:expr => $value:expr ,)* ) => {{
let mut map = $crate::hashmap::HashMap::new();
$({
map.insert($key, $value);
})*;
map
}};
}
def_pool!(HashMapPool, Node<(K,V)>);
/// An unordered map.
///
/// An immutable hash map using [hash array mapped tries] [1].
///
/// Most operations on this map are O(logx n) for a
/// suitably high *x* that it should be nearly O(1) for most maps.
/// Because of this, it's a great choice for a generic map as long as
/// you don't mind that keys will need to implement
/// [`Hash`][std::hash::Hash] and [`Eq`][std::cmp::Eq].
///
/// Map entries will have a predictable order based on the hasher
/// being used. Unless otherwise specified, this will be the standard
/// [`RandomState`][std::collections::hash_map::RandomState] hasher.
///
/// [1]: https://en.wikipedia.org/wiki/Hash_array_mapped_trie
/// [std::cmp::Eq]: https://doc.rust-lang.org/std/cmp/trait.Eq.html
/// [std::hash::Hash]: https://doc.rust-lang.org/std/hash/trait.Hash.html
/// [std::collections::hash_map::RandomState]: https://doc.rust-lang.org/std/collections/hash_map/struct.RandomState.html
pub struct HashMap {
size: usize,
pool: HashMapPool,
root: PoolRef>,
hasher: Ref,
}
impl HashValue for (K, V)
where
K: Eq,
{
type Key = K;
fn extract_key(&self) -> &Self::Key {
&self.0
}
fn ptr_eq(&self, _other: &Self) -> bool {
false
}
}
impl HashMap {
/// Construct an empty hash map.
#[inline]
#[must_use]
pub fn new() -> Self {
Self::default()
}
/// Construct an empty hash map using a specific memory pool.
#[cfg(feature = "pool")]
#[must_use]
pub fn with_pool(pool: &HashMapPool) -> Self {
let root = PoolRef::default(&pool.0);
Self {
size: 0,
hasher: Default::default(),
pool: pool.clone(),
root,
}
}
}
impl HashMap
where
K: Hash + Eq + Clone,
V: Clone,
{
/// Construct a hash map with a single mapping.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map = HashMap::unit(123, "onetwothree");
/// assert_eq!(
/// map.get(&123),
/// Some(&"onetwothree")
/// );
/// ```
#[inline]
#[must_use]
pub fn unit(k: K, v: V) -> HashMap {
HashMap::new().update(k, v)
}
}
impl HashMap {
/// Test whether a hash map is empty.
///
/// Time: O(1)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// assert!(
/// !hashmap!{1 => 2}.is_empty()
/// );
/// assert!(
/// HashMap::::new().is_empty()
/// );
/// ```
#[inline]
#[must_use]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
/// Get the size of a hash map.
///
/// Time: O(1)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// assert_eq!(3, hashmap!{
/// 1 => 11,
/// 2 => 22,
/// 3 => 33
/// }.len());
/// ```
#[inline]
#[must_use]
pub fn len(&self) -> usize {
self.size
}
/// Test whether two maps refer to the same content in memory.
///
/// This is true if the two sides are references to the same map,
/// or if the two maps refer to the same root node.
///
/// This would return true if you're comparing a map to itself, or
/// if you're comparing a map to a fresh clone of itself.
///
/// Time: O(1)
pub fn ptr_eq(&self, other: &Self) -> bool {
std::ptr::eq(self, other) || PoolRef::ptr_eq(&self.root, &other.root)
}
/// Get a reference to the memory pool used by this map.
///
/// Note that if you didn't specifically construct it with a pool, you'll
/// get back a reference to a pool of size 0.
#[cfg(feature = "pool")]
pub fn pool(&self) -> &HashMapPool {
&self.pool
}
/// Construct an empty hash map using the provided hasher.
#[inline]
#[must_use]
pub fn with_hasher(hasher: RS) -> Self
where
Ref: From,
{
let pool = HashMapPool::default();
let root = PoolRef::default(&pool.0);
HashMap {
size: 0,
hasher: hasher.into(),
pool,
root,
}
}
/// Construct an empty hash map using a specific memory pool and hasher.
#[cfg(feature = "pool")]
#[must_use]
pub fn with_pool_hasher(pool: &HashMapPool, hasher: RS) -> Self
where
Ref: From,
{
let root = PoolRef::default(&pool.0);
Self {
size: 0,
hasher: hasher.into(),
pool: pool.clone(),
root,
}
}
/// Get a reference to the map's [`BuildHasher`][BuildHasher].
///
/// [BuildHasher]: https://doc.rust-lang.org/std/hash/trait.BuildHasher.html
#[must_use]
pub fn hasher(&self) -> &Ref {
&self.hasher
}
/// Construct an empty hash map using the same hasher as the
/// current hash map.
#[inline]
#[must_use]
pub fn new_from(&self) -> HashMap
where
K1: Hash + Eq + Clone,
V1: Clone,
{
let pool = HashMapPool::default();
let root = PoolRef::default(&pool.0);
HashMap {
size: 0,
pool,
root,
hasher: self.hasher.clone(),
}
}
/// Get an iterator over the key/value pairs of a hash map.
///
/// Please note that the order is consistent between maps using
/// the same hasher, but no other ordering guarantee is offered.
/// Items will not come out in insertion order or sort order.
/// They will, however, come out in the same order every time for
/// the same map.
#[inline]
#[must_use]
pub fn iter(&self) -> Iter<'_, K, V> {
Iter {
it: NodeIter::new(&self.root, self.size),
}
}
/// Get an iterator over a hash map's keys.
///
/// Please note that the order is consistent between maps using
/// the same hasher, but no other ordering guarantee is offered.
/// Items will not come out in insertion order or sort order.
/// They will, however, come out in the same order every time for
/// the same map.
#[inline]
#[must_use]
pub fn keys(&self) -> Keys<'_, K, V> {
Keys {
it: NodeIter::new(&self.root, self.size),
}
}
/// Get an iterator over a hash map's values.
///
/// Please note that the order is consistent between maps using
/// the same hasher, but no other ordering guarantee is offered.
/// Items will not come out in insertion order or sort order.
/// They will, however, come out in the same order every time for
/// the same map.
#[inline]
#[must_use]
pub fn values(&self) -> Values<'_, K, V> {
Values {
it: NodeIter::new(&self.root, self.size),
}
}
/// Discard all elements from the map.
///
/// This leaves you with an empty map, and all elements that
/// were previously inside it are dropped.
///
/// Time: O(n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::HashMap;
/// let mut map = hashmap![1=>1, 2=>2, 3=>3];
/// map.clear();
/// assert!(map.is_empty());
/// ```
pub fn clear(&mut self) {
if !self.is_empty() {
self.root = PoolRef::default(&self.pool.0);
self.size = 0;
}
}
}
impl HashMap
where
K: Hash + Eq,
S: BuildHasher,
{
fn test_eq(&self, other: &Self) -> bool
where
K: Hash + Eq,
V: PartialEq,
{
if self.len() != other.len() {
return false;
}
let mut seen = collections::HashSet::new();
for (key, value) in self.iter() {
if Some(value) != other.get(key) {
return false;
}
seen.insert(key);
}
for key in other.keys() {
if !seen.contains(&key) {
return false;
}
}
true
}
/// Get the value for a key from a hash map.
///
/// Time: O(log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map = hashmap!{123 => "lol"};
/// assert_eq!(
/// map.get(&123),
/// Some(&"lol")
/// );
/// ```
#[must_use]
pub fn get(&self, key: &BK) -> Option<&V>
where
BK: Hash + Eq + ?Sized,
K: Borrow,
{
self.root
.get(hash_key(&*self.hasher, key), 0, key)
.map(|&(_, ref v)| v)
}
/// Get the key/value pair for a key from a hash map.
///
/// Time: O(log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map = hashmap!{123 => "lol"};
/// assert_eq!(
/// map.get_key_value(&123),
/// Some((&123, &"lol"))
/// );
/// ```
#[must_use]
pub fn get_key_value(&self, key: &BK) -> Option<(&K, &V)>
where
BK: Hash + Eq + ?Sized,
K: Borrow,
{
self.root
.get(hash_key(&*self.hasher, key), 0, key)
.map(|&(ref k, ref v)| (k, v))
}
/// Test for the presence of a key in a hash map.
///
/// Time: O(log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map = hashmap!{123 => "lol"};
/// assert!(
/// map.contains_key(&123)
/// );
/// assert!(
/// !map.contains_key(&321)
/// );
/// ```
#[inline]
#[must_use]
pub fn contains_key(&self, k: &BK) -> bool
where
BK: Hash + Eq + ?Sized,
K: Borrow,
{
self.get(k).is_some()
}
/// Test whether a map is a submap of another map, meaning that
/// all keys in our map must also be in the other map, with the
/// same values.
///
/// Use the provided function to decide whether values are equal.
///
/// Time: O(n log n)
#[must_use]
pub fn is_submap_by(&self, other: RM, mut cmp: F) -> bool
where
F: FnMut(&V, &B) -> bool,
RM: Borrow>,
{
self.iter()
.all(|(k, v)| other.borrow().get(k).map(|ov| cmp(v, ov)).unwrap_or(false))
}
/// Test whether a map is a proper submap of another map, meaning
/// that all keys in our map must also be in the other map, with
/// the same values. To be a proper submap, ours must also contain
/// fewer keys than the other map.
///
/// Use the provided function to decide whether values are equal.
///
/// Time: O(n log n)
#[must_use]
pub fn is_proper_submap_by(&self, other: RM, cmp: F) -> bool
where
F: FnMut(&V, &B) -> bool,
RM: Borrow>,
{
self.len() != other.borrow().len() && self.is_submap_by(other, cmp)
}
/// Test whether a map is a submap of another map, meaning that
/// all keys in our map must also be in the other map, with the
/// same values.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 2 => 2};
/// let map2 = hashmap!{1 => 1, 2 => 2, 3 => 3};
/// assert!(map1.is_submap(map2));
/// ```
#[inline]
#[must_use]
pub fn is_submap(&self, other: RM) -> bool
where
V: PartialEq,
RM: Borrow,
{
self.is_submap_by(other.borrow(), PartialEq::eq)
}
/// Test whether a map is a proper submap of another map, meaning
/// that all keys in our map must also be in the other map, with
/// the same values. To be a proper submap, ours must also contain
/// fewer keys than the other map.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 2 => 2};
/// let map2 = hashmap!{1 => 1, 2 => 2, 3 => 3};
/// assert!(map1.is_proper_submap(map2));
///
/// let map3 = hashmap!{1 => 1, 2 => 2};
/// let map4 = hashmap!{1 => 1, 2 => 2};
/// assert!(!map3.is_proper_submap(map4));
/// ```
#[inline]
#[must_use]
pub fn is_proper_submap(&self, other: RM) -> bool
where
V: PartialEq,
RM: Borrow,
{
self.is_proper_submap_by(other.borrow(), PartialEq::eq)
}
}
impl HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher,
{
/// Get a mutable iterator over the values of a hash map.
///
/// Please note that the order is consistent between maps using
/// the same hasher, but no other ordering guarantee is offered.
/// Items will not come out in insertion order or sort order.
/// They will, however, come out in the same order every time for
/// the same map.
#[inline]
#[must_use]
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
let root = PoolRef::make_mut(&self.pool.0, &mut self.root);
IterMut {
it: NodeIterMut::new(&self.pool.0, root, self.size),
}
}
/// Get a mutable reference to the value for a key from a hash
/// map.
///
/// Time: O(log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let mut map = hashmap!{123 => "lol"};
/// if let Some(value) = map.get_mut(&123) {
/// *value = "omg";
/// }
/// assert_eq!(
/// map.get(&123),
/// Some(&"omg")
/// );
/// ```
#[must_use]
pub fn get_mut(&mut self, key: &BK) -> Option<&mut V>
where
BK: Hash + Eq + ?Sized,
K: Borrow,
{
let root = PoolRef::make_mut(&self.pool.0, &mut self.root);
match root.get_mut(&self.pool.0, hash_key(&*self.hasher, key), 0, key) {
None => None,
Some(&mut (_, ref mut value)) => Some(value),
}
}
/// Insert a key/value mapping into a map.
///
/// If the map already has a mapping for the given key, the
/// previous value is overwritten.
///
/// Time: O(log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let mut map = hashmap!{};
/// map.insert(123, "123");
/// map.insert(456, "456");
/// assert_eq!(
/// map,
/// hashmap!{123 => "123", 456 => "456"}
/// );
/// ```
#[inline]
pub fn insert(&mut self, k: K, v: V) -> Option {
let hash = hash_key(&*self.hasher, &k);
let root = PoolRef::make_mut(&self.pool.0, &mut self.root);
let result = root.insert(&self.pool.0, hash, 0, (k, v));
if result.is_none() {
self.size += 1;
}
result.map(|(_, v)| v)
}
/// Remove a key/value pair from a map, if it exists, and return
/// the removed value.
///
/// This is a copy-on-write operation, so that the parts of the
/// set's structure which are shared with other sets will be
/// safely copied before mutating.
///
/// Time: O(log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let mut map = hashmap!{123 => "123", 456 => "456"};
/// assert_eq!(Some("123"), map.remove(&123));
/// assert_eq!(Some("456"), map.remove(&456));
/// assert_eq!(None, map.remove(&789));
/// assert!(map.is_empty());
/// ```
pub fn remove(&mut self, k: &BK) -> Option
where
BK: Hash + Eq + ?Sized,
K: Borrow,
{
self.remove_with_key(k).map(|(_, v)| v)
}
/// Remove a key/value pair from a map, if it exists, and return
/// the removed key and value.
///
/// Time: O(log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let mut map = hashmap!{123 => "123", 456 => "456"};
/// assert_eq!(Some((123, "123")), map.remove_with_key(&123));
/// assert_eq!(Some((456, "456")), map.remove_with_key(&456));
/// assert_eq!(None, map.remove_with_key(&789));
/// assert!(map.is_empty());
/// ```
pub fn remove_with_key(&mut self, k: &BK) -> Option<(K, V)>
where
BK: Hash + Eq + ?Sized,
K: Borrow,
{
let root = PoolRef::make_mut(&self.pool.0, &mut self.root);
let result = root.remove(&self.pool.0, hash_key(&*self.hasher, k), 0, k);
if result.is_some() {
self.size -= 1;
}
result
}
/// Get the [`Entry`][Entry] for a key in the map for in-place manipulation.
///
/// Time: O(log n)
///
/// [Entry]: enum.Entry.html
#[must_use]
pub fn entry(&mut self, key: K) -> Entry<'_, K, V, S> {
let hash = hash_key(&*self.hasher, &key);
if self.root.get(hash, 0, &key).is_some() {
Entry::Occupied(OccupiedEntry {
map: self,
hash,
key,
})
} else {
Entry::Vacant(VacantEntry {
map: self,
hash,
key,
})
}
}
/// Construct a new hash map by inserting a key/value mapping into a map.
///
/// If the map already has a mapping for the given key, the previous value
/// is overwritten.
///
/// Time: O(log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map = hashmap!{};
/// assert_eq!(
/// map.update(123, "123"),
/// hashmap!{123 => "123"}
/// );
/// ```
#[inline]
#[must_use]
pub fn update(&self, k: K, v: V) -> Self {
let mut out = self.clone();
out.insert(k, v);
out
}
/// Construct a new hash map by inserting a key/value mapping into
/// a map.
///
/// If the map already has a mapping for the given key, we call
/// the provided function with the old value and the new value,
/// and insert the result as the new value.
///
/// Time: O(log n)
#[must_use]
pub fn update_with(&self, k: K, v: V, f: F) -> Self
where
F: FnOnce(V, V) -> V,
{
match self.extract_with_key(&k) {
None => self.update(k, v),
Some((_, v2, m)) => m.update(k, f(v2, v)),
}
}
/// Construct a new map by inserting a key/value mapping into a
/// map.
///
/// If the map already has a mapping for the given key, we call
/// the provided function with the key, the old value and the new
/// value, and insert the result as the new value.
///
/// Time: O(log n)
#[must_use]
pub fn update_with_key(&self, k: K, v: V, f: F) -> Self
where
F: FnOnce(&K, V, V) -> V,
{
match self.extract_with_key(&k) {
None => self.update(k, v),
Some((_, v2, m)) => {
let out_v = f(&k, v2, v);
m.update(k, out_v)
}
}
}
/// Construct a new map by inserting a key/value mapping into a
/// map, returning the old value for the key as well as the new
/// map.
///
/// If the map already has a mapping for the given key, we call
/// the provided function with the key, the old value and the new
/// value, and insert the result as the new value.
///
/// Time: O(log n)
#[must_use]
pub fn update_lookup_with_key(&self, k: K, v: V, f: F) -> (Option, Self)
where
F: FnOnce(&K, &V, V) -> V,
{
match self.extract_with_key(&k) {
None => (None, self.update(k, v)),
Some((_, v2, m)) => {
let out_v = f(&k, &v2, v);
(Some(v2), m.update(k, out_v))
}
}
}
/// Update the value for a given key by calling a function with
/// the current value and overwriting it with the function's
/// return value.
///
/// The function gets an [`Option`][std::option::Option] and
/// returns the same, so that it can decide to delete a mapping
/// instead of updating the value, and decide what to do if the
/// key isn't in the map.
///
/// Time: O(log n)
///
/// [std::option::Option]: https://doc.rust-lang.org/std/option/enum.Option.html
#[must_use]
pub fn alter(&self, f: F, k: K) -> Self
where
F: FnOnce(Option) -> Option,
{
let pop = self.extract_with_key(&k);
match (f(pop.as_ref().map(|&(_, ref v, _)| v.clone())), pop) {
(None, None) => self.clone(),
(Some(v), None) => self.update(k, v),
(None, Some((_, _, m))) => m,
(Some(v), Some((_, _, m))) => m.update(k, v),
}
}
/// Construct a new map without the given key.
///
/// Construct a map that's a copy of the current map, absent the
/// mapping for `key` if it's present.
///
/// Time: O(log n)
#[must_use]
pub fn without(&self, k: &BK) -> Self
where
BK: Hash + Eq + ?Sized,
K: Borrow,
{
match self.extract_with_key(k) {
None => self.clone(),
Some((_, _, map)) => map,
}
}
/// Filter out values from a map which don't satisfy a predicate.
///
/// This is slightly more efficient than filtering using an
/// iterator, in that it doesn't need to rehash the retained
/// values, but it still needs to reconstruct the entire tree
/// structure of the map.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::HashMap;
/// let mut map = hashmap!{1 => 1, 2 => 2, 3 => 3};
/// map.retain(|k, v| *k > 1);
/// let expected = hashmap!{2 => 2, 3 => 3};
/// assert_eq!(expected, map);
/// ```
pub fn retain(&mut self, mut f: F)
where
F: FnMut(&K, &V) -> bool,
{
let old_root = self.root.clone();
let root = PoolRef::make_mut(&self.pool.0, &mut self.root);
for ((key, value), hash) in NodeIter::new(&old_root, self.size) {
if !f(key, value) && root.remove(&self.pool.0, hash, 0, key).is_some() {
self.size -= 1;
}
}
}
/// Remove a key/value pair from a map, if it exists, and return
/// the removed value as well as the updated map.
///
/// Time: O(log n)
#[must_use]
pub fn extract(&self, k: &BK) -> Option<(V, Self)>
where
BK: Hash + Eq + ?Sized,
K: Borrow,
{
self.extract_with_key(k).map(|(_, v, m)| (v, m))
}
/// Remove a key/value pair from a map, if it exists, and return
/// the removed key and value as well as the updated list.
///
/// Time: O(log n)
#[must_use]
pub fn extract_with_key(&self, k: &BK) -> Option<(K, V, Self)>
where
BK: Hash + Eq + ?Sized,
K: Borrow,
{
let mut out = self.clone();
out.remove_with_key(k).map(|(k, v)| (k, v, out))
}
/// Construct the union of two maps, keeping the values in the
/// current map when keys exist in both maps.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 3 => 3};
/// let map2 = hashmap!{2 => 2, 3 => 4};
/// let expected = hashmap!{1 => 1, 2 => 2, 3 => 3};
/// assert_eq!(expected, map1.union(map2));
/// ```
#[must_use]
pub fn union(self, other: Self) -> Self {
let (mut to_mutate, to_consume) = if self.len() >= other.len() {
(self, other)
} else {
(other, self)
};
for (k, v) in to_consume {
to_mutate.entry(k).or_insert(v);
}
to_mutate
}
/// Construct the union of two maps, using a function to decide
/// what to do with the value when a key is in both maps.
///
/// The function is called when a value exists in both maps, and
/// receives the value from the current map as its first argument,
/// and the value from the other map as the second. It should
/// return the value to be inserted in the resulting map.
///
/// Time: O(n log n)
#[inline]
#[must_use]
pub fn union_with(self, other: Self, mut f: F) -> Self
where
F: FnMut(V, V) -> V,
{
self.union_with_key(other, |_, v1, v2| f(v1, v2))
}
/// Construct the union of two maps, using a function to decide
/// what to do with the value when a key is in both maps.
///
/// The function is called when a value exists in both maps, and
/// receives a reference to the key as its first argument, the
/// value from the current map as the second argument, and the
/// value from the other map as the third argument. It should
/// return the value to be inserted in the resulting map.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 3 => 4};
/// let map2 = hashmap!{2 => 2, 3 => 5};
/// let expected = hashmap!{1 => 1, 2 => 2, 3 => 9};
/// assert_eq!(expected, map1.union_with_key(
/// map2,
/// |key, left, right| left + right
/// ));
/// ```
#[must_use]
pub fn union_with_key(self, other: Self, mut f: F) -> Self
where
F: FnMut(&K, V, V) -> V,
{
if self.len() >= other.len() {
self.union_with_key_inner(other, f)
} else {
other.union_with_key_inner(self, |key, other_value, self_value| {
f(key, self_value, other_value)
})
}
}
fn union_with_key_inner(mut self, other: Self, mut f: F) -> Self
where
F: FnMut(&K, V, V) -> V,
{
for (key, right_value) in other {
match self.remove(&key) {
None => {
self.insert(key, right_value);
}
Some(left_value) => {
let final_value = f(&key, left_value, right_value);
self.insert(key, final_value);
}
}
}
self
}
/// Construct the union of a sequence of maps, selecting the value
/// of the leftmost when a key appears in more than one map.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 3 => 3};
/// let map2 = hashmap!{2 => 2};
/// let expected = hashmap!{1 => 1, 2 => 2, 3 => 3};
/// assert_eq!(expected, HashMap::unions(vec![map1, map2]));
/// ```
#[must_use]
pub fn unions(i: I) -> Self
where
S: Default,
I: IntoIterator- ,
{
i.into_iter().fold(Self::default(), Self::union)
}
/// Construct the union of a sequence of maps, using a function to
/// decide what to do with the value when a key is in more than
/// one map.
///
/// The function is called when a value exists in multiple maps,
/// and receives the value from the current map as its first
/// argument, and the value from the next map as the second. It
/// should return the value to be inserted in the resulting map.
///
/// Time: O(n log n)
#[must_use]
pub fn unions_with(i: I, f: F) -> Self
where
S: Default,
I: IntoIterator
- ,
F: Fn(V, V) -> V,
{
i.into_iter()
.fold(Self::default(), |a, b| a.union_with(b, &f))
}
/// Construct the union of a sequence of maps, using a function to
/// decide what to do with the value when a key is in more than
/// one map.
///
/// The function is called when a value exists in multiple maps,
/// and receives a reference to the key as its first argument, the
/// value from the current map as the second argument, and the
/// value from the next map as the third argument. It should
/// return the value to be inserted in the resulting map.
///
/// Time: O(n log n)
#[must_use]
pub fn unions_with_key(i: I, f: F) -> Self
where
S: Default,
I: IntoIterator
- ,
F: Fn(&K, V, V) -> V,
{
i.into_iter()
.fold(Self::default(), |a, b| a.union_with_key(b, &f))
}
/// Construct the symmetric difference between two maps by discarding keys
/// which occur in both maps.
///
/// This is an alias for the
/// [`symmetric_difference`][symmetric_difference] method.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 3 => 4};
/// let map2 = hashmap!{2 => 2, 3 => 5};
/// let expected = hashmap!{1 => 1, 2 => 2};
/// assert_eq!(expected, map1.difference(map2));
/// ```
///
/// [symmetric_difference]: #method.symmetric_difference
#[inline]
#[must_use]
pub fn difference(self, other: Self) -> Self {
self.symmetric_difference(other)
}
/// Construct the symmetric difference between two maps by discarding keys
/// which occur in both maps.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 3 => 4};
/// let map2 = hashmap!{2 => 2, 3 => 5};
/// let expected = hashmap!{1 => 1, 2 => 2};
/// assert_eq!(expected, map1.symmetric_difference(map2));
/// ```
#[inline]
#[must_use]
pub fn symmetric_difference(self, other: Self) -> Self {
self.symmetric_difference_with_key(other, |_, _, _| None)
}
/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both.
///
/// This is an alias for the
/// [`symmetric_difference_with`][symmetric_difference_with] method.
///
/// Time: O(n log n)
///
/// [symmetric_difference_with]: #method.symmetric_difference_with
#[inline]
#[must_use]
pub fn difference_with(self, other: Self, f: F) -> Self
where
F: FnMut(V, V) -> Option,
{
self.symmetric_difference_with(other, f)
}
/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both.
///
/// Time: O(n log n)
#[inline]
#[must_use]
pub fn symmetric_difference_with(self, other: Self, mut f: F) -> Self
where
F: FnMut(V, V) -> Option,
{
self.symmetric_difference_with_key(other, |_, a, b| f(a, b))
}
/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both. The function
/// receives the key as well as both values.
///
/// This is an alias for the
/// [`symmetric_difference_with`_key][symmetric_difference_with_key]
/// method.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 3 => 4};
/// let map2 = hashmap!{2 => 2, 3 => 5};
/// let expected = hashmap!{1 => 1, 2 => 2, 3 => 9};
/// assert_eq!(expected, map1.difference_with_key(
/// map2,
/// |key, left, right| Some(left + right)
/// ));
/// ```
///
/// [symmetric_difference_with_key]: #method.symmetric_difference_with_key
#[must_use]
pub fn difference_with_key(self, other: Self, f: F) -> Self
where
F: FnMut(&K, V, V) -> Option,
{
self.symmetric_difference_with_key(other, f)
}
/// Construct the symmetric difference between two maps by using a function
/// to decide what to do if a key occurs in both. The function
/// receives the key as well as both values.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 3 => 4};
/// let map2 = hashmap!{2 => 2, 3 => 5};
/// let expected = hashmap!{1 => 1, 2 => 2, 3 => 9};
/// assert_eq!(expected, map1.symmetric_difference_with_key(
/// map2,
/// |key, left, right| Some(left + right)
/// ));
/// ```
#[must_use]
pub fn symmetric_difference_with_key(mut self, other: Self, mut f: F) -> Self
where
F: FnMut(&K, V, V) -> Option,
{
let mut out = self.new_from();
for (key, right_value) in other {
match self.remove(&key) {
None => {
out.insert(key, right_value);
}
Some(left_value) => {
if let Some(final_value) = f(&key, left_value, right_value) {
out.insert(key, final_value);
}
}
}
}
out.union(self)
}
/// Construct the relative complement between two maps by discarding keys
/// which occur in `other`.
///
/// Time: O(m log n) where m is the size of the other map
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::ordmap::OrdMap;
/// let map1 = ordmap!{1 => 1, 3 => 4};
/// let map2 = ordmap!{2 => 2, 3 => 5};
/// let expected = ordmap!{1 => 1};
/// assert_eq!(expected, map1.relative_complement(map2));
/// ```
#[inline]
#[must_use]
pub fn relative_complement(mut self, other: Self) -> Self {
for (key, _) in other {
let _ = self.remove(&key);
}
self
}
/// Construct the intersection of two maps, keeping the values
/// from the current map.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 2 => 2};
/// let map2 = hashmap!{2 => 3, 3 => 4};
/// let expected = hashmap!{2 => 2};
/// assert_eq!(expected, map1.intersection(map2));
/// ```
#[inline]
#[must_use]
pub fn intersection(self, other: Self) -> Self {
self.intersection_with_key(other, |_, v, _| v)
}
/// Construct the intersection of two maps, calling a function
/// with both values for each key and using the result as the
/// value for the key.
///
/// Time: O(n log n)
#[inline]
#[must_use]
pub fn intersection_with(self, other: HashMap, mut f: F) -> HashMap
where
B: Clone,
C: Clone,
F: FnMut(V, B) -> C,
{
self.intersection_with_key(other, |_, v1, v2| f(v1, v2))
}
/// Construct the intersection of two maps, calling a function
/// with the key and both values for each key and using the result
/// as the value for the key.
///
/// Time: O(n log n)
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate im_rc as im;
/// # use im::hashmap::HashMap;
/// let map1 = hashmap!{1 => 1, 2 => 2};
/// let map2 = hashmap!{2 => 3, 3 => 4};
/// let expected = hashmap!{2 => 5};
/// assert_eq!(expected, map1.intersection_with_key(
/// map2,
/// |key, left, right| left + right
/// ));
/// ```
#[must_use]
pub fn intersection_with_key(
mut self,
other: HashMap,
mut f: F,
) -> HashMap
where
B: Clone,
C: Clone,
F: FnMut(&K, V, B) -> C,
{
let mut out = self.new_from();
for (key, right_value) in other {
match self.remove(&key) {
None => (),
Some(left_value) => {
let result = f(&key, left_value, right_value);
out.insert(key, result);
}
}
}
out
}
}
// Entries
/// A handle for a key and its associated value.
///
/// ## Performance Note
///
/// When using an `Entry`, the key is only ever hashed once, when you
/// create the `Entry`. Operations on an `Entry` will never trigger a
/// rehash, where eg. a `contains_key(key)` followed by an
/// `insert(key, default_value)` (the equivalent of
/// `Entry::or_insert()`) would need to hash the key once for the
/// `contains_key` and again for the `insert`. The operations
/// generally perform similarly otherwise.
pub enum Entry<'a, K, V, S>
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher,
{
/// An entry which exists in the map.
Occupied(OccupiedEntry<'a, K, V, S>),
/// An entry which doesn't exist in the map.
Vacant(VacantEntry<'a, K, V, S>),
}
impl<'a, K, V, S> Entry<'a, K, V, S>
where
K: 'a + Hash + Eq + Clone,
V: 'a + Clone,
S: 'a + BuildHasher,
{
/// Insert the default value provided if there was no value
/// already, and return a mutable reference to the value.
pub fn or_insert(self, default: V) -> &'a mut V {
self.or_insert_with(|| default)
}
/// Insert the default value from the provided function if there
/// was no value already, and return a mutable reference to the
/// value.
pub fn or_insert_with(self, default: F) -> &'a mut V
where
F: FnOnce() -> V,
{
match self {
Entry::Occupied(entry) => entry.into_mut(),
Entry::Vacant(entry) => entry.insert(default()),
}
}
/// Insert a default value if there was no value already, and
/// return a mutable reference to the value.
pub fn or_default(self) -> &'a mut V
where
V: Default,
{
self.or_insert_with(Default::default)
}
/// Get the key for this entry.
#[must_use]
pub fn key(&self) -> &K {
match self {
Entry::Occupied(entry) => entry.key(),
Entry::Vacant(entry) => entry.key(),
}
}
/// Call the provided function to modify the value if the value
/// exists.
pub fn and_modify(mut self, f: F) -> Self
where
F: FnOnce(&mut V),
{
match &mut self {
Entry::Occupied(ref mut entry) => f(entry.get_mut()),
Entry::Vacant(_) => (),
}
self
}
}
/// An entry for a mapping that already exists in the map.
pub struct OccupiedEntry<'a, K, V, S>
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher,
{
map: &'a mut HashMap,
hash: HashBits,
key: K,
}
impl<'a, K, V, S> OccupiedEntry<'a, K, V, S>
where
K: 'a + Hash + Eq + Clone,
V: 'a + Clone,
S: 'a + BuildHasher,
{
/// Get the key for this entry.
#[must_use]
pub fn key(&self) -> &K {
&self.key
}
/// Remove this entry from the map and return the removed mapping.
pub fn remove_entry(self) -> (K, V) {
let root = PoolRef::make_mut(&self.map.pool.0, &mut self.map.root);
let result = root.remove(&self.map.pool.0, self.hash, 0, &self.key);
self.map.size -= 1;
result.unwrap()
}
/// Get the current value.
#[must_use]
pub fn get(&self) -> &V {
&self.map.root.get(self.hash, 0, &self.key).unwrap().1
}
/// Get a mutable reference to the current value.
#[must_use]
pub fn get_mut(&mut self) -> &mut V {
let root = PoolRef::make_mut(&self.map.pool.0, &mut self.map.root);
&mut root
.get_mut(&self.map.pool.0, self.hash, 0, &self.key)
.unwrap()
.1
}
/// Convert this entry into a mutable reference.
#[must_use]
pub fn into_mut(self) -> &'a mut V {
let root = PoolRef::make_mut(&self.map.pool.0, &mut self.map.root);
&mut root
.get_mut(&self.map.pool.0, self.hash, 0, &self.key)
.unwrap()
.1
}
/// Overwrite the current value.
pub fn insert(&mut self, value: V) -> V {
mem::replace(self.get_mut(), value)
}
/// Remove this entry from the map and return the removed value.
pub fn remove(self) -> V {
self.remove_entry().1
}
}
/// An entry for a mapping that does not already exist in the map.
pub struct VacantEntry<'a, K, V, S>
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher,
{
map: &'a mut HashMap,
hash: HashBits,
key: K,
}
impl<'a, K, V, S> VacantEntry<'a, K, V, S>
where
K: 'a + Hash + Eq + Clone,
V: 'a + Clone,
S: 'a + BuildHasher,
{
/// Get the key for this entry.
#[must_use]
pub fn key(&self) -> &K {
&self.key
}
/// Convert this entry into its key.
#[must_use]
pub fn into_key(self) -> K {
self.key
}
/// Insert a value into this entry.
pub fn insert(self, value: V) -> &'a mut V {
let root = PoolRef::make_mut(&self.map.pool.0, &mut self.map.root);
if root
.insert(&self.map.pool.0, self.hash, 0, (self.key.clone(), value))
.is_none()
{
self.map.size += 1;
}
// TODO it's unfortunate that we need to look up the key again
// here to get the mut ref.
&mut root
.get_mut(&self.map.pool.0, self.hash, 0, &self.key)
.unwrap()
.1
}
}
// Core traits
impl Clone for HashMap
where
K: Clone,
V: Clone,
{
/// Clone a map.
///
/// Time: O(1)
#[inline]
fn clone(&self) -> Self {
HashMap {
root: self.root.clone(),
pool: self.pool.clone(),
size: self.size,
hasher: self.hasher.clone(),
}
}
}
#[cfg(not(has_specialisation))]
impl PartialEq for HashMap
where
K: Hash + Eq,
V: PartialEq,
S: BuildHasher,
{
fn eq(&self, other: &Self) -> bool {
self.test_eq(other)
}
}
#[cfg(has_specialisation)]
impl PartialEq for HashMap
where
K: Hash + Eq,
V: PartialEq,
S: BuildHasher,
{
default fn eq(&self, other: &Self) -> bool {
self.test_eq(other)
}
}
#[cfg(has_specialisation)]
impl PartialEq for HashMap
where
K: Hash + Eq,
V: Eq,
S: BuildHasher,
{
fn eq(&self, other: &Self) -> bool {
if PoolRef::ptr_eq(&self.root, &other.root) {
return true;
}
self.test_eq(other)
}
}
impl Eq for HashMap
where
K: Hash + Eq,
V: Eq,
S: BuildHasher,
{
}
impl PartialOrd for HashMap
where
K: Hash + Eq + Clone + PartialOrd,
V: PartialOrd + Clone,
S: BuildHasher,
{
fn partial_cmp(&self, other: &Self) -> Option {
if Ref::ptr_eq(&self.hasher, &other.hasher) {
return self.iter().partial_cmp(other.iter());
}
self.iter().partial_cmp(other.iter())
}
}
impl Ord for HashMap
where
K: Hash + Eq + Ord + Clone,
V: Ord + Clone,
S: BuildHasher,
{
fn cmp(&self, other: &Self) -> Ordering {
if Ref::ptr_eq(&self.hasher, &other.hasher) {
return self.iter().cmp(other.iter());
}
self.iter().cmp(other.iter())
}
}
impl Hash for HashMap
where
K: Hash + Eq,
V: Hash,
S: BuildHasher,
{
fn hash(&self, state: &mut H)
where
H: Hasher,
{
for i in self.iter() {
i.hash(state);
}
}
}
impl Default for HashMap
where
S: BuildHasher + Default,
{
#[inline]
fn default() -> Self {
let pool = HashMapPool::default();
let root = PoolRef::default(&pool.0);
HashMap {
size: 0,
pool,
root,
hasher: Ref::
::default(),
}
}
}
impl Add for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher,
{
type Output = HashMap;
fn add(self, other: Self) -> Self::Output {
self.union(other)
}
}
impl<'a, K, V, S> Add for &'a HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher,
{
type Output = HashMap;
fn add(self, other: Self) -> Self::Output {
self.clone().union(other.clone())
}
}
impl Sum for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher + Default,
{
fn sum(it: I) -> Self
where
I: Iterator- ,
{
it.fold(Self::default(), |a, b| a + b)
}
}
impl Extend<(RK, RV)> for HashMap
where
K: Hash + Eq + Clone + From,
V: Clone + From,
S: BuildHasher,
{
fn extend(&mut self, iter: I)
where
I: IntoIterator
- ,
{
for (key, value) in iter {
self.insert(From::from(key), From::from(value));
}
}
}
impl<'a, BK, K, V, S> Index<&'a BK> for HashMap
where
BK: Hash + Eq + ?Sized,
K: Hash + Eq + Borrow,
S: BuildHasher,
{
type Output = V;
fn index(&self, key: &BK) -> &Self::Output {
match self.root.get(hash_key(&*self.hasher, key), 0, key) {
None => panic!("HashMap::index: invalid key"),
Some(&(_, ref value)) => value,
}
}
}
impl<'a, BK, K, V, S> IndexMut<&'a BK> for HashMap
where
BK: Hash + Eq + ?Sized,
K: Hash + Eq + Clone + Borrow,
V: Clone,
S: BuildHasher,
{
fn index_mut(&mut self, key: &BK) -> &mut Self::Output {
let root = PoolRef::make_mut(&self.pool.0, &mut self.root);
match root.get_mut(&self.pool.0, hash_key(&*self.hasher, key), 0, key) {
None => panic!("HashMap::index_mut: invalid key"),
Some(&mut (_, ref mut value)) => value,
}
}
}
#[cfg(not(has_specialisation))]
impl Debug for HashMap
where
K: Hash + Eq + Debug,
V: Debug,
S: BuildHasher,
{
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
let mut d = f.debug_map();
for (k, v) in self {
d.entry(k, v);
}
d.finish()
}
}
#[cfg(has_specialisation)]
impl Debug for HashMap
where
K: Hash + Eq + Debug,
V: Debug,
S: BuildHasher,
{
default fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
let mut d = f.debug_map();
for (k, v) in self {
d.entry(k, v);
}
d.finish()
}
}
#[cfg(has_specialisation)]
impl Debug for HashMap
where
K: Hash + Eq + Ord + Debug,
V: Debug,
S: BuildHasher,
{
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
let mut keys = collections::BTreeSet::new();
keys.extend(self.keys());
let mut d = f.debug_map();
for key in keys {
d.entry(key, &self[key]);
}
d.finish()
}
}
// // Iterators
/// An iterator over the elements of a map.
pub struct Iter<'a, K, V> {
it: NodeIter<'a, (K, V)>,
}
impl<'a, K, V> Iterator for Iter<'a, K, V> {
type Item = (&'a K, &'a V);
fn next(&mut self) -> Option {
self.it.next().map(|((k, v), _)| (k, v))
}
fn size_hint(&self) -> (usize, Option) {
self.it.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {}
impl<'a, K, V> FusedIterator for Iter<'a, K, V> {}
/// A mutable iterator over the elements of a map.
pub struct IterMut<'a, K, V>
where
K: Clone,
V: Clone,
{
it: NodeIterMut<'a, (K, V)>,
}
impl<'a, K, V> Iterator for IterMut<'a, K, V>
where
K: Clone,
V: Clone,
{
type Item = (&'a K, &'a mut V);
fn next(&mut self) -> Option {
self.it.next().map(|((k, v), _)| (&*k, v))
}
fn size_hint(&self) -> (usize, Option) {
self.it.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V>
where
K: Clone,
V: Clone,
{
}
impl<'a, K, V> FusedIterator for IterMut<'a, K, V>
where
K: Clone,
V: Clone,
{
}
/// A consuming iterator over the elements of a map.
pub struct ConsumingIter {
it: NodeDrain,
}
impl Iterator for ConsumingIter
where
A: HashValue + Clone,
{
type Item = A;
fn next(&mut self) -> Option {
self.it.next().map(|(p, _)| p)
}
fn size_hint(&self) -> (usize, Option) {
self.it.size_hint()
}
}
impl ExactSizeIterator for ConsumingIter where A: HashValue + Clone {}
impl FusedIterator for ConsumingIter where A: HashValue + Clone {}
/// An iterator over the keys of a map.
pub struct Keys<'a, K, V> {
it: NodeIter<'a, (K, V)>,
}
impl<'a, K, V> Iterator for Keys<'a, K, V> {
type Item = &'a K;
fn next(&mut self) -> Option {
self.it.next().map(|((k, _), _)| k)
}
fn size_hint(&self) -> (usize, Option) {
self.it.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {}
impl<'a, K, V> FusedIterator for Keys<'a, K, V> {}
/// An iterator over the values of a map.
pub struct Values<'a, K, V> {
it: NodeIter<'a, (K, V)>,
}
impl<'a, K, V> Iterator for Values<'a, K, V> {
type Item = &'a V;
fn next(&mut self) -> Option {
self.it.next().map(|((_, v), _)| v)
}
fn size_hint(&self) -> (usize, Option) {
self.it.size_hint()
}
}
impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {}
impl<'a, K, V> FusedIterator for Values<'a, K, V> {}
impl<'a, K, V, S> IntoIterator for &'a HashMap
where
K: Hash + Eq,
S: BuildHasher,
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl IntoIterator for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher,
{
type Item = (K, V);
type IntoIter = ConsumingIter<(K, V)>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
ConsumingIter {
it: NodeDrain::new(&self.pool.0, self.root, self.size),
}
}
}
// Conversions
impl FromIterator<(K, V)> for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher + Default,
{
fn from_iter(i: T) -> Self
where
T: IntoIterator
- ,
{
let mut map = Self::default();
for (k, v) in i {
map.insert(k, v);
}
map
}
}
impl AsRef> for HashMap {
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
impl<'m, 'k, 'v, K, V, OK, OV, SA, SB> From<&'m HashMap<&'k K, &'v V, SA>> for HashMap
where
K: Hash + Eq + ToOwned + ?Sized,
V: ToOwned + ?Sized,
OK: Hash + Eq + Clone + Borrow,
OV: Borrow + Clone,
SA: BuildHasher,
SB: BuildHasher + Default,
{
fn from(m: &HashMap<&K, &V, SA>) -> Self {
m.iter()
.map(|(k, v)| ((*k).to_owned(), (*v).to_owned()))
.collect()
}
}
impl<'a, K, V, S> From<&'a [(K, V)]> for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher + Default,
{
fn from(m: &'a [(K, V)]) -> Self {
m.iter().cloned().collect()
}
}
impl From> for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher + Default,
{
fn from(m: Vec<(K, V)>) -> Self {
m.into_iter().collect()
}
}
impl<'a, K, V, S> From<&'a Vec<(K, V)>> for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher + Default,
{
fn from(m: &'a Vec<(K, V)>) -> Self {
m.iter().cloned().collect()
}
}
impl From> for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher + Default,
{
fn from(m: collections::HashMap) -> Self {
m.into_iter().collect()
}
}
impl<'a, K, V, S> From<&'a collections::HashMap> for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher + Default,
{
fn from(m: &'a collections::HashMap) -> Self {
m.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
}
}
impl From> for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher + Default,
{
fn from(m: collections::BTreeMap) -> Self {
m.into_iter().collect()
}
}
impl<'a, K, V, S> From<&'a collections::BTreeMap> for HashMap
where
K: Hash + Eq + Clone,
V: Clone,
S: BuildHasher + Default,
{
fn from(m: &'a collections::BTreeMap) -> Self {
m.iter().map(|(k, v)| (k.clone(), v.clone())).collect()
}
}
// impl From> for HashMap
// where
// S: BuildHasher + Default,
// {
// fn from(m: OrdMap) -> Self {
// m.into_iter().collect()
// }
// }
// impl<'a, K: Ord + Hash + Eq, V, S> From<&'a OrdMap> for HashMap
// where
// S: BuildHasher + Default,
// {
// fn from(m: &'a OrdMap) -> Self {
// m.into_iter().collect()
// }
// }
// Proptest
#[cfg(any(test, feature = "proptest"))]
#[doc(hidden)]
pub mod proptest {
#[deprecated(
since = "14.3.0",
note = "proptest strategies have moved to im::proptest"
)]
pub use crate::proptest::hash_map;
}
// Tests
#[cfg(test)]
mod test {
use super::*;
use crate::test::LolHasher;
use ::proptest::num::{i16, usize};
use ::proptest::{collection, proptest};
use std::hash::BuildHasherDefault;
#[test]
fn safe_mutation() {
let v1: HashMap = (0..131_072).map(|i| (i, i)).collect::>();
let mut v2 = v1.clone();
v2.insert(131_000, 23);
assert_eq!(Some(&23), v2.get(&131_000));
assert_eq!(Some(&131_000), v1.get(&131_000));
}
#[test]
fn index_operator() {
let mut map = hashmap![1 => 2, 3 => 4, 5 => 6];
assert_eq!(4, map[&3]);
map[&3] = 8;
assert_eq!(hashmap![1 => 2, 3 => 8, 5 => 6], map);
}
#[test]
fn proper_formatting() {
let map = hashmap![1 => 2];
assert_eq!("{1: 2}", format!("{:?}", map));
assert_eq!("{}", format!("{:?}", HashMap::<(), ()>::new()));
}
#[test]
fn remove_failing() {
let pairs = [(1469, 0), (-67, 0)];
let mut m: collections::HashMap =
collections::HashMap::with_hasher(BuildHasherDefault::::default());
for &(ref k, ref v) in &pairs {
m.insert(*k, *v);
}
let mut map: HashMap =
HashMap::with_hasher(BuildHasherDefault::::default());
for (k, v) in &m {
map = map.update(*k, *v);
}
for k in m.keys() {
let l = map.len();
assert_eq!(m.get(k).cloned(), map.get(k).cloned());
map = map.without(k);
assert_eq!(None, map.get(k));
assert_eq!(l - 1, map.len());
}
}
#[test]
fn match_string_keys_with_string_slices() {
let mut map: HashMap =
From::from(&hashmap! { "foo" => &1, "bar" => &2, "baz" => &3 });
assert_eq!(Some(&1), map.get("foo"));
map = map.without("foo");
assert_eq!(Some(3), map.remove("baz"));
map["bar"] = 8;
assert_eq!(8, map["bar"]);
}
#[test]
fn macro_allows_trailing_comma() {
let map1 = hashmap! {"x" => 1, "y" => 2};
let map2 = hashmap! {
"x" => 1,
"y" => 2,
};
assert_eq!(map1, map2);
}
#[test]
fn remove_top_level_collisions() {
let pairs = vec![9, 2569, 27145];
let mut map: HashMap> = Default::default();
for k in pairs.clone() {
map.insert(k, k);
}
assert_eq!(pairs.len(), map.len());
let keys: Vec<_> = map.keys().cloned().collect();
for k in keys {
let l = map.len();
assert_eq!(Some(&k), map.get(&k));
map.remove(&k);
assert_eq!(None, map.get(&k));
assert_eq!(l - 1, map.len());
}
}
#[test]
fn entry_api() {
let mut map = hashmap! {"bar" => 5};
map.entry("foo").and_modify(|v| *v += 5).or_insert(1);
assert_eq!(1, map[&"foo"]);
map.entry("foo").and_modify(|v| *v += 5).or_insert(1);
assert_eq!(6, map[&"foo"]);
map.entry("bar").and_modify(|v| *v += 5).or_insert(1);
assert_eq!(10, map[&"bar"]);
assert_eq!(
10,
match map.entry("bar") {
Entry::Occupied(entry) => entry.remove(),
_ => panic!(),
}
);
assert!(!map.contains_key(&"bar"));
}
#[test]
fn refpool_crash() {
let _map = HashMap::::new();
}
#[test]
fn large_map() {
let mut map = HashMap::new();
let size = 32769;
for i in 0..size {
map.insert(i, i);
}
assert_eq!(size, map.len());
for i in 0..size {
assert_eq!(Some(&i), map.get(&i));
}
}
proptest! {
#[test]
fn update_and_length(ref m in collection::hash_map(i16::ANY, i16::ANY, 0..100)) {
let mut map: HashMap> = Default::default();
for (index, (k, v)) in m.iter().enumerate() {
map = map.update(*k, *v);
assert_eq!(Some(v), map.get(k));
assert_eq!(index + 1, map.len());
}
}
#[test]
fn from_iterator(ref m in collection::hash_map(i16::ANY, i16::ANY, 0..100)) {
let map: HashMap =
FromIterator::from_iter(m.iter().map(|(k, v)| (*k, *v)));
assert_eq!(m.len(), map.len());
}
#[test]
fn iterate_over(ref m in collection::hash_map(i16::ANY, i16::ANY, 0..100)) {
let map: HashMap = FromIterator::from_iter(m.iter().map(|(k, v)| (*k, *v)));
assert_eq!(m.len(), map.iter().count());
}
#[test]
fn equality(ref m in collection::hash_map(i16::ANY, i16::ANY, 0..100)) {
let map1: HashMap = FromIterator::from_iter(m.iter().map(|(k, v)| (*k, *v)));
let map2: HashMap = FromIterator::from_iter(m.iter().map(|(k, v)| (*k, *v)));
assert_eq!(map1, map2);
}
#[test]
fn lookup(ref m in collection::hash_map(i16::ANY, i16::ANY, 0..100)) {
let map: HashMap = FromIterator::from_iter(m.iter().map(|(k, v)| (*k, *v)));
for (k, v) in m {
assert_eq!(Some(*v), map.get(k).cloned());
}
}
#[test]
fn without(ref pairs in collection::vec((i16::ANY, i16::ANY), 0..100)) {
let mut m: collections::HashMap =
collections::HashMap::with_hasher(BuildHasherDefault::::default());
for &(ref k, ref v) in pairs {
m.insert(*k, *v);
}
let mut map: HashMap = HashMap::with_hasher(BuildHasherDefault::::default());
for (k, v) in &m {
map = map.update(*k, *v);
}
for k in m.keys() {
let l = map.len();
assert_eq!(m.get(k).cloned(), map.get(k).cloned());
map = map.without(k);
assert_eq!(None, map.get(k));
assert_eq!(l - 1, map.len());
}
}
#[test]
fn insert(ref m in collection::hash_map(i16::ANY, i16::ANY, 0..100)) {
let mut mut_map: HashMap> = Default::default();
let mut map: HashMap> = Default::default();
for (count, (k, v)) in m.iter().enumerate() {
map = map.update(*k, *v);
mut_map.insert(*k, *v);
assert_eq!(count + 1, map.len());
assert_eq!(count + 1, mut_map.len());
}
assert_eq!(map, mut_map);
}
#[test]
fn remove(ref pairs in collection::vec((i16::ANY, i16::ANY), 0..100)) {
let mut m: collections::HashMap =
collections::HashMap::with_hasher(BuildHasherDefault::::default());
for &(ref k, ref v) in pairs {
m.insert(*k, *v);
}
let mut map: HashMap = HashMap::with_hasher(BuildHasherDefault::::default());
for (k, v) in &m {
map.insert(*k, *v);
}
for k in m.keys() {
let l = map.len();
assert_eq!(m.get(k).cloned(), map.get(k).cloned());
map.remove(k);
assert_eq!(None, map.get(k));
assert_eq!(l - 1, map.len());
}
}
#[test]
fn delete_and_reinsert(
ref input in collection::hash_map(i16::ANY, i16::ANY, 1..100),
index_rand in usize::ANY
) {
let index = *input.keys().nth(index_rand % input.len()).unwrap();
let map1: HashMap<_, _> = HashMap::from_iter(input.clone());
let (val, map2) = map1.extract(&index).unwrap();
let map3 = map2.update(index, val);
for key in map2.keys() {
assert!(*key != index);
}
assert_eq!(map1.len(), map2.len() + 1);
assert_eq!(map1, map3);
}
#[test]
fn proptest_works(ref m in proptest::hash_map(0..9999, ".*", 10..100)) {
assert!(m.len() < 100);
assert!(m.len() >= 10);
}
#[test]
fn exact_size_iterator(ref m in proptest::hash_map(i16::ANY, i16::ANY, 0..100)) {
let mut should_be = m.len();
let mut it = m.iter();
loop {
assert_eq!(should_be, it.len());
match it.next() {
None => break,
Some(_) => should_be -= 1,
}
}
assert_eq!(0, it.len());
}
}
}