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}