hashvec/lib.rs
1//! A [`HashVec`] is a hash map / dictionary whose key-value pairs are stored (and can be iterated over) in a fixed order, by default the order in which they were inserted into the hashvec. It's essentially a vector whose values can be inserted/retrieved with keys.
2//! # Example
3//! ```
4//! use hashvec::*;
5//!
6//! // Create a new hashvec containing pairs of animal names and species
7//! // The hashvec! macro acts like vec!, but with key-value tuple pairs
8//! let mut hashvec: HashVec<&'static str, &'static str> = hashvec![
9//! ("Doug", "Kobold"),
10//! ("Skye", "Hyena"),
11//! ("Lee", "Shiba"),
12//! ("Sock", "Man"),
13//! ("Salad", "Wolf"),
14//! ("Finn", "Human")
15//! ];
16//!
17//! // Insert a value into the hashvec (HashMap-style)
18//! // Inserting overwrites existing keys' entries in-place
19//! hashvec.insert("Jake", "Dog");
20//!
21//! // Push a value onto the hashvec (Vector-style)
22//! // Pushing overwrites existing keys' entries and moves them to the end
23//! hashvec.push(("Susie", "Squid"));
24//!
25//! // Access a value by key
26//! match hashvec.get(&"Finn") {
27//! Some(value) => {
28//! assert_eq!(*value, "Human");
29//! },
30//! None => {}
31//! }
32//!
33//! // Access an entry by index
34//! let lee_value = hashvec[2];
35//! assert_eq!(lee_value, ("Lee", "Shiba"));
36//!
37//! // Get the index of a key
38//! let lee_index = hashvec.index(&"Lee").unwrap();
39//! assert_eq!(lee_index, 2);
40//!
41//! // Get the length of the hashvec
42//! let hashvec_length = hashvec.len();
43//! assert_eq!(hashvec_length, 8);
44//!
45//! // Change an entry's key in-place
46//! hashvec.rename(&"Salad", "Caesar");
47//! assert_eq!(hashvec[4], ("Caesar", "Dog"));
48//!
49//! // Mutate a value
50//! match hashvec.get_mut(&"Sock") {
51//! Some(value) => {
52//! *value = "Guinea Pig";
53//! },
54//! None => {}
55//! }
56//! assert_eq!(*hashvec.get(&"Sock").unwrap(), "Guinea Pig");
57//!
58//! // Remove an entry
59//! hashvec.remove_key(&"Doug");
60//! assert_eq!(hashvec.get(&"Doug"), None);
61//!
62//! // Swap the locations of two entries by their keys
63//! hashvec.swap_keys(&"Lee", &"Skye");
64//! assert_eq!(hashvec.index(&"Lee").unwrap(), 0);
65//! assert_eq!(hashvec.index(&"Skye").unwrap(), 1);
66//!
67//! // Now swap them again, by their indices
68//! hashvec.swap_indices(0, 1);
69//! assert_eq!(hashvec[0], ("Skye", "Hyena"));
70//! assert_eq!(hashvec[1], ("Lee", "Shiba"));
71//!
72//! // Iterate over each of the key-value pairs in the hashvec
73//! for (k, v) in hashvec.into_iter() {
74//! println!("{} is a {}!", k, v);
75//! }
76//!
77//! // Remove an entry from the end of the hashvec
78//! let last_entry = hashvec.pop();
79//! assert_eq!(last_entry.unwrap(), ("Susie", "Squid"));
80//!
81//! // Clear the hashvec
82//! hashvec.clear();
83//! ```
84
85use std::collections::HashMap;
86use std::collections::hash_map::DefaultHasher;
87use std::hash::{Hash, Hasher};
88use core::ops::Index;
89
90#[derive(Debug)]
91pub struct HashVec<K: Eq + Hash, V> {
92 entries: Vec<(K, V)>,
93 order: HashMap<u64, usize>
94}
95
96impl<K: Eq + Hash, V> HashVec<K, V> {
97 /// Creates a new, empty map.
98 pub fn new() -> HashVec<K, V> {
99 HashVec {
100 entries: Vec::new(),
101 order: HashMap::new()
102 }
103 }
104
105 /// Creates a new, empty hashvec with the specified capacity.
106 pub fn with_capacity(capacity: usize) -> HashVec<K, V> {
107 HashVec {
108 entries: Vec::with_capacity(capacity),
109 order: HashMap::with_capacity(capacity)
110 }
111 }
112
113 /// Creates a hashvec from a vector of key-value pairs.
114 ///
115 /// Internally, this uses [`HashVec::append_vec()`], which means that redundant keys' entries will be overwritten and moved to the end of the hashvec sequentially.
116 pub fn from_vec(v: Vec<(K, V)>) -> HashVec<K, V> {
117 let mut new_hashvec = HashVec::with_capacity(v.len());
118 new_hashvec.append_vec(v);
119 new_hashvec
120 }
121
122 /// Returns the number of elements the hashvec can hold without reallocating.
123 pub fn capacity(&self) -> usize {
124 self.entries.capacity().min(self.order.capacity())
125 }
126
127 /// Returns the number of elements in the hashvec.
128 pub fn len(&self) -> usize {
129 self.entries.len()
130 }
131
132 /// Returns `true` if the hashvec contains no elements.
133 pub fn is_empty(&self) -> bool {
134 self.entries.is_empty()
135 }
136
137 /// Clears the hashvec, removing all entries.
138 ///
139 /// Keep in mind this will not reallocate memory.
140 pub fn clear(&mut self) {
141 self.entries.clear();
142 self.order.clear();
143 }
144
145 /// Inserts an entry into the hashvec, or replaces an existing one.
146 pub fn insert(&mut self, k: K, v: V) {
147 match self.order.get(&calculate_hash(&k)) {
148 Some(index) => {
149 // If the key was already in the hashvec, update its entry in-place
150 self.entries[*index].1 = v;
151 },
152 None => {
153 // If the entry wasn't in the hashvec already, add it
154 self.order.insert(calculate_hash(&k), self.entries.len());
155 self.entries.push((k, v));
156 }
157 }
158 }
159
160 /// Appends an entry to the back of the hashvec.
161 ///
162 /// If an entry with an identical key was already in the hashvec, it is removed before the new entry is inserted.
163 ///
164 /// # Panics
165 /// Panics if the new capacity either overflows `usize` or exceeds `isize::MAX` bytes.
166 pub fn push(&mut self, entry: (K, V)) {
167 if self.contains_key(&entry.0) {
168 self.remove_key(&entry.0);
169 }
170
171 let key_hash = calculate_hash(&entry.0);
172 self.order.insert(key_hash, self.entries.len());
173 self.entries.push(entry);
174 }
175
176 /// Removes the last entry from the hashvec and returns it (or `None` if the hashvec is empty).
177 pub fn pop(&mut self) -> Option<(K, V)> {
178 let last_entry = self.entries.pop();
179
180 match last_entry {
181 Some(entry) => {
182 let key_hash = calculate_hash(&entry.0);
183
184 // Stop tracking the popped entry's key
185 self.order.remove(&key_hash);
186
187 Some(entry)
188 },
189 None => None
190 }
191 }
192
193 /// Appends all entries of `other` into `Self`, leaving `other` empty.
194 ///
195 /// # Panics
196 /// Panics if the number of elements in the hashvec either overflows `usize` or exceeds `isize::MAX` bytes
197 pub fn append(&mut self, other: &mut HashVec<K, V>) {
198 let mut other_entries: Vec<(K, V)> = Vec::new();
199 other_entries.append(&mut other.entries);
200 for (k, v) in other_entries {
201 self.push((k, v));
202 }
203 other.clear();
204 }
205
206 /// Appends a vector of key-value pairs onto the hashvec.
207 ///
208 /// Internally, this uses [`HashVec::push()`], which means that redundant keys' entries will be overwritten and moved to the end of the hashvec sequentially.
209 pub fn append_vec(&mut self, v: Vec<(K, V)>) {
210 for entry in v {
211 self.push(entry);
212 }
213 }
214
215 /// Swaps the location of the provided keys' entries
216 ///
217 /// If either one of the keys is not already in the hashvec, this is a no-op.
218 pub fn swap_keys(&mut self, key_a: &K, key_b: &K) {
219 let key_hash_a = calculate_hash(&key_a);
220 let key_hash_b = calculate_hash(&key_b);
221 let op_valid = self.order.contains_key(&key_hash_a) && self.order.contains_key(&key_hash_b);
222
223 if op_valid {
224 // Swap the tracked order
225 let old_index_a = *self.order.get(&key_hash_a).unwrap();
226 let old_index_b = *self.order.get(&key_hash_b).unwrap();
227 self.order.insert(key_hash_a, old_index_b);
228 self.order.insert(key_hash_b, old_index_a);
229
230 // Swap the actual entries
231 self.entries.swap(old_index_a, old_index_b);
232 }
233 }
234
235 /// Swaps the location of the entries at the provided indices
236 ///
237 /// If either one of the indices exceeds the current length of the hashvec, this is a no-op.
238 pub fn swap_indices(&mut self, index_a: usize, index_b: usize) {
239 if index_a.max(index_b) < self.len() {
240 let key_hash_a = calculate_hash(&self.entries[index_a].0);
241 let key_hash_b = calculate_hash(&self.entries[index_b].0);
242
243 // Swap the tracked order
244 let old_index_a = *self.order.get(&key_hash_a).unwrap();
245 let old_index_b = *self.order.get(&key_hash_b).unwrap();
246 self.order.insert(key_hash_a, old_index_b);
247 self.order.insert(key_hash_b, old_index_a);
248
249 // Swap the actual entries
250 self.entries.swap(old_index_a, old_index_b);
251 }
252 }
253
254 /// Returns `true` if the hashvec contains an entry corresponding to the provided key.
255 pub fn contains_key(&self, k: &K) -> bool {
256 self.order.contains_key(&calculate_hash(k))
257 }
258
259 /// Returns a reference to the value corresponding to the key, if it exists.
260 pub fn get(&self, k: &K) -> Option<&V> {
261 match self.order.get(&calculate_hash(&k)) {
262 Some(index) => Some(&self.entries[*index].1),
263 None => None
264 }
265 }
266
267 /// Returns a mutable reference to the value corresponding to the key, if it exists.
268 pub fn get_mut(&mut self, k: &K) -> Option<&mut V> {
269 match self.order.get(&calculate_hash(&k)) {
270 Some(index) => Some(&mut self.entries[*index].1),
271 None => None
272 }
273 }
274
275 /// Changes an entry's key, preserving and returning a reference to the associated value.
276 ///
277 /// If the hashvec did not have an entry corresponding to the old key, `None` is returned.
278 pub fn rename(&mut self, old_key: &K, new_key: K) -> Option<&V> {
279 let old_key_hash = calculate_hash(old_key);
280
281 let index_opt = match self.order.get(&old_key_hash) {
282 Some(index) => Some(*index),
283 None => None
284 };
285
286 match index_opt {
287 Some(index) => {
288 let new_key_hash = calculate_hash(&new_key);
289
290 // Change the entry's key
291 self.entries[index].0 = new_key;
292
293 // Stop tracking the old key hash
294 self.order.remove(&old_key_hash);
295
296 // Start tracking the new key hash
297 self.order.insert(new_key_hash, index);
298
299 // Return the corresponding value
300 Some(&self.entries[index].1)
301 },
302 None => None
303 }
304 }
305
306 /// Removes a key from the hashvec, returning the stored key and value if the key was previously in the hashvec.
307 pub fn remove_key_entry(&mut self, k: &K) -> Option<(K, V)> {
308 let key_hash = calculate_hash(k);
309
310 let index_opt = match self.order.get(&key_hash) {
311 Some(index) => Some(*index),
312 None => None
313 };
314
315 match index_opt {
316 Some(index) => {
317 // Get the entry and then remove it from the hashvec entirely before returning the value
318 let value = self.entries.remove(index);
319
320 // Remove the corresponding entry from the order hashmap
321 self.order.remove(&key_hash);
322
323 // Update the index on all the remaining entries which followed the one we just removed
324 for (i, (k, v)) in self.entries.iter().enumerate() {
325 if i >= index {
326 self.order.insert(calculate_hash(&self.entries[i].0), i);
327 }
328 }
329
330 // Now return the value we retained earlier
331 Some(value)
332 },
333 None => None
334 }
335 }
336
337 // Swaps the positions of entries `a` and `b` within the hashvec.
338 //pub fn swap(&mut self, a: K, b: K) {
339 //
340 //}
341
342 /// Returns the index of the provided key, if the key exists.
343 pub fn index(&self, k: &K) -> Option<usize> {
344 match self.order.get(&calculate_hash(k)) {
345 Some(index) => Some(*index),
346 None => None
347 }
348 }
349
350 /// Removes a key from the hashvec, returning the stored value if the key was previously in the hashvec.
351 pub fn remove_key(&mut self, k: &K) -> Option<V> {
352 match self.remove_key_entry(k) {
353 Some((_, v)) => Some(v),
354 None => None
355 }
356 }
357
358 /// Reserves capacity for at least `additional` more elements to be inserted in the `HashVec`. The collection may reserve more space to avoid frequent reallocations.
359 ///
360 /// # Panics
361 /// Panics if the new capacity either overflows `usize` or exceeds `isize::MAX` bytes.
362 pub fn reserve(&mut self, additional: usize) {
363 self.entries.reserve(additional);
364 self.order.reserve(additional);
365 }
366
367 /// Shrinks the capacity of the hashvec with a lower limit.
368 ///
369 /// The capacity will remain at least as large as both the length and the supplied value.
370 ///
371 /// If the current capacity is less than the lower limit, this is a no-op.
372 pub fn shrink_to(&mut self, min_capacity: usize) {
373 self.entries.shrink_to(min_capacity);
374 self.order.shrink_to(min_capacity);
375 }
376
377 /// Shrinks the capacity of the hashvec as much as possible, according to internal rules.
378 pub fn shrink_to_fit(&mut self) {
379 self.entries.shrink_to_fit();
380 self.order.shrink_to_fit();
381 }
382}
383
384impl<K: Eq + Hash, V> Index<usize> for HashVec<K, V> {
385 type Output = (K, V);
386 fn index(&self, i: usize) -> &(K, V) {
387 &self.entries[i]
388 }
389}
390
391impl<'a, K: Eq + Hash, V> IntoIterator for &'a HashVec<K, V> {
392 type Item = (&'a K, &'a V);
393 type IntoIter = HashVecIter<'a, K, V>;
394 fn into_iter(self) -> Self::IntoIter {
395 HashVecIter {
396 ordered_map: self,
397 index: 0
398 }
399 }
400}
401
402// Wrapping iterator struct
403pub struct HashVecIter<'a, K: Eq + Hash, V> {
404 ordered_map: &'a HashVec<K, V>,
405 index: usize
406}
407
408impl<'a, K: Eq + Hash, V> Iterator for HashVecIter<'a, K, V> {
409 type Item = (&'a K, &'a V);
410 fn next(&mut self) -> Option<Self::Item> {
411 let result = match self.ordered_map.entries.get(self.index) {
412 Some((k, v)) => Some((k, v)),
413 None => None
414 };
415 self.index += 1;
416 result
417 }
418}
419
420fn calculate_hash<K: Hash>(k: &K)-> u64 {
421 let mut hasher = DefaultHasher::new();
422 k.hash(&mut hasher);
423 hasher.finish()
424}
425
426#[macro_export]
427macro_rules! hashvec {
428 ($($x:expr),+ $(,)?) => (
429 HashVec::from_vec(vec![$($x),+])
430 );
431}