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
274#[cfg(any(test, feature = "std", feature = "ahash"))]
275impl<K, V, const N: usize> From<[(K::Strong, V); N]> for PtrWeakKeyHashMap<K, V, RandomState>
276where
277    K: WeakElement,
278    K::Strong: Deref,
279{
280    /// Converts an array of key-value pairs into a map.
281    ///
282    /// If any entries in the array have equal keys,
283    /// all but one of the corresponding values will be dropped.
284    fn from(value: [(K::Strong, V); N]) -> Self {
285        Self::from_iter(value)
286    }
287}
288
289impl<K, V, S> Extend<(K::Strong, V)> for PtrWeakKeyHashMap<K, V, S>
290where
291    K: WeakElement,
292    K::Strong: Deref,
293    S: BuildHasher,
294{
295    fn extend<T: IntoIterator<Item = (K::Strong, V)>>(&mut self, iter: T) {
296        self.0.extend(iter);
297    }
298}
299
300impl<'a, K, V, S> Extend<(&'a K::Strong, &'a V)> for PtrWeakKeyHashMap<K, V, S>
301where
302    K: 'a + WeakElement,
303    K::Strong: Clone + Deref,
304    V: 'a + Clone,
305    S: BuildHasher,
306{
307    fn extend<T: IntoIterator<Item = (&'a K::Strong, &'a V)>>(&mut self, iter: T) {
308        self.0.extend(iter);
309    }
310}
311
312impl<K, V: Debug, S> Debug for PtrWeakKeyHashMap<K, V, S>
313where
314    K: WeakElement,
315    K::Strong: Debug,
316{
317    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
318        self.0.fmt(f)
319    }
320}
321
322impl<K: WeakElement, V, S> IntoIterator for PtrWeakKeyHashMap<K, V, S> {
323    type Item = (K::Strong, V);
324    type IntoIter = IntoIter<ByPtr<K>, V>;
325
326    /// Creates an owning iterator from `self`.
327    ///
328    /// *O*(1) time (and *O*(*n*) time to dispose of the result)
329    fn into_iter(self) -> Self::IntoIter {
330        self.0.into_iter()
331    }
332}
333
334impl<'a, K: WeakElement, V, S> IntoIterator for &'a PtrWeakKeyHashMap<K, V, S> {
335    type Item = (K::Strong, &'a V);
336    type IntoIter = Iter<'a, ByPtr<K>, V>;
337
338    /// Creates a borrowing iterator from `self`.
339    ///
340    /// *O*(1) time
341    fn into_iter(self) -> Self::IntoIter {
342        (&self.0).into_iter()
343    }
344}
345
346impl<'a, K: WeakElement, V, S> IntoIterator for &'a mut PtrWeakKeyHashMap<K, V, S> {
347    type Item = (K::Strong, &'a mut V);
348    type IntoIter = IterMut<'a, ByPtr<K>, V>;
349
350    /// Creates a borrowing iterator from `self`.
351    ///
352    /// *O*(1) time
353    fn into_iter(self) -> Self::IntoIter {
354        (&mut self.0).into_iter()
355    }
356}
357
358#[cfg(test)]
359mod test {
360    #![allow(clippy::print_stderr)]
361    // TODO 050: remove.
362    #![cfg_attr(feature = "ahash", allow(deprecated))]
363
364    use super::{Entry, PtrWeakKeyHashMap};
365    use crate::{
366        compat::{
367            eprintln, format,
368            rc::{Rc, Weak},
369            Vec,
370        },
371        tests::util::VecDebugAsMap,
372    };
373
374    crate::tests::common::empty_constructor_tests! {PtrWeakKeyHashMap<Weak<u32>, u32>}
375
376    //    fn show_me(weakmap: &PtrWeakKeyHashMap<Weak<u32>, f32>) {
377    //        for (key, _) in weakmap {
378    //            eprint!(" {:2}", *key);
379    //        }
380    //        eprintln!();
381    //    }
382
383    // From https://github.com/tov/weak-table-rs/issues/1#issuecomment-461858060
384    #[test]
385    fn insert_and_check() {
386        let mut rcs: Vec<Rc<u32>> = Vec::new();
387
388        for i in 0..200 {
389            rcs.push(Rc::new(i));
390        }
391
392        let mut weakmap: PtrWeakKeyHashMap<Weak<u32>, f32> = PtrWeakKeyHashMap::new();
393
394        for item in rcs.iter().cloned() {
395            let f = *item as f32 + 0.1;
396            weakmap.insert(item, f);
397        }
398
399        let mut count = 0;
400
401        for item in &rcs {
402            assert!(weakmap.contains_key(item));
403
404            match weakmap.entry(Rc::clone(item)) {
405                Entry::Occupied(_) => count += 1,
406                Entry::Vacant(_) => eprintln!("PointerWeakKeyHashMap: missing: {}", *item),
407            }
408        }
409
410        assert_eq!(count, rcs.len());
411    }
412
413    #[test]
414    fn debug_map() {
415        let rcs: Vec<Rc<u32>> = (0..20).map(Rc::new).collect();
416        let map: PtrWeakKeyHashMap<Weak<u32>, u32> =
417            rcs.iter().map(|n| (n.clone(), **n * 7)).collect();
418        let vec: VecDebugAsMap<_, _> = map.iter().collect();
419        assert_eq!(format!("{map:?}"), format!("{vec:?}"));
420    }
421
422    #[test]
423    fn is_submap() {
424        let mut rcs: Vec<Rc<u32>> = (0..50).map(|_| Rc::new(0)).collect();
425        let weakmap: PtrWeakKeyHashMap<Weak<u32>, u32> =
426            rcs.iter().take(25).map(|n| (n.clone(), **n)).collect();
427        let mut weakmap2 = weakmap.clone();
428
429        assert!(weakmap.is_submap(&weakmap2));
430        assert!(weakmap2.is_submap(&weakmap));
431
432        weakmap2.extend(rcs.iter().skip(25).map(|n| (n.clone(), **n)));
433        assert!(weakmap.is_submap(&weakmap2));
434        assert!(!weakmap2.is_submap(&weakmap));
435        assert!(weakmap.domain_is_subset(&weakmap2));
436        assert!(!weakmap2.domain_is_subset(&weakmap));
437
438        weakmap2.insert(rcs[0].clone(), 12);
439        assert!(!weakmap.is_submap(&weakmap2));
440        assert!(!weakmap2.is_submap(&weakmap));
441        assert!(weakmap.submap_with(&weakmap2, |_v1, _v2| true));
442        assert!(!weakmap2.submap_with(&weakmap, |_v1, _v2| true));
443
444        let _ = rcs.remove(0);
445        assert!(weakmap.is_submap(&weakmap2));
446    }
447}