use dashmap::DashMap;
use grafeo_common::types::NodeId;
use std::hash::Hash;
pub struct HashIndex<K: Hash + Eq, V: Copy> {
map: DashMap<K, V>,
}
impl<K: Hash + Eq, V: Copy> HashIndex<K, V> {
#[must_use]
pub fn new() -> Self {
Self {
map: DashMap::new(),
}
}
#[must_use]
pub fn with_capacity(capacity: usize) -> Self {
Self {
map: DashMap::with_capacity(capacity),
}
}
pub fn insert(&self, key: K, value: V) -> Option<V> {
self.map.insert(key, value)
}
pub fn get(&self, key: &K) -> Option<V> {
self.map.get(key).map(|v| *v)
}
pub fn remove(&self, key: &K) -> Option<V> {
self.map.remove(key).map(|(_, v)| v)
}
pub fn contains(&self, key: &K) -> bool {
self.map.contains_key(key)
}
pub fn len(&self) -> usize {
self.map.len()
}
pub fn is_empty(&self) -> bool {
self.map.is_empty()
}
pub fn clear(&self) {
self.map.clear();
}
}
impl<K: Hash + Eq, V: Copy> Default for HashIndex<K, V> {
fn default() -> Self {
Self::new()
}
}
pub type StringKeyIndex = HashIndex<String, NodeId>;
pub type NodeIdIndex = HashIndex<NodeId, NodeId>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_hash_index_basic() {
let index: HashIndex<u64, NodeId> = HashIndex::new();
index.insert(1, NodeId::new(100));
index.insert(2, NodeId::new(200));
assert_eq!(index.get(&1), Some(NodeId::new(100)));
assert_eq!(index.get(&2), Some(NodeId::new(200)));
assert_eq!(index.get(&3), None);
}
#[test]
fn test_hash_index_update() {
let index: HashIndex<u64, NodeId> = HashIndex::new();
index.insert(1, NodeId::new(100));
let old = index.insert(1, NodeId::new(200));
assert_eq!(old, Some(NodeId::new(100)));
assert_eq!(index.get(&1), Some(NodeId::new(200)));
}
#[test]
fn test_hash_index_remove() {
let index: HashIndex<u64, NodeId> = HashIndex::new();
index.insert(1, NodeId::new(100));
assert!(index.contains(&1));
let removed = index.remove(&1);
assert_eq!(removed, Some(NodeId::new(100)));
assert!(!index.contains(&1));
}
#[test]
fn test_hash_index_len() {
let index: HashIndex<u64, NodeId> = HashIndex::new();
assert!(index.is_empty());
assert_eq!(index.len(), 0);
index.insert(1, NodeId::new(100));
index.insert(2, NodeId::new(200));
assert!(!index.is_empty());
assert_eq!(index.len(), 2);
}
#[test]
fn test_hash_index_clear() {
let index: HashIndex<u64, NodeId> = HashIndex::new();
index.insert(1, NodeId::new(100));
index.insert(2, NodeId::new(200));
index.clear();
assert!(index.is_empty());
assert_eq!(index.get(&1), None);
}
#[test]
fn test_string_key_index() {
let index: StringKeyIndex = HashIndex::new();
index.insert("alix".to_string(), NodeId::new(1));
index.insert("gus".to_string(), NodeId::new(2));
assert_eq!(index.get(&"alix".to_string()), Some(NodeId::new(1)));
assert_eq!(index.get(&"gus".to_string()), Some(NodeId::new(2)));
}
}