Skip to main content

weak_table/
ptr_weak_weak_hash_map.rs

1//! A hash map where the keys and values are both held by weak pointers, and keys are compared by
2//! pointer.
3
4use crate::compat::*;
5
6use super::by_ptr::*;
7use super::traits::*;
8use super::weak_weak_hash_map as base;
9
10pub use super::weak_weak_hash_map::{Drain, Entry, IntoIter, Iter, Keys, Values};
11pub use super::PtrWeakWeakHashMap;
12
13impl<K: WeakElement, V: WeakElement> PtrWeakWeakHashMap<K, V, RandomState>
14where
15    K::Strong: Deref,
16{
17    /// Creates an empty `PtrWeakWeakHashMap`.
18    ///
19    /// *O*(1) time
20    pub fn new() -> Self {
21        PtrWeakWeakHashMap(base::WeakWeakHashMap::new())
22    }
23
24    /// Creates an empty `PtrWeakWeakHashMap` with the given capacity.
25    ///
26    /// *O*(*n*) time
27    pub fn with_capacity(capacity: usize) -> Self {
28        PtrWeakWeakHashMap(base::WeakWeakHashMap::with_capacity(capacity))
29    }
30}
31
32impl<K: WeakElement, V: WeakElement, S: BuildHasher> PtrWeakWeakHashMap<K, V, S>
33where
34    K::Strong: Deref,
35{
36    /// Creates an empty `PtrWeakWeakHashMap` with the given hasher.
37    ///
38    /// *O*(*n*) time
39    pub fn with_hasher(hash_builder: S) -> Self {
40        PtrWeakWeakHashMap(base::WeakWeakHashMap::with_hasher(hash_builder))
41    }
42
43    /// Creates an empty `PtrWeakWeakHashMap` with the given capacity and hasher.
44    ///
45    /// *O*(*n*) time
46    pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> Self {
47        PtrWeakWeakHashMap(base::WeakWeakHashMap::with_capacity_and_hasher(
48            capacity,
49            hash_builder,
50        ))
51    }
52
53    /// Returns a reference to the map's `BuildHasher`.
54    ///
55    /// *O*(1) time
56    pub fn hasher(&self) -> &S {
57        self.0.hasher()
58    }
59
60    /// Returns the number of elements the map can hold without reallocating.
61    ///
62    /// *O*(1) time
63    pub fn capacity(&self) -> usize {
64        self.0.capacity()
65    }
66
67    /// Removes all mappings whose keys have expired.
68    ///
69    /// *O*(*n*) time
70    pub fn remove_expired(&mut self) {
71        self.0.remove_expired();
72    }
73
74    /// Reserves room for additional elements.
75    ///
76    /// This method ensures that at least `additional_capacity` insertions
77    /// may be performed without reallocating.
78    ///
79    /// *O*(*n*) time
80    pub fn reserve(&mut self, additional_capacity: usize) {
81        self.0.reserve(additional_capacity);
82    }
83
84    /// Shrinks the capacity to the minimum allowed to hold the current number of elements.
85    ///
86    /// *O*(*n*) time
87    pub fn shrink_to_fit(&mut self) {
88        self.0.shrink_to_fit();
89    }
90
91    /// Returns an over-approximation of the number of elements.
92    ///
93    /// (This is an over-approximation because it includes expired elements.)
94    ///
95    /// (This is an over-approximation because it includes expired elements.)
96    ///    /// *O*(1) time
97    pub fn len(&self) -> usize {
98        self.0.len()
99    }
100
101    /// Is the map empty?
102    ///
103    /// Note that this may return false even if all keys in the map have
104    /// expired, if they haven't been collected yet.
105    ///
106    /// *O*(1) time
107    pub fn is_empty(&self) -> bool {
108        self.0.is_empty()
109    }
110
111    /// The proportion of buckets that are used.
112    ///
113    /// This is an over-approximation because of expired keys.
114    ///
115    /// *O*(1) time
116    pub fn load_factor(&self) -> f32 {
117        self.0.load_factor()
118    }
119
120    /// Gets the requested entry.
121    ///
122    /// expected *O*(1) time; worst-case *O*(*p*) time
123    pub fn entry(&mut self, key: K::Strong) -> Entry<'_, ByPtr<K>, V> {
124        self.0.entry(key)
125    }
126
127    /// Removes all associations from the map.
128    ///
129    /// *O*(*n*) time
130    pub fn clear(&mut self) {
131        self.0.clear();
132    }
133
134    /// Returns a reference to the value corresponding to the key.
135    ///
136    /// Returns `None` if no matching key is found.
137    ///
138    /// expected *O*(1) time; worst-case *O*(*p*) time
139    pub fn get(&self, key: &K::Strong) -> Option<V::Strong> {
140        self.0.get(&(key.deref() as *const _))
141    }
142
143    /// Returns true if the map contains the specified key.
144    ///
145    /// expected *O*(1) time; worst-case *O*(*p*) time
146    pub fn contains_key(&self, key: &K::Strong) -> bool {
147        self.0.contains_key(&(key.deref() as *const _))
148    }
149
150    /// Unconditionally inserts the value, returning the old value if already present. Does not
151    /// replace the key.
152    ///
153    /// expected *O*(1) time; worst-case *O*(*p*) time
154    pub fn insert(&mut self, key: K::Strong, value: V::Strong) -> Option<V::Strong> {
155        self.0.insert(key, value)
156    }
157
158    /// Removes the entry with the given key, if it exists, and returns the value.
159    ///
160    /// expected *O*(1) time; worst-case *O*(*p*) time
161    pub fn remove(&mut self, key: &K::Strong) -> Option<V::Strong> {
162        self.0.remove(&(key.deref() as *const _))
163    }
164
165    /// Removes all mappings not satisfying the given predicate.
166    ///
167    /// Also removes any expired mappings.
168    ///
169    /// *O*(*n*) time
170    pub fn retain<F>(&mut self, f: F)
171    where
172        F: FnMut(K::Strong, V::Strong) -> bool,
173    {
174        self.0.retain(f);
175    }
176
177    /// Is this map a submap of the other, using the given value comparison.
178    ///
179    /// In particular, all the keys of self must be in other and the values must compare true with
180    /// value_equal.
181    ///
182    /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is
183    /// `self.capacity()` and *q* is the length of the probe sequences
184    /// in `other`)
185    pub fn submap_with<F, S1, V1>(
186        &self,
187        other: &PtrWeakWeakHashMap<K, V1, S1>,
188        value_equal: F,
189    ) -> bool
190    where
191        F: FnMut(V::Strong, V1::Strong) -> bool,
192        V1: WeakElement,
193        S1: BuildHasher,
194    {
195        self.0.is_submap_with(&other.0, value_equal)
196    }
197
198    /// Is self a submap of other?
199    ///
200    /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is
201    /// `self.capacity()` and *q* is the length of the probe sequences
202    /// in `other`)
203    pub fn is_submap<V1, S1>(&self, other: &PtrWeakWeakHashMap<K, V1, S1>) -> bool
204    where
205        V1: WeakElement,
206        V::Strong: PartialEq<V1::Strong>,
207        S1: BuildHasher,
208    {
209        self.0.is_submap(&other.0)
210    }
211
212    /// Are the keys of self a subset of the keys of other?
213    ///
214    /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is
215    /// `self.capacity()` and *q* is the length of the probe sequences
216    /// in `other`)
217    pub fn domain_is_subset<V1, S1>(&self, other: &PtrWeakWeakHashMap<K, V1, S1>) -> bool
218    where
219        V1: WeakElement,
220        S1: BuildHasher,
221    {
222        self.0.domain_is_subset(&other.0)
223    }
224}
225
226impl<K: WeakElement, V: WeakElement, S> PtrWeakWeakHashMap<K, V, S>
227where
228    K::Strong: Deref,
229{
230    /// Gets an iterator over the keys and values.
231    ///
232    /// *O*(1) time
233    pub fn iter(&self) -> Iter<'_, ByPtr<K>, V> {
234        self.0.iter()
235    }
236
237    /// Gets an iterator over the keys.
238    ///
239    /// *O*(1) time
240    pub fn keys(&self) -> Keys<'_, ByPtr<K>, V> {
241        self.0.keys()
242    }
243
244    /// Gets an iterator over the values.
245    ///
246    /// *O*(1) time
247    pub fn values(&self) -> Values<'_, ByPtr<K>, V> {
248        self.0.values()
249    }
250
251    /// Gets a draining iterator, which removes all the values but retains the storage.
252    ///
253    /// *O*(1) time (and *O*(*n*) time to dispose of the result)
254    pub fn drain(&mut self) -> Drain<'_, ByPtr<K>, V> {
255        self.0.drain()
256    }
257}
258
259impl<K, V, V1, S, S1> PartialEq<PtrWeakWeakHashMap<K, V1, S1>> for PtrWeakWeakHashMap<K, V, S>
260where
261    K: WeakElement,
262    K::Strong: Deref,
263    V: WeakElement,
264    V1: WeakElement,
265    V::Strong: PartialEq<V1::Strong>,
266    S: BuildHasher,
267    S1: BuildHasher,
268{
269    fn eq(&self, other: &PtrWeakWeakHashMap<K, V1, S1>) -> bool {
270        self.0 == other.0
271    }
272}
273
274impl<K: WeakElement, V: WeakElement, S: BuildHasher> Eq for PtrWeakWeakHashMap<K, V, S>
275where
276    K::Strong: Deref,
277    V::Strong: Eq,
278{
279}
280
281impl<K: WeakElement, V: WeakElement, S: BuildHasher + Default> Default
282    for PtrWeakWeakHashMap<K, V, S>
283where
284    K::Strong: Deref,
285{
286    fn default() -> Self {
287        PtrWeakWeakHashMap(base::WeakWeakHashMap::<ByPtr<K>, V, S>::default())
288    }
289}
290
291impl<K, V, S> FromIterator<(K::Strong, V::Strong)> for PtrWeakWeakHashMap<K, V, S>
292where
293    K: WeakElement,
294    K::Strong: Deref,
295    V: WeakElement,
296    S: BuildHasher + Default,
297{
298    fn from_iter<T: IntoIterator<Item = (K::Strong, V::Strong)>>(iter: T) -> Self {
299        PtrWeakWeakHashMap(base::WeakWeakHashMap::<ByPtr<K>, V, S>::from_iter(iter))
300    }
301}
302
303impl<K, V, S> Extend<(K::Strong, V::Strong)> for PtrWeakWeakHashMap<K, V, S>
304where
305    K: WeakElement,
306    K::Strong: Deref,
307    V: WeakElement,
308    S: BuildHasher,
309{
310    fn extend<T: IntoIterator<Item = (K::Strong, V::Strong)>>(&mut self, iter: T) {
311        self.0.extend(iter);
312    }
313}
314
315impl<K, V, S> Debug for PtrWeakWeakHashMap<K, V, S>
316where
317    K: WeakElement,
318    K::Strong: Debug,
319    V: WeakElement,
320    V::Strong: Debug,
321{
322    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
323        self.0.fmt(f)
324    }
325}
326
327impl<K: WeakElement, V: WeakElement, S> IntoIterator for PtrWeakWeakHashMap<K, V, S> {
328    type Item = (K::Strong, V::Strong);
329    type IntoIter = IntoIter<ByPtr<K>, V>;
330
331    /// Creates an owning iterator from `self`.
332    ///
333    /// *O*(1) time (and *O*(*n*) time to dispose of the result)
334    fn into_iter(self) -> Self::IntoIter {
335        self.0.into_iter()
336    }
337}
338
339impl<'a, K: WeakElement, V: WeakElement, S> IntoIterator for &'a PtrWeakWeakHashMap<K, V, S> {
340    type Item = (K::Strong, V::Strong);
341    type IntoIter = Iter<'a, ByPtr<K>, V>;
342
343    /// Creates a borrowing iterator from `self`.
344    ///
345    /// *O*(1) time
346    fn into_iter(self) -> Self::IntoIter {
347        (&self.0).into_iter()
348    }
349}
350
351#[cfg(test)]
352mod test {
353    #![allow(clippy::print_stderr)]
354
355    use super::{Entry, PtrWeakWeakHashMap};
356    use crate::compat::{
357        eprintln,
358        rc::{Rc, Weak},
359        Vec,
360    };
361
362    //    fn show_me(weakmap: &PtrWeakWeakHashMap<Weak<u32>, Weak<f32>>) {
363    //        for (key, _) in weakmap {
364    //            eprint!(" {:2}", *key);
365    //        }
366    //        eprintln!();
367    //    }
368
369    // From https://github.com/tov/weak-table-rs/issues/1#issuecomment-461858060
370    #[test]
371    fn insert_and_check() {
372        let mut rcs: Vec<(Rc<u32>, Rc<f32>)> = Vec::new();
373
374        for i in 0..200 {
375            rcs.push((Rc::new(i), Rc::new(i as f32 + 0.1)));
376        }
377
378        let mut weakmap: PtrWeakWeakHashMap<Weak<u32>, Weak<f32>> = PtrWeakWeakHashMap::new();
379
380        for (key, value) in rcs.iter().cloned() {
381            weakmap.insert(key, value);
382            //            show_me(&weakmap);
383        }
384
385        let mut count = 0;
386
387        for (key, value) in &rcs {
388            assert!(weakmap.contains_key(key));
389
390            match weakmap.entry(Rc::clone(key)) {
391                Entry::Occupied(occ) => {
392                    assert_eq!(occ.get(), value);
393                    count += 1;
394                }
395                Entry::Vacant(_) => {
396                    eprintln!("PointerWeakWeakHashMap: missing: {}", *key);
397                }
398            }
399        }
400
401        assert_eq!(count, rcs.len());
402    }
403}