Skip to main content

weak_table/
ptr_weak_key_hash_map.rs

1//! A hash map where the keys are held by weak pointers and compared by pointer.
2
3use crate::common::*;
4use crate::compat::*;
5
6use super::by_ptr::*;
7use super::traits::*;
8use super::weak_key_hash_map as base;
9
10pub use super::weak_key_hash_map::{
11    Drain, Entry, ExtractIf, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values, ValuesMut,
12};
13pub use super::PtrWeakKeyHashMap;
14
15universal_hashless_members! {
16    PtrWeakKeyHashMap
17    ("`PtrWeakKeyHashMap", a "map")
18    crate::WeakKeyHashMap::with_capacity_and_hasher
19    {K, V}
20}
21
22impl<K: WeakElement, V, S: BuildHasher> PtrWeakKeyHashMap<K, V, S>
23where
24    K::Strong: Deref,
25{
26    universal_key_independent_members! {"mappings"}
27
28    /// The proportion of buckets that
29    /// Gets the requested entry.
30    ///
31    /// expected *O*(1) time; worst-case *O*(*p*) time
32    pub fn entry(&mut self, key: K::Strong) -> Entry<'_, ByPtr<K>, V> {
33        self.0.entry(key)
34    }
35
36    /// Returns a reference to the value corresponding to the key.
37    ///
38    /// Returns `None` if no matching key is found.
39    ///
40    /// expected *O*(1) time; worst-case *O*(*p*) time
41    pub fn get(&self, key: &K::Strong) -> Option<&V> {
42        self.0.get(&(key.deref() as *const _))
43    }
44
45    /// Returns true if the map contains the specified key.
46    ///
47    /// expected *O*(1) time; worst-case *O*(*p*) time
48    pub fn contains_key(&self, key: &K::Strong) -> bool {
49        self.0.contains_key(&(key.deref() as *const _))
50    }
51
52    /// Returns a mutable reference to the value corresponding to the key.
53    ///
54    /// Returns `None` if no matching key is found.
55    ///
56    /// expected *O*(1) time; worst-case *O*(*p*) time
57    pub fn get_mut(&mut self, key: &K::Strong) -> Option<&mut V> {
58        let p = key.deref() as *const _;
59        self.0.get_mut(&p)
60    }
61
62    /// Looks up mutable references to the values corresponding to several keys
63    /// at a time.
64    ///
65    /// (Because of borrowing rules, Rust doesn't allow you to call `get_mut()` again
66    /// while the result of a previous `get_mut()` is still live.  This method exists
67    /// to work around that limitation.)
68    ///
69    /// Only one mutable reference can exist to any given value at a time.
70    /// Therefore, all keys must refer to different values, or this
71    /// method will panic.
72    ///
73    /// expected *O*(1 `N^2`) time; worst-case *O*(*p* `N^2`) time,
74    /// where N is the length of the array.
75    ///
76    /// # Panics
77    ///
78    /// Panics if any keys refer to the same value.
79    pub fn get_disjoint_mut<const N: usize>(&mut self, ks: [&K::Strong; N]) -> [Option<&mut V>; N] {
80        let ks: [*const <K::Strong as Deref>::Target; N] = ks.map(|k| (*k).deref() as *const _);
81        let ks_refs = crate::util::each_ref(&ks);
82
83        self.0
84             .0
85            .get_disjoint_mut(ks_refs)
86            .map(|ent| ent.map(|(_k, v)| v))
87    }
88
89    /// Unconditionally inserts the value, returning the old value if already present. Does not
90    /// replace the key.
91    ///
92    /// expected *O*(1) time; worst-case *O*(*p*) time
93    pub fn insert(&mut self, key: K::Strong, value: V) -> Option<V> {
94        self.0.insert(key, value)
95    }
96
97    /// Removes the entry with the given key, if it exists, and returns the value.
98    ///
99    /// expected *O*(1) time; worst-case *O*(*p*) time
100    pub fn remove(&mut self, key: &K::Strong) -> Option<V> {
101        self.0.remove(&(key.deref() as *const _))
102    }
103
104    /// Removes all mappings not satisfying the given predicate.
105    ///
106    /// Also removes any expired mappings.
107    ///
108    /// *O*(*n*) time
109    pub fn retain<F>(&mut self, f: F)
110    where
111        F: FnMut(K::Strong, &mut V) -> bool,
112    {
113        self.0.retain(f);
114    }
115
116    /// Is this map a submap of the other, using the given value comparison.
117    ///
118    /// In particular, all the keys of self must be in other and the values must compare true with
119    /// value_equal.
120    ///
121    /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is
122    /// `self.capacity()` and *q* is the length of the probe sequences
123    /// in `other`)
124    pub fn submap_with<F, S1, V1>(
125        &self,
126        other: &PtrWeakKeyHashMap<K, V1, S1>,
127        value_equal: F,
128    ) -> bool
129    where
130        F: FnMut(&V, &V1) -> bool,
131        S1: BuildHasher,
132    {
133        self.0.is_submap_with(&other.0, value_equal)
134    }
135
136    /// Is self a submap of other?
137    ///
138    /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is
139    /// `self.capacity()` and *q* is the length of the probe sequences
140    /// in `other`)
141    pub fn is_submap<V1, S1>(&self, other: &PtrWeakKeyHashMap<K, V1, S1>) -> bool
142    where
143        V: PartialEq<V1>,
144        S1: BuildHasher,
145    {
146        self.0.is_submap(&other.0)
147    }
148
149    /// Are the keys of self a subset of the keys of other?
150    ///
151    /// expected *O*(*n*) time; worst-case *O*(*nq*) time (where *n* is
152    /// `self.capacity()` and *q* is the length of the probe sequences
153    /// in `other`)
154    pub fn domain_is_subset<V1, S1>(&self, other: &PtrWeakKeyHashMap<K, V1, S1>) -> bool
155    where
156        S1: BuildHasher,
157    {
158        self.0.domain_is_subset(&other.0)
159    }
160}
161
162impl<K: WeakElement, V, S> PtrWeakKeyHashMap<K, V, S> {
163    /// Gets an iterator over the keys and values.
164    ///
165    /// *O*(1) time
166    pub fn iter(&self) -> Iter<'_, ByPtr<K>, V> {
167        self.0.iter()
168    }
169
170    /// Gets an iterator over the keys.
171    ///
172    /// *O*(1) time
173    pub fn keys(&self) -> Keys<'_, ByPtr<K>, V> {
174        self.0.keys()
175    }
176
177    /// Gets an iterator over the values.
178    ///
179    /// *O*(1) time
180    pub fn values(&self) -> Values<'_, ByPtr<K>, V> {
181        self.0.values()
182    }
183
184    /// Gets an iterator over the keys and mutable values.
185    ///
186    /// *O*(1) time
187    pub fn iter_mut(&mut self) -> IterMut<'_, ByPtr<K>, V> {
188        self.0.iter_mut()
189    }
190
191    /// Gets an iterator over the mutable values.
192    ///
193    /// *O*(1) time
194    pub fn values_mut(&mut self) -> ValuesMut<'_, ByPtr<K>, V> {
195        self.0.values_mut()
196    }
197
198    /// Gets a draining iterator, which removes all the values but retains the storage.
199    ///
200    /// *O*(1) time (and *O*(*n*) time to dispose of the result)
201    pub fn drain(&mut self) -> Drain<'_, ByPtr<K>, V> {
202        self.0.drain()
203    }
204
205    ptr_into_kv_methods! {}
206
207    /// Gets an iterator that removes and returns elements matching a given predicate.
208    ///
209    /// Expired elements are also removed.
210    ///
211    /// If this iterator is dropped before it is completed, then no further
212    /// elements are removed.
213    /// (This is in contrast to the behavior of [`drain`](Self::drain)).
214    ///
215    /// *O*(1) time
216    pub fn extract_if<'a, F>(&'a mut self, f: F) -> ExtractIf<'a, ByPtr<K>, V, F>
217    where
218        F: FnMut(K::Strong, &mut V) -> bool + 'a,
219    {
220        self.0.extract_if(f)
221    }
222}
223
224impl<K, V, V1, S, S1> PartialEq<PtrWeakKeyHashMap<K, V1, S1>> for PtrWeakKeyHashMap<K, V, S>
225where
226    K: WeakElement,
227    K::Strong: Deref,
228    V: PartialEq<V1>,
229    S: BuildHasher,
230    S1: BuildHasher,
231{
232    fn eq(&self, other: &PtrWeakKeyHashMap<K, V1, S1>) -> bool {
233        self.0 == other.0
234    }
235}
236
237impl<K: WeakElement, V: Eq, S: BuildHasher> Eq for PtrWeakKeyHashMap<K, V, S> where K::Strong: Deref {}
238
239impl<'a, K, V, S> Index<&'a K::Strong> for PtrWeakKeyHashMap<K, V, S>
240where
241    K: WeakElement,
242    K::Strong: Deref,
243    S: BuildHasher,
244{
245    type Output = V;
246
247    fn index(&self, index: &'a K::Strong) -> &Self::Output {
248        self.0.index(&(index.deref() as *const _))
249    }
250}
251
252impl<'a, K, V, S> IndexMut<&'a K::Strong> for PtrWeakKeyHashMap<K, V, S>
253where
254    K: WeakElement,
255    K::Strong: Deref,
256    S: BuildHasher,
257{
258    fn index_mut(&mut self, index: &'a K::Strong) -> &mut Self::Output {
259        self.0.index_mut(&(index.deref() as *const _))
260    }
261}
262
263impl<K, V, S> FromIterator<(K::Strong, V)> for PtrWeakKeyHashMap<K, V, S>
264where
265    K: WeakElement,
266    K::Strong: Deref,
267    S: BuildHasher + Default,
268{
269    fn from_iter<T: IntoIterator<Item = (K::Strong, V)>>(iter: T) -> Self {
270        PtrWeakKeyHashMap(base::WeakKeyHashMap::<ByPtr<K>, V, S>::from_iter(iter))
271    }
272}
273
274impl<K, V, const N: usize> From<[(K::Strong, V); N]> for PtrWeakKeyHashMap<K, V, RandomState>
275where
276    K: WeakElement,
277    K::Strong: Deref,
278{
279    /// Converts an array of key-value pairs into a map.
280    ///
281    /// If any entries in the array have equal keys,
282    /// all but one of the corresponding values will be dropped.
283    fn from(value: [(K::Strong, V); N]) -> Self {
284        Self::from_iter(value)
285    }
286}
287
288impl<K, V, S> Extend<(K::Strong, V)> for PtrWeakKeyHashMap<K, V, S>
289where
290    K: WeakElement,
291    K::Strong: Deref,
292    S: BuildHasher,
293{
294    fn extend<T: IntoIterator<Item = (K::Strong, V)>>(&mut self, iter: T) {
295        self.0.extend(iter);
296    }
297}
298
299impl<'a, K, V, S> Extend<(&'a K::Strong, &'a V)> for PtrWeakKeyHashMap<K, V, S>
300where
301    K: 'a + WeakElement,
302    K::Strong: Clone + Deref,
303    V: 'a + Clone,
304    S: BuildHasher,
305{
306    fn extend<T: IntoIterator<Item = (&'a K::Strong, &'a V)>>(&mut self, iter: T) {
307        self.0.extend(iter);
308    }
309}
310
311impl<K, V: Debug, S> Debug for PtrWeakKeyHashMap<K, V, S>
312where
313    K: WeakElement,
314    K::Strong: Debug,
315{
316    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
317        self.0.fmt(f)
318    }
319}
320
321impl<K: WeakElement, V, S> IntoIterator for PtrWeakKeyHashMap<K, V, S> {
322    type Item = (K::Strong, V);
323    type IntoIter = IntoIter<ByPtr<K>, V>;
324
325    /// Creates an owning iterator from `self`.
326    ///
327    /// *O*(1) time (and *O*(*n*) time to dispose of the result)
328    fn into_iter(self) -> Self::IntoIter {
329        self.0.into_iter()
330    }
331}
332
333impl<'a, K: WeakElement, V, S> IntoIterator for &'a PtrWeakKeyHashMap<K, V, S> {
334    type Item = (K::Strong, &'a V);
335    type IntoIter = Iter<'a, ByPtr<K>, V>;
336
337    /// Creates a borrowing iterator from `self`.
338    ///
339    /// *O*(1) time
340    fn into_iter(self) -> Self::IntoIter {
341        (&self.0).into_iter()
342    }
343}
344
345impl<'a, K: WeakElement, V, S> IntoIterator for &'a mut PtrWeakKeyHashMap<K, V, S> {
346    type Item = (K::Strong, &'a mut V);
347    type IntoIter = IterMut<'a, ByPtr<K>, V>;
348
349    /// Creates a borrowing iterator from `self`.
350    ///
351    /// *O*(1) time
352    fn into_iter(self) -> Self::IntoIter {
353        (&mut self.0).into_iter()
354    }
355}
356
357#[cfg(test)]
358mod test {
359    #![allow(clippy::print_stderr)]
360
361    use super::{Entry, PtrWeakKeyHashMap};
362    use crate::{
363        compat::{
364            eprintln, format,
365            rc::{Rc, Weak},
366            Vec,
367        },
368        tests::util::VecDebugAsMap,
369    };
370
371    crate::tests::common::empty_constructor_tests! {PtrWeakKeyHashMap<Weak<u32>, u32>}
372
373    //    fn show_me(weakmap: &PtrWeakKeyHashMap<Weak<u32>, f32>) {
374    //        for (key, _) in weakmap {
375    //            eprint!(" {:2}", *key);
376    //        }
377    //        eprintln!();
378    //    }
379
380    // From https://github.com/tov/weak-table-rs/issues/1#issuecomment-461858060
381    #[test]
382    fn insert_and_check() {
383        let mut rcs: Vec<Rc<u32>> = Vec::new();
384
385        for i in 0..200 {
386            rcs.push(Rc::new(i));
387        }
388
389        let mut weakmap: PtrWeakKeyHashMap<Weak<u32>, f32> = PtrWeakKeyHashMap::new();
390
391        for item in rcs.iter().cloned() {
392            let f = *item as f32 + 0.1;
393            weakmap.insert(item, f);
394        }
395
396        let mut count = 0;
397
398        for item in &rcs {
399            assert!(weakmap.contains_key(item));
400
401            match weakmap.entry(Rc::clone(item)) {
402                Entry::Occupied(_) => count += 1,
403                Entry::Vacant(_) => eprintln!("PointerWeakKeyHashMap: missing: {}", *item),
404            }
405        }
406
407        assert_eq!(count, rcs.len());
408    }
409
410    #[test]
411    fn debug_map() {
412        let rcs: Vec<Rc<u32>> = (0..20).map(Rc::new).collect();
413        let map: PtrWeakKeyHashMap<Weak<u32>, u32> =
414            rcs.iter().map(|n| (n.clone(), **n * 7)).collect();
415        let vec: VecDebugAsMap<_, _> = map.iter().collect();
416        assert_eq!(format!("{map:?}"), format!("{vec:?}"));
417    }
418
419    #[test]
420    fn is_submap() {
421        let mut rcs: Vec<Rc<u32>> = (0..50).map(|_| Rc::new(0)).collect();
422        let weakmap: PtrWeakKeyHashMap<Weak<u32>, u32> =
423            rcs.iter().take(25).map(|n| (n.clone(), **n)).collect();
424        let mut weakmap2 = weakmap.clone();
425
426        assert!(weakmap.is_submap(&weakmap2));
427        assert!(weakmap2.is_submap(&weakmap));
428
429        weakmap2.extend(rcs.iter().skip(25).map(|n| (n.clone(), **n)));
430        assert!(weakmap.is_submap(&weakmap2));
431        assert!(!weakmap2.is_submap(&weakmap));
432        assert!(weakmap.domain_is_subset(&weakmap2));
433        assert!(!weakmap2.domain_is_subset(&weakmap));
434
435        weakmap2.insert(rcs[0].clone(), 12);
436        assert!(!weakmap.is_submap(&weakmap2));
437        assert!(!weakmap2.is_submap(&weakmap));
438        assert!(weakmap.submap_with(&weakmap2, |_v1, _v2| true));
439        assert!(!weakmap2.submap_with(&weakmap, |_v1, _v2| true));
440
441        let _ = rcs.remove(0);
442        assert!(weakmap.is_submap(&weakmap2));
443    }
444}