grafeo_core/index/
hash.rs1use dashmap::DashMap;
10use grafeo_common::types::NodeId;
11use std::hash::Hash;
12
13pub struct HashIndex<K: Hash + Eq, V: Copy> {
40 map: DashMap<K, V>,
42}
43
44impl<K: Hash + Eq, V: Copy> HashIndex<K, V> {
45 #[must_use]
47 pub fn new() -> Self {
48 Self {
49 map: DashMap::new(),
50 }
51 }
52
53 #[must_use]
55 pub fn with_capacity(capacity: usize) -> Self {
56 Self {
57 map: DashMap::with_capacity(capacity),
58 }
59 }
60
61 pub fn insert(&self, key: K, value: V) -> Option<V> {
65 self.map.insert(key, value)
66 }
67
68 pub fn get(&self, key: &K) -> Option<V> {
73 self.map.get(key).map(|v| *v)
74 }
75
76 pub fn remove(&self, key: &K) -> Option<V> {
80 self.map.remove(key).map(|(_, v)| v)
81 }
82
83 pub fn contains(&self, key: &K) -> bool {
85 self.map.contains_key(key)
86 }
87
88 pub fn len(&self) -> usize {
90 self.map.len()
91 }
92
93 pub fn is_empty(&self) -> bool {
95 self.map.is_empty()
96 }
97
98 pub fn clear(&self) {
100 self.map.clear();
101 }
102}
103
104impl<K: Hash + Eq, V: Copy> Default for HashIndex<K, V> {
105 fn default() -> Self {
106 Self::new()
107 }
108}
109
110pub type StringKeyIndex = HashIndex<String, NodeId>;
112
113pub type NodeIdIndex = HashIndex<NodeId, NodeId>;
115
116#[cfg(test)]
117mod tests {
118 use super::*;
119
120 #[test]
121 fn test_hash_index_basic() {
122 let index: HashIndex<u64, NodeId> = HashIndex::new();
123
124 index.insert(1, NodeId::new(100));
125 index.insert(2, NodeId::new(200));
126
127 assert_eq!(index.get(&1), Some(NodeId::new(100)));
128 assert_eq!(index.get(&2), Some(NodeId::new(200)));
129 assert_eq!(index.get(&3), None);
130 }
131
132 #[test]
133 fn test_hash_index_update() {
134 let index: HashIndex<u64, NodeId> = HashIndex::new();
135
136 index.insert(1, NodeId::new(100));
137 let old = index.insert(1, NodeId::new(200));
138
139 assert_eq!(old, Some(NodeId::new(100)));
140 assert_eq!(index.get(&1), Some(NodeId::new(200)));
141 }
142
143 #[test]
144 fn test_hash_index_remove() {
145 let index: HashIndex<u64, NodeId> = HashIndex::new();
146
147 index.insert(1, NodeId::new(100));
148 assert!(index.contains(&1));
149
150 let removed = index.remove(&1);
151 assert_eq!(removed, Some(NodeId::new(100)));
152 assert!(!index.contains(&1));
153 }
154
155 #[test]
156 fn test_hash_index_len() {
157 let index: HashIndex<u64, NodeId> = HashIndex::new();
158
159 assert!(index.is_empty());
160 assert_eq!(index.len(), 0);
161
162 index.insert(1, NodeId::new(100));
163 index.insert(2, NodeId::new(200));
164
165 assert!(!index.is_empty());
166 assert_eq!(index.len(), 2);
167 }
168
169 #[test]
170 fn test_hash_index_clear() {
171 let index: HashIndex<u64, NodeId> = HashIndex::new();
172
173 index.insert(1, NodeId::new(100));
174 index.insert(2, NodeId::new(200));
175
176 index.clear();
177
178 assert!(index.is_empty());
179 assert_eq!(index.get(&1), None);
180 }
181
182 #[test]
183 fn test_string_key_index() {
184 let index: StringKeyIndex = HashIndex::new();
185
186 index.insert("alice".to_string(), NodeId::new(1));
187 index.insert("bob".to_string(), NodeId::new(2));
188
189 assert_eq!(index.get(&"alice".to_string()), Some(NodeId::new(1)));
190 assert_eq!(index.get(&"bob".to_string()), Some(NodeId::new(2)));
191 }
192}