use crate::common::*;
use crate::compat::*;
use super::by_ptr::*;
use super::traits::*;
use super::weak_key_hash_map as base;
pub use super::weak_key_hash_map::{
Drain, Entry, ExtractIf, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values, ValuesMut,
};
pub use super::PtrWeakKeyHashMap;
universal_hashless_members! {
PtrWeakKeyHashMap
("`PtrWeakKeyHashMap", a "map")
crate::WeakKeyHashMap::with_capacity_and_hasher
{K, V}
}
impl<K: WeakElement, V, S: BuildHasher> PtrWeakKeyHashMap<K, V, S>
where
K::Strong: Deref,
{
universal_key_independent_members! {"mappings"}
pub fn entry(&mut self, key: K::Strong) -> Entry<'_, ByPtr<K>, V> {
self.0.entry(key)
}
pub fn get(&self, key: &K::Strong) -> Option<&V> {
self.0.get(&(key.deref() as *const _))
}
pub fn contains_key(&self, key: &K::Strong) -> bool {
self.0.contains_key(&(key.deref() as *const _))
}
pub fn get_mut(&mut self, key: &K::Strong) -> Option<&mut V> {
let p = key.deref() as *const _;
self.0.get_mut(&p)
}
pub fn get_disjoint_mut<const N: usize>(&mut self, ks: [&K::Strong; N]) -> [Option<&mut V>; N] {
let ks: [*const <K::Strong as Deref>::Target; N] = ks.map(|k| (*k).deref() as *const _);
let ks_refs = crate::util::each_ref(&ks);
self.0
.0
.get_disjoint_mut(ks_refs)
.map(|ent| ent.map(|(_k, v)| v))
}
pub fn insert(&mut self, key: K::Strong, value: V) -> Option<V> {
self.0.insert(key, value)
}
pub fn remove(&mut self, key: &K::Strong) -> Option<V> {
self.0.remove(&(key.deref() as *const _))
}
pub fn retain<F>(&mut self, f: F)
where
F: FnMut(K::Strong, &mut V) -> bool,
{
self.0.retain(f);
}
pub fn submap_with<F, S1, V1>(
&self,
other: &PtrWeakKeyHashMap<K, V1, S1>,
value_equal: F,
) -> bool
where
F: FnMut(&V, &V1) -> bool,
S1: BuildHasher,
{
self.0.is_submap_with(&other.0, value_equal)
}
pub fn is_submap<V1, S1>(&self, other: &PtrWeakKeyHashMap<K, V1, S1>) -> bool
where
V: PartialEq<V1>,
S1: BuildHasher,
{
self.0.is_submap(&other.0)
}
pub fn domain_is_subset<V1, S1>(&self, other: &PtrWeakKeyHashMap<K, V1, S1>) -> bool
where
S1: BuildHasher,
{
self.0.domain_is_subset(&other.0)
}
}
impl<K: WeakElement, V, S> PtrWeakKeyHashMap<K, V, S> {
pub fn iter(&self) -> Iter<'_, ByPtr<K>, V> {
self.0.iter()
}
pub fn keys(&self) -> Keys<'_, ByPtr<K>, V> {
self.0.keys()
}
pub fn values(&self) -> Values<'_, ByPtr<K>, V> {
self.0.values()
}
pub fn iter_mut(&mut self) -> IterMut<'_, ByPtr<K>, V> {
self.0.iter_mut()
}
pub fn values_mut(&mut self) -> ValuesMut<'_, ByPtr<K>, V> {
self.0.values_mut()
}
pub fn drain(&mut self) -> Drain<'_, ByPtr<K>, V> {
self.0.drain()
}
ptr_into_kv_methods! {}
pub fn extract_if<'a, F>(&'a mut self, f: F) -> ExtractIf<'a, ByPtr<K>, V, F>
where
F: FnMut(K::Strong, &mut V) -> bool + 'a,
{
self.0.extract_if(f)
}
}
impl<K, V, V1, S, S1> PartialEq<PtrWeakKeyHashMap<K, V1, S1>> for PtrWeakKeyHashMap<K, V, S>
where
K: WeakElement,
K::Strong: Deref,
V: PartialEq<V1>,
S: BuildHasher,
S1: BuildHasher,
{
fn eq(&self, other: &PtrWeakKeyHashMap<K, V1, S1>) -> bool {
self.0 == other.0
}
}
impl<K: WeakElement, V: Eq, S: BuildHasher> Eq for PtrWeakKeyHashMap<K, V, S> where K::Strong: Deref {}
impl<'a, K, V, S> Index<&'a K::Strong> for PtrWeakKeyHashMap<K, V, S>
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<K, V, S>
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<K, V, S> FromIterator<(K::Strong, V)> for PtrWeakKeyHashMap<K, V, S>
where
K: WeakElement,
K::Strong: Deref,
S: BuildHasher + Default,
{
fn from_iter<T: IntoIterator<Item = (K::Strong, V)>>(iter: T) -> Self {
PtrWeakKeyHashMap(base::WeakKeyHashMap::<ByPtr<K>, V, S>::from_iter(iter))
}
}
#[cfg(any(test, feature = "std", feature = "ahash"))]
impl<K, V, const N: usize> From<[(K::Strong, V); N]> for PtrWeakKeyHashMap<K, V, RandomState>
where
K: WeakElement,
K::Strong: Deref,
{
fn from(value: [(K::Strong, V); N]) -> Self {
Self::from_iter(value)
}
}
impl<K, V, S> Extend<(K::Strong, V)> for PtrWeakKeyHashMap<K, V, S>
where
K: WeakElement,
K::Strong: Deref,
S: BuildHasher,
{
fn extend<T: IntoIterator<Item = (K::Strong, V)>>(&mut self, iter: T) {
self.0.extend(iter);
}
}
impl<'a, K, V, S> Extend<(&'a K::Strong, &'a V)> for PtrWeakKeyHashMap<K, V, S>
where
K: 'a + WeakElement,
K::Strong: Clone + Deref,
V: 'a + Clone,
S: BuildHasher,
{
fn extend<T: IntoIterator<Item = (&'a K::Strong, &'a V)>>(&mut self, iter: T) {
self.0.extend(iter);
}
}
impl<K, V: Debug, S> Debug for PtrWeakKeyHashMap<K, V, S>
where
K: WeakElement,
K::Strong: Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
impl<K: WeakElement, V, S> IntoIterator for PtrWeakKeyHashMap<K, V, S> {
type Item = (K::Strong, V);
type IntoIter = IntoIter<ByPtr<K>, V>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
impl<'a, K: WeakElement, V, S> IntoIterator for &'a PtrWeakKeyHashMap<K, V, S> {
type Item = (K::Strong, &'a V);
type IntoIter = Iter<'a, ByPtr<K>, V>;
fn into_iter(self) -> Self::IntoIter {
(&self.0).into_iter()
}
}
impl<'a, K: WeakElement, V, S> IntoIterator for &'a mut PtrWeakKeyHashMap<K, V, S> {
type Item = (K::Strong, &'a mut V);
type IntoIter = IterMut<'a, ByPtr<K>, V>;
fn into_iter(self) -> Self::IntoIter {
(&mut self.0).into_iter()
}
}
#[cfg(test)]
mod test {
#![allow(clippy::print_stderr)]
#![cfg_attr(feature = "ahash", allow(deprecated))]
use super::{Entry, PtrWeakKeyHashMap};
use crate::{
compat::{
eprintln, format,
rc::{Rc, Weak},
Vec,
},
tests::util::VecDebugAsMap,
};
crate::tests::common::empty_constructor_tests! {PtrWeakKeyHashMap<Weak<u32>, u32>}
#[test]
fn insert_and_check() {
let mut rcs: Vec<Rc<u32>> = Vec::new();
for i in 0..200 {
rcs.push(Rc::new(i));
}
let mut weakmap: PtrWeakKeyHashMap<Weak<u32>, 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());
}
#[test]
fn debug_map() {
let rcs: Vec<Rc<u32>> = (0..20).map(Rc::new).collect();
let map: PtrWeakKeyHashMap<Weak<u32>, u32> =
rcs.iter().map(|n| (n.clone(), **n * 7)).collect();
let vec: VecDebugAsMap<_, _> = map.iter().collect();
assert_eq!(format!("{map:?}"), format!("{vec:?}"));
}
#[test]
fn is_submap() {
let mut rcs: Vec<Rc<u32>> = (0..50).map(|_| Rc::new(0)).collect();
let weakmap: PtrWeakKeyHashMap<Weak<u32>, u32> =
rcs.iter().take(25).map(|n| (n.clone(), **n)).collect();
let mut weakmap2 = weakmap.clone();
assert!(weakmap.is_submap(&weakmap2));
assert!(weakmap2.is_submap(&weakmap));
weakmap2.extend(rcs.iter().skip(25).map(|n| (n.clone(), **n)));
assert!(weakmap.is_submap(&weakmap2));
assert!(!weakmap2.is_submap(&weakmap));
assert!(weakmap.domain_is_subset(&weakmap2));
assert!(!weakmap2.domain_is_subset(&weakmap));
weakmap2.insert(rcs[0].clone(), 12);
assert!(!weakmap.is_submap(&weakmap2));
assert!(!weakmap2.is_submap(&weakmap));
assert!(weakmap.submap_with(&weakmap2, |_v1, _v2| true));
assert!(!weakmap2.submap_with(&weakmap, |_v1, _v2| true));
let _ = rcs.remove(0);
assert!(weakmap.is_submap(&weakmap2));
}
}