indexedlinkedhashmap/
lib.rs

1#![crate_name = "indexedlinkedhashmap"]
2
3//! Provides an easy interface to preserve the insertion order of your `HashMap`.
4
5use std::collections::HashMap;
6use std::fmt::{Debug, Formatter, Result};
7use std::hash::Hash;
8use traits::Ordered;
9
10/// Stores an index for quick key lookup and the value.
11#[derive(PartialEq, Clone, Copy)]
12pub struct IndexedLinkedHashMapValue<V> {
13    pub index: Option<usize>,
14    pub value: V,
15}
16
17/// Stores number of keys, keys in order, and values.
18pub struct IndexedLinkedHashMap<I, K, V> {
19    _keys: I,
20    _values: HashMap<K, IndexedLinkedHashMapValue<V>>,
21}
22
23impl<I, K, V> IndexedLinkedHashMap<I, K, V>
24where
25    I: Ordered<K> + Default,
26    K: Eq + Hash + Clone,
27    V: Clone,
28{
29    /// Creates new `IndexedLinkedHashMap`.
30    pub fn new() -> Self {
31        return IndexedLinkedHashMap {
32            _keys: I::default(),
33            _values: HashMap::new(),
34        };
35    }
36
37    /// Gets value using key; returns `Some(v)` if exists or `None`.
38    pub fn get(&self, k: K) -> Option<&V> {
39        return match self._values.get(&k) {
40            Some(v) => Some(&v.value),
41            None => None,
42        };
43    }
44
45    /// Sets value; upserts if exists already or adds new entry.
46    pub fn set(&mut self, k: K, v: V) {
47        if self._values.contains_key(&k) {
48            let value: &IndexedLinkedHashMapValue<V> = self._values.get(&k).unwrap();
49            self._values.insert(
50                k,
51                IndexedLinkedHashMapValue {
52                    index: value.index,
53                    value: v,
54                },
55            );
56        } else {
57            self._keys.push(k.to_owned());
58            self._values.insert(
59                k,
60                IndexedLinkedHashMapValue {
61                    index: Some(self._keys.len() - 1),
62                    value: v,
63                },
64            );
65        }
66    }
67
68    /// Gets value using index; returns `Some(v)` if exists or `None`.
69    pub fn at(&self, i: Option<usize>) -> Option<&V> {
70        return match i {
71            Some(i) => match i >= self._keys.len() {
72                true => None,
73                false => match self._keys.get(Some(i)) {
74                    Some(k) => match self._values.get(k) {
75                        Some(v) => Some(&v.value),
76                        None => None,
77                    },
78                    None => None,
79                },
80            },
81            None => match self._keys.get(i) {
82                Some(k) => match self._values.get(k) {
83                    Some(v) => Some(&v.value),
84                    None => None,
85                },
86                None => None,
87            },
88        };
89    }
90
91    /// Gets key using index; returns `Some(k)` if exists or `None`.
92    pub fn key_at(&self, i: Option<usize>) -> Option<&K> {
93        return match i {
94            Some(i) => match i >= self._keys.len() {
95                true => None,
96                false => self._keys.get(Some(i)),
97            },
98            None => self._keys.get(i),
99        };
100    }
101
102    // Sets value at index.
103    pub fn set_at(&mut self, i: Option<usize>, k: K, v: V) {
104        return match i {
105            Some(i) => match i >= self._keys.len() {
106                true => (),
107                false => {
108                    self._keys.set(Some(i), k.to_owned());
109                    self._values.insert(
110                        k,
111                        IndexedLinkedHashMapValue {
112                            index: Some(i),
113                            value: v,
114                        },
115                    );
116                }
117            },
118            None => {
119                self._keys.set(i, k.to_owned());
120                self._values
121                    .insert(k, IndexedLinkedHashMapValue { index: i, value: v });
122            }
123        };
124    }
125
126    /// Removes value; returns `Some(v)` if exists or `None`.
127    pub fn remove(&mut self, k: K) -> Option<IndexedLinkedHashMapValue<V>> {
128        if self._values.contains_key(&k) {
129            let removed = self._values.remove(&k).unwrap();
130            self._keys.remove(removed.index);
131
132            return Some(removed);
133        }
134
135        return None;
136    }
137
138    /// Clears all values.
139    pub fn clear(&mut self) {
140        self._keys.clear();
141        self._values.clear();
142    }
143
144    /// Gets length.
145    pub fn len(&self) -> usize {
146        return self._keys.len();
147    }
148
149    /// Check if contains a key.
150    pub fn contains_key(&self, k: K) -> bool {
151        return self._values.contains_key(&k);
152    }
153
154    /// Gets all keys.
155    pub fn keys(&self) -> &I {
156        return &self._keys;
157    }
158
159    /// Gets all values.
160    pub fn values(&self) -> Vec<&IndexedLinkedHashMapValue<V>> {
161        return self
162            ._values
163            .values()
164            .collect::<Vec<&IndexedLinkedHashMapValue<V>>>();
165    }
166}
167
168impl<I, K, V> Debug for IndexedLinkedHashMap<I, K, V>
169where
170    I: Ordered<K> + Default,
171    K: Eq + Hash + Clone + Debug,
172    V: Clone + Debug,
173{
174    fn fmt(&self, f: &mut Formatter) -> Result {
175        let mut out: String = String::new();
176        for i in 0..self._keys.len() {
177            match self._keys.get(Some(i)) {
178                Some(k) => match self._values.get(k) {
179                    Some(v) => out += format!("{:?}: {:?}", k, v.value).as_str(),
180                    None => (),
181                },
182                None => (),
183            };
184        }
185
186        return write!(f, "{}", out);
187    }
188}
189
190pub mod traits {
191    pub trait Ordered<K> {
192        fn get(&self, i: Option<usize>) -> Option<&K>;
193        fn set(&mut self, i: Option<usize>, k: K);
194        fn push(&mut self, k: K);
195        fn remove(&mut self, i: Option<usize>);
196        fn clear(&mut self);
197        fn len(&self) -> usize;
198    }
199}
200
201#[cfg(any(
202    feature = "collections_ordering_vec",
203    feature = "collections_ordering_binary_heap"
204))]
205pub mod collections {
206    pub mod ordering {
207        use super::super::traits::Ordered;
208        use std::collections::BinaryHeap;
209
210        #[cfg(feature = "collections_ordering_vec")]
211        impl<K> Ordered<K> for Vec<K> {
212            fn get(&self, i: Option<usize>) -> Option<&K> {
213                return match i {
214                    Some(i) => match i >= self.len() {
215                        true => None,
216                        false => Some(&self[i]),
217                    },
218                    None => None,
219                };
220            }
221
222            fn set(&mut self, i: Option<usize>, k: K) {
223                match i {
224                    Some(i) => match i >= self.len() {
225                        true => (),
226                        false => {
227                            self[i] = k;
228                        }
229                    },
230                    None => (),
231                };
232            }
233
234            fn push(&mut self, k: K) {
235                self.push(k);
236            }
237
238            fn remove(&mut self, i: Option<usize>) {
239                match i {
240                    Some(i) => match i >= self.len() {
241                        true => (),
242                        false => {
243                            self.remove(i);
244                        }
245                    },
246                    None => (),
247                };
248            }
249
250            fn clear(&mut self) {
251                self.clear();
252            }
253
254            fn len(&self) -> usize {
255                return self.len();
256            }
257        }
258
259        #[cfg(feature = "collections_ordering_binary_heap")]
260        impl<K> Ordered<K> for BinaryHeap<K>
261        where
262            K: Ord + Eq,
263            BinaryHeap<K>: From<Vec<K>> + Clone,
264        {
265            fn get(&self, i: Option<usize>) -> Option<&K> {
266                return match i {
267                    Some(i) => match i >= self.len() {
268                        true => None,
269                        false => {
270                            for (idx, k) in self.iter().enumerate() {
271                                if i == idx {
272                                    return Some(k);
273                                }
274                            }
275
276                            return None;
277                        }
278                    },
279                    None => None,
280                };
281            }
282
283            fn set(&mut self, _i: Option<usize>, k: K) {
284                let mut p = Vec::from(self.clone());
285                p.push(k);
286
287                self.append(&mut BinaryHeap::<K>::from(p));
288            }
289
290            fn push(&mut self, k: K) {
291                self.push(k);
292            }
293
294            fn remove(&mut self, i: Option<usize>) {
295                return match i {
296                    Some(i) => match i >= self.len() {
297                        true => (),
298                        false => {
299                            let p: Vec<K> = Vec::from(self.clone());
300                            let mut n: Vec<&K> = Vec::new();
301                            for (idx, k) in p.iter().enumerate() {
302                                if idx != i {
303                                    n.push(k);
304                                }
305                            }
306
307                            self.append(&mut BinaryHeap::<K>::from(p));
308                        }
309                    },
310                    None => (),
311                };
312            }
313
314            fn clear(&mut self) {
315                self.clear();
316            }
317
318            fn len(&self) -> usize {
319                return self.len();
320            }
321        }
322    }
323}
324
325#[cfg(test)]
326mod tests {
327    mod indexedlinkedhashmap {
328        use crate::*;
329
330        #[test]
331        fn new() {
332            let ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
333            assert!(ins.len() == 0);
334            assert!(ins.keys().len() == 0);
335            assert!(ins.values().len() == 0);
336        }
337
338        #[test]
339        fn get() {
340            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
341            assert!(ins.get(&"k") == None);
342            ins.set("k", 1);
343            assert!(ins.get(&"k") == Some(&1));
344        }
345
346        #[test]
347        fn set() {
348            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
349            ins.set("k", 1);
350            assert!(ins.len() == 1);
351            assert!(ins.keys().len() == 1);
352            assert!(ins.values().len() == 1);
353            assert!(ins.get("k") == Some(&1));
354        }
355
356        #[test]
357        fn at() {
358            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
359            assert!(ins.at(Some(0)) == None);
360            ins.set("k", 1);
361            assert!(ins.at(Some(0)) == Some(&1));
362            assert!(ins.at(Some(1)) == None);
363        }
364
365        #[test]
366        fn key_at() {
367            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
368            assert!(ins.at(Some(0)) == None);
369            ins.set("k", 1);
370            assert!(ins.key_at(Some(0)) == Some(&"k"));
371            assert!(ins.key_at(Some(1)) == None);
372        }
373
374        #[test]
375        fn set_at() {
376            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
377            ins.set_at(Some(1), "a", 2);
378            assert!(ins.get(&"a") == None);
379            ins.set("k", 1);
380            ins.set_at(Some(0), "b", 3);
381            assert!(ins.at(Some(0)) == Some(&3));
382            assert!(ins.get(&"b") == Some(&3));
383        }
384
385        #[test]
386        fn remove() {
387            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
388            assert!(ins.remove("k") == None);
389            assert!(ins.len() == 0);
390            assert!(ins.keys().len() == 0);
391            assert!(ins.values().len() == 0);
392            ins.set("k", 1);
393            assert!(
394                ins.remove("k")
395                    == Some(IndexedLinkedHashMapValue {
396                        index: Some(0),
397                        value: 1
398                    })
399            );
400            assert!(ins.len() == 0);
401            assert!(ins.keys().len() == 0);
402            assert!(ins.values().len() == 0);
403        }
404
405        #[test]
406        fn clear() {
407            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
408            ins.clear();
409            assert!(ins.len() == 0);
410            assert!(ins.keys().len() == 0);
411            assert!(ins.values().len() == 0);
412            ins.set("k", 1);
413            ins.clear();
414            assert!(ins.len() == 0);
415            assert!(ins.keys().len() == 0);
416            assert!(ins.values().len() == 0);
417        }
418
419        #[test]
420        fn len() {
421            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
422            assert!(ins.len() == 0);
423            ins.clear();
424            assert!(ins.len() == 0);
425            ins.set("k", 1);
426            assert!(ins.len() == 1);
427            ins.clear();
428            assert!(ins.len() == 0);
429        }
430
431        #[test]
432        fn contains_key() {
433            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
434            assert!(ins.contains_key(&"k") == false);
435            ins.set("k", 1);
436            assert!(ins.contains_key(&"k") == true);
437        }
438
439        #[test]
440        fn keys() {
441            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
442            let mut keys: Vec<&str> = Vec::new();
443            assert!(ins.keys().eq(&keys));
444            ins.set("k", 1);
445            keys.push("k");
446            assert!(ins.keys().eq(&keys));
447        }
448
449        #[test]
450        fn values() {
451            let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
452            let mut values: Vec<&IndexedLinkedHashMapValue<usize>> = Vec::new();
453            assert!(ins.values().eq(&values));
454            ins.set("k", 1);
455            values.push(&IndexedLinkedHashMapValue {
456                index: Some(0),
457                value: 1,
458            });
459            assert!(ins.values().eq(&values));
460        }
461
462        mod debug {
463            use crate::*;
464
465            #[test]
466            fn fmt() {
467                let mut ins = IndexedLinkedHashMap::<Vec<&str>, &str, usize>::new();
468                assert!("" == format!("{:?}", ins));
469                ins.set("k", 1);
470                println!("{:?}", ins);
471                assert!("\"k\": 1" == format!("{:?}", ins));
472            }
473        }
474    }
475}