//! A hash map where the keys are held by weak pointers and compared by pointer. use crate::compat::*; use super::by_ptr::*; use super::traits::*; use super::weak_key_hash_map as base; pub use super::PtrWeakKeyHashMap; pub use super::weak_key_hash_map::{Entry, Iter, IterMut, Keys, Values, ValuesMut, Drain, IntoIter}; impl PtrWeakKeyHashMap where K::Strong: Deref { /// Creates an empty `PtrWeakKeyHashMap`. /// /// *O*(1) time pub fn new() -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::new()) } /// Creates an empty `PtrWeakKeyHashMap` with the given capacity. /// /// *O*(*n*) time pub fn with_capacity(capacity: usize) -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::with_capacity(capacity)) } } impl PtrWeakKeyHashMap where K::Strong: Deref { /// Creates an empty `PtrWeakKeyHashMap` with the given capacity and hasher. /// /// *O*(*n*) time pub fn with_hasher(hash_builder: S) -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::with_hasher(hash_builder)) } /// Creates an empty `PtrWeakKeyHashMap` with the given capacity and hasher. /// /// *O*(*n*) time pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::with_capacity_and_hasher(capacity, hash_builder)) } /// Returns a reference to the map's `BuildHasher`. /// /// *O*(1) time pub fn hasher(&self) -> &S { self.0.hasher() } /// Returns the number of elements the map can hold without reallocating. /// /// *O*(1) time pub fn capacity(&self) -> usize { self.0.capacity() } /// Removes all mappings whose keys have expired. /// /// *O*(*n*) time pub fn remove_expired(&mut self) { self.0.remove_expired() } /// Reserves room for additional elements. /// /// *O*(*n*) time pub fn reserve(&mut self, additional_capacity: usize) { self.0.reserve(additional_capacity) } /// Shrinks the capacity to the minimum allowed to hold the current number of elements. /// /// *O*(*n*) time pub fn shrink_to_fit(&mut self) { self.0.shrink_to_fit() } /// Returns an over-approximation of the number of elements. /// /// *O*(1) time pub fn len(&self) -> usize { self.0.len() } /// Is the map known to be empty? /// /// This could answer `false` for an empty map whose keys have /// expired but have yet to be collected. /// /// *O*(1) time pub fn is_empty(&self) -> bool { self.len() == 0 } /// The proportion of buckets that are used. /// /// This is an over-approximation because of expired keys. /// /// *O*(1) time pub fn load_factor(&self) -> f32 { self.0.load_factor() } /// Gets the requested entry. /// /// expected *O*(1) time; worst-case *O*(*p*) time pub fn entry(&mut self, key: K::Strong) -> Entry, V> { self.0.entry(key) } /// Removes all associations from the map. /// /// *O*(*n*) time pub fn clear(&mut self) { self.0.clear() } /// Returns a reference to the value corresponding to the key. /// /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get(&self, key: &K::Strong) -> Option<&V> { self.0.get(&(key.deref() as *const _)) } /// Returns true if the map contains the specified key. /// /// expected *O*(1) time; worst-case *O*(*p*) time pub fn contains_key(&self, key:&K::Strong) -> bool { self.0.contains_key(&(key.deref() as *const _)) } /// Returns a mutable reference to the value corresponding to the key. /// /// expected *O*(1) time; worst-case *O*(*p*) time pub fn get_mut(&mut self, key: &K::Strong) -> Option<&mut V> { self.0.get_mut(&(key.deref() as *const _)) } /// Unconditionally inserts the value, returning the old value if already present. Does not /// replace the key. /// /// expected *O*(1) time; worst-case *O*(*p*) time pub fn insert(&mut self, key: K::Strong, value: V) -> Option { self.0.insert(key, value) } /// Removes the entry with the given key, if it exists, and returns the value. /// /// expected *O*(1) time; worst-case *O*(*p*) time pub fn remove(&mut self, key: &K::Strong) -> Option { self.0.remove(&(key.deref() as *const _)) } /// Removes all mappings not satisfying the given predicate. /// /// Also removes any expired mappings. /// /// *O*(*n*) time pub fn retain(&mut self, f: F) where F: FnMut(K::Strong, &mut V) -> bool { self.0.retain(f) } /// Is this map a submap of the other, using the given value comparison. /// /// In particular, all the keys of self must be in other and the values must compare true with /// value_equal. /// /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is /// `self.capacity()` and *q* is the length of the probe sequences /// in `other`) pub fn submap_with(&self, other: &PtrWeakKeyHashMap, value_equal: F) -> bool where F: FnMut(&V, &V1) -> bool, S1: BuildHasher { self.0.is_submap_with(&other.0, value_equal) } /// Is self a submap of other? /// /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is /// `self.capacity()` and *q* is the length of the probe sequences /// in `other`) pub fn is_submap(&self, other: &PtrWeakKeyHashMap) -> bool where V: PartialEq, S1: BuildHasher { self.0.is_submap(&other.0) } /// Are the keys of self a subset of the keys of other? /// /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is /// `self.capacity()` and *q* is the length of the probe sequences /// in `other`) pub fn domain_is_subset(&self, other: &PtrWeakKeyHashMap) -> bool where S1: BuildHasher { self.0.domain_is_subset(&other.0) } } impl PtrWeakKeyHashMap where K::Strong: Deref { /// Gets an iterator over the keys and values. /// /// *O*(1) time pub fn iter(&self) -> Iter, V> { self.0.iter() } /// Gets an iterator over the keys. /// /// *O*(1) time pub fn keys(&self) -> Keys, V> { self.0.keys() } /// Gets an iterator over the values. /// /// *O*(1) time pub fn values(&self) -> Values, V> { self.0.values() } /// Gets an iterator over the keys and mutable values. /// /// *O*(1) time pub fn iter_mut(&mut self) -> IterMut, V> { self.0.iter_mut() } /// Gets an iterator over the mutable values. /// /// *O*(1) time pub fn values_mut(&mut self) -> ValuesMut, V> { self.0.values_mut() } /// Gets a draining iterator, which removes all the values but retains the storage. /// /// *O*(1) time (and *O*(*n*) time to dispose of the result) pub fn drain(&mut self) -> Drain, V> { self.0.drain() } } impl PartialEq> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, V: PartialEq, S: BuildHasher, S1: BuildHasher { fn eq(&self, other: &PtrWeakKeyHashMap) -> bool { self.0 == other.0 } } impl Eq for PtrWeakKeyHashMap where K::Strong: Deref { } impl Default for PtrWeakKeyHashMap where K::Strong: Deref { fn default() -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::, V, S>::default()) } } impl<'a, K, V, S> Index<&'a K::Strong> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, S: BuildHasher { type Output = V; fn index(&self, index: &'a K::Strong) -> &Self::Output { self.0.index(&(index.deref() as *const _)) } } impl<'a, K, V, S> IndexMut<&'a K::Strong> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, S: BuildHasher { fn index_mut(&mut self, index: &'a K::Strong) -> &mut Self::Output { self.0.index_mut(&(index.deref() as *const _)) } } impl FromIterator<(K::Strong, V)> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, S: BuildHasher + Default { fn from_iter>(iter: T) -> Self { PtrWeakKeyHashMap(base::WeakKeyHashMap::, V, S>::from_iter(iter)) } } impl Extend<(K::Strong, V)> for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Deref, S: BuildHasher { fn extend>(&mut self, iter: T) { self.0.extend(iter) } } impl<'a, K, V, S> Extend<(&'a K::Strong, &'a V)> for PtrWeakKeyHashMap where K: 'a + WeakElement, K::Strong: Clone + Deref, V: 'a + Clone, S: BuildHasher { fn extend>(&mut self, iter: T) { self.0.extend(iter) } } impl Debug for PtrWeakKeyHashMap where K: WeakElement, K::Strong: Debug { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(f) } } impl IntoIterator for PtrWeakKeyHashMap { type Item = (K::Strong, V); type IntoIter = IntoIter, V>; /// Creates an owning iterator from `self`. /// /// *O*(1) time (and *O*(*n*) time to dispose of the result) fn into_iter(self) -> Self::IntoIter { self.0.into_iter() } } impl<'a, K: WeakElement, V, S> IntoIterator for &'a PtrWeakKeyHashMap { type Item = (K::Strong, &'a V); type IntoIter = Iter<'a, ByPtr, V>; /// Creates a borrowing iterator from `self`. /// /// *O*(1) time fn into_iter(self) -> Self::IntoIter { (&self.0).into_iter() } } impl<'a, K: WeakElement, V, S> IntoIterator for &'a mut PtrWeakKeyHashMap { type Item = (K::Strong, &'a mut V); type IntoIter = IterMut<'a, ByPtr, V>; /// Creates a borrowing iterator from `self`. /// /// *O*(1) time fn into_iter(self) -> Self::IntoIter { (&mut self.0).into_iter() } } #[cfg(test)] mod test { use crate::compat::{ eprintln, rc::{Rc, Weak}, Vec, }; use super::{Entry, PtrWeakKeyHashMap}; // fn show_me(weakmap: &PtrWeakKeyHashMap, f32>) { // for (key, _) in weakmap { // eprint!(" {:2}", *key); // } // eprintln!(); // } // From https://github.com/tov/weak-table-rs/issues/1#issuecomment-461858060 #[test] fn insert_and_check() { let mut rcs: Vec> = Vec::new(); for i in 0 .. 200 { rcs.push(Rc::new(i)); } let mut weakmap: PtrWeakKeyHashMap, f32> = PtrWeakKeyHashMap::new(); for item in rcs.iter().cloned() { let f = *item as f32 + 0.1; weakmap.insert(item, f); } let mut count = 0; for item in &rcs { assert!(weakmap.contains_key(item)); match weakmap.entry(Rc::clone(item)) { Entry::Occupied(_) => count += 1, Entry::Vacant(_) => eprintln!("PointerWeakKeyHashMap: missing: {}", *item), } } assert_eq!( count, rcs.len() ); } }