use std::collections::hash_map::RandomState;
use std::{cmp, hash};
use papaya::Equivalent;
#[derive(Debug, Clone, Default)]
pub struct HashMap<K, V, S = RandomState>(papaya::HashMap<K, V, S>)
where
K: hash::Hash + cmp::Eq,
V: Clone,
S: hash::BuildHasher + Default;
impl<K, V, S> HashMap<K, V, S>
where
K: hash::Hash + cmp::Eq,
V: Clone,
S: hash::BuildHasher + Default,
{
pub fn new() -> Self {
Self(Default::default())
}
pub fn insert(&self, key: K, value: V) {
self.0.pin().insert(key, value);
}
pub fn get<Q>(&self, key: &Q) -> Option<V>
where
Q: Equivalent<K> + hash::Hash + ?Sized,
{
self.0.pin().get(key).cloned()
}
pub fn contains_key<Q>(&self, key: &Q) -> bool
where
Q: Equivalent<K> + hash::Hash + ?Sized,
{
self.0.pin().contains_key(key)
}
pub fn values(&self) -> Vec<V> {
self.0.pin().values().cloned().collect()
}
pub fn to_vec(&self) -> Vec<(K, V)>
where
K: Clone,
{
let map = self.0.pin();
let mut vec = Vec::with_capacity(map.len());
for (k, v) in map.iter() {
vec.push((k.clone(), v.clone()));
}
vec
}
pub fn remove<Q>(&self, key: &Q)
where
Q: Equivalent<K> + hash::Hash + ?Sized,
{
self.0.pin().remove(key);
}
pub fn take<Q>(&self, key: &Q) -> Option<V>
where
Q: Equivalent<K> + hash::Hash + ?Sized,
{
self.0.pin().remove(key).cloned()
}
pub fn clear(&self) {
self.0.pin().clear();
}
pub fn len(&self) -> usize {
self.0.pin().len()
}
pub fn is_empty(&self) -> bool {
self.0.pin().is_empty()
}
pub fn retain<F>(&self, f: F)
where
F: FnMut(&K, &V) -> bool,
{
self.0.pin().retain(f);
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_basic_operations() {
let map: HashMap<String, i32> = HashMap::new();
map.insert("key1".to_string(), 1);
map.insert("key2".to_string(), 2);
assert_eq!(map.get(&"key1".to_string()), Some(1));
assert_eq!(map.get(&"key2".to_string()), Some(2));
assert_eq!(map.get(&"key3".to_string()), None);
assert!(map.contains_key(&"key1".to_string()));
assert!(!map.contains_key(&"key3".to_string()));
assert_eq!(map.len(), 2);
assert!(!map.is_empty());
map.remove(&"key1".to_string());
assert_eq!(map.get(&"key1".to_string()), None);
assert_eq!(map.len(), 1);
map.clear();
assert!(map.is_empty());
}
#[test]
fn test_values_and_to_vec() {
let map: HashMap<String, i32> = HashMap::new();
map.insert("a".to_string(), 1);
map.insert("b".to_string(), 2);
map.insert("c".to_string(), 3);
let values = map.values();
assert_eq!(values.len(), 3);
let vec = map.to_vec();
assert_eq!(vec.len(), 3);
}
#[test]
fn test_retain() {
let map: HashMap<String, i32> = HashMap::new();
map.insert("a".to_string(), 1);
map.insert("b".to_string(), 2);
map.insert("c".to_string(), 3);
map.insert("d".to_string(), 4);
map.retain(|_, v| *v % 2 == 0);
assert_eq!(map.len(), 2);
assert!(map.contains_key(&"b".to_string()));
assert!(map.contains_key(&"d".to_string()));
assert!(!map.contains_key(&"a".to_string()));
assert!(!map.contains_key(&"c".to_string()));
}
#[test]
fn test_clone() {
let map: HashMap<String, i32> = HashMap::new();
map.insert("key".to_string(), 42);
let cloned = map.clone();
assert_eq!(cloned.get(&"key".to_string()), Some(42));
cloned.insert("key".to_string(), 100);
assert_eq!(map.get(&"key".to_string()), Some(42));
assert_eq!(cloned.get(&"key".to_string()), Some(100));
}
}