index_map/
lib.rs

1#![no_std]
2#![warn(missing_docs)]
3#![warn(rust_2018_idioms)]
4//! A map with automatically generated `usize`s as keys.
5//!
6//! # Usage
7//!
8//! ```
9//! use index_map::IndexMap;
10//!
11//! let mut process_table = IndexMap::new();
12//!
13//! // Create some processes
14//! // Unlike HashMap, insert only takes a value, and returns the key.
15//! let vim = process_table.insert("vim".to_string());
16//! //  ^^^----------------------------------------------------------.
17//! let cargo = process_table.insert("cargo".to_string()); //        |
18//! //  ^^^^^--------------------------------------------------------|
19//! let rls = process_table.insert("rust-analyser".to_string()); //  |
20//! //  ^^^----------------------------------------------------------|
21//! //                                                               |
22//! //  Unique numbers representing each process  <------------------'
23//!
24//! // Check for a specific one.
25//! if !process_table.contains_key(6) {
26//!     println!("Invalid PID 6");
27//! }
28//!
29//! // cargo finished running, remove it
30//! process_table.remove(cargo);
31//!
32//! // Look up the values associated with some keys.
33//! let to_find = [2, 4];
34//! for &pid in &to_find {
35//!     match process_table.get(pid) {
36//!         Some(process) => println!("{}: {}", pid, process),
37//!         None => println!("{} not found", pid)
38//!     }
39//! }
40//!
41//! // Look up the value for a key (will panic if the key is not found).
42//! println!("PID 0 process name: {}", process_table[0]);
43//!
44//! // Iterate over everything.
45//! for (pid, process) in &process_table {
46//!     println!("{}: \"{}\"", pid, process);
47//! }
48//! ```
49//!
50//! # How it works
51//! It internally is based on a [`Vec`], where each element either stores a value, or stores the index
52//! of the next free element. Since it accommodates for empty elements in between, it can perform
53//! O(1)* inserts and O(1) removals from any index. The "free" indices essentially make a singly
54//! linked list.
55//!
56//! \* amortized similar to [`Vec::push()`] (triggers a resize when [`len()`](IndexMap::len) ==
57//! [`capacity()`](IndexMap::capacity))
58//!
59//! Take the following example:
60//! > `*` represents an element \
61//! >`-` represents no index (end of the linked list) \
62//! >`<int>` represents the index of the next free element
63//!
64//! Assuming there are already 3 elements,
65//!
66//! ```text
67//! Initial State:
68//! .---.---.---.
69//! | * | * | * | head - None
70//! '---'---'---'
71//!   0   1   2
72//!
73//! Op - remove(1)
74//! State:
75//! .---.---.---.
76//! | * | - | * |
77//! '---'---'---'
78//!       ^-- head [ 1 ]
79//!
80//! Op - remove(2)
81//! State:
82//! ```text
83//! .---.---.---.
84//! | * | - | 1 |
85//! '---'---'---'
86//!           ^-- head [ 2 ]
87//!
88//! Op - insert
89//! State:
90//! .---.---.---.
91//! | * | - | * |
92//! '---'---'---'
93//!       ^-- head [ 1 ]
94//! ```
95
96extern crate alloc;
97
98use alloc::vec::Vec;
99
100mod iter;
101mod option_index;
102pub use iter::{Drain, IntoIter, Iter, IterMut, Keys, Values, ValuesMut};
103use option_index::OptionIndex;
104
105/// A map of `usize` to value, which allows efficient O(1) inserts, O(1) indexing and O(1) removal.
106///
107/// See [crate level documentation](crate) for more information.
108#[derive(PartialEq, PartialOrd, Eq, Ord)]
109pub struct IndexMap<T> {
110    data: Vec<OptionIndex<T>>,
111    head: Option<usize>,
112    len: usize,
113}
114
115impl<T> IndexMap<T> {
116    /// Creates a new `IndexMap`.
117    ///
118    /// It initially has a capacity of 0, and won't allocate until first inserted into.
119    ///
120    /// # Examples
121    /// ```
122    /// use index_map::IndexMap;
123    /// let mut map: IndexMap<&str> = IndexMap::new();
124    /// ```
125    pub fn new() -> Self {
126        Self {
127            data: Vec::new(),
128            head: None,
129            len: 0,
130        }
131    }
132
133    /// Creates an empty `IndexMap` with the specified capacity.
134    ///
135    /// The map will be able to hold at least capacity elements without reallocating. If capacity
136    /// is 0, the map will not allocate.
137    ///
138    /// # Examples
139    /// ```
140    /// use index_map::IndexMap;
141    /// let mut map: IndexMap<&str> = IndexMap::with_capacity(10);
142    /// ```
143    pub fn with_capacity(capacity: usize) -> Self {
144        Self {
145            data: Vec::with_capacity(capacity),
146            head: None,
147            len: 0,
148        }
149    }
150
151    /// Returns the number of elements map can hold without reallocating.
152    ///
153    /// # Examples
154    /// ```
155    /// use index_map::IndexMap;
156    /// let mut map: IndexMap<&str> = IndexMap::with_capacity(10);
157    /// assert!(map.capacity() >= 10);
158    /// ```
159    pub fn capacity(&self) -> usize {
160        self.data.capacity()
161    }
162
163    /// Returns the number of elements present in the map.
164    ///
165    /// # Examples
166    /// ```
167    /// use index_map::IndexMap;
168    /// let mut map = IndexMap::new();
169    /// assert_eq!(map.len(), 0);
170    /// map.insert("a");
171    /// assert_eq!(map.len(), 1);
172    /// ```
173    pub fn len(&self) -> usize {
174        self.len
175    }
176
177    /// Returns `true` if the map is empty.
178    ///
179    /// # Examples
180    /// ```
181    /// use index_map::IndexMap;
182    /// let mut map = IndexMap::new();
183    /// assert!(map.is_empty());
184    /// map.insert("a");
185    /// assert!(!map.is_empty());
186    /// ```
187    pub fn is_empty(&self) -> bool {
188        self.len() == 0
189    }
190
191    /// Clears the map, dropping all key-value pairs. Keeps the allocated memory for reuse.
192    ///
193    /// # Examples
194    /// ```
195    /// use index_map::IndexMap;
196    /// let mut map = IndexMap::new();
197    ///
198    /// map.insert("a");
199    /// map.clear();
200    ///
201    /// assert!(map.is_empty());
202    /// ```
203    pub fn clear(&mut self) {
204        self.len = 0;
205        self.data.clear()
206    }
207
208    /// Reserves capacity for at least additional more elements to be inserted in the `IndexMap`
209    /// The collection may reserve more space to avoid frequent reallocations.
210    ///
211    /// # Panics
212    /// Panics if the new capacity exceeds [`isize::MAX`] bytes.
213    ///
214    /// # Examples
215    /// ```
216    /// use index_map::IndexMap;
217    /// let mut map: IndexMap<&str> = IndexMap::new();
218    /// map.reserve(10);
219    /// assert!(map.capacity() >= 10);
220    /// ```
221    pub fn reserve(&mut self, additional: usize) {
222        self.data.reserve(additional)
223    }
224
225    /// Shrinks the capacity of the map as much as possible. It will drop down as much as possible
226    /// while maintaining the internal rules and possibly leaving some space to keep keys valid.
227    ///
228    /// # Examples
229    /// ```
230    /// use index_map::IndexMap;
231    /// let mut map = IndexMap::with_capacity(100);
232    /// map.insert("a");
233    /// map.insert("b");
234    /// assert!(map.capacity() >= 100);
235    /// map.shrink_to_fit();
236    /// assert!(map.capacity() >= 2);
237    /// ```
238    pub fn shrink_to_fit(&mut self) {
239        // This relies on the fact that `||` short-circuits. If `data` is empty, `head` *has* to be
240        // None, and so `data.last()` *cannot* be None.
241        if self.head.is_none() || self.data.last().unwrap().is_inner() {
242            self.data.shrink_to_fit();
243            return;
244        }
245
246        if self.is_empty() {
247            self.head = None;
248            self.data.clear();
249            self.data.shrink_to_fit();
250            return;
251        }
252
253        // random default value, the previous check makes sure there are elements, so the if
254        // condition has to be triggered.
255        let mut last = usize::MAX;
256
257        for (i, v) in self.data.iter().enumerate().rev() {
258            if v.is_inner() {
259                last = i;
260                break;
261            }
262        }
263
264        assert_ne!(last, usize::MAX);
265
266        let mut head = self.head.unwrap();
267        // If head is more than last, it needs to be set in such a way that head points to an
268        // index which is not truncated
269        //                   ,-- head [ 4 ]   |   Key:
270        // .---.---.---.---.---.              |   *     = element
271        // | * | - | * | * | 1 |              |   -     = No Index
272        // '---'---'---'---'---'              |   <int> = Index
273        //               ^-- last [ 3 ]       |
274        // Take the above data. After shrinking, it would be erroneous for head to still point
275        // to 4, since it will be deleted.
276        let mut should_set_head = head > last;
277
278        while let OptionIndex::Index(next) = self.data[head] {
279            if next > last {
280                // We can't use clone because `T` is not required to be clone, so no bound is
281                // added. We can't use `OptionIndex::take`, since we need the index intact for
282                // the next loop.
283                self.data[head] = match self.data[next] {
284                    OptionIndex::Index(i) => OptionIndex::Index(i),
285                    OptionIndex::NoIndex => OptionIndex::NoIndex,
286                    OptionIndex::Some(_) => {
287                        unreachable!("encountered value while walking index list")
288                    }
289                };
290            }
291
292            if should_set_head && head < last {
293                self.head = Some(head);
294                should_set_head = false;
295            }
296            head = next;
297        }
298
299        // The only index not checked is `head`, replace `self.head` based on it.
300        if should_set_head {
301            self.head = if head < last { Some(head) } else { None };
302        }
303
304        self.data[head] = OptionIndex::NoIndex;
305
306        // Truncate expects length, not the index of last element
307        self.data.truncate(last + 1);
308
309        self.data.shrink_to_fit()
310    }
311
312    /// Returns `true` if the map contains a value for the specified key.
313    ///
314    /// # Examples
315    ///
316    /// ```
317    /// use index_map::IndexMap;
318    ///
319    /// let mut map = IndexMap::new();
320    /// map.insert("a");
321    /// assert_eq!(map.contains_key(0), true);
322    /// assert_eq!(map.contains_key(1), false);
323    /// ```
324    pub fn contains_key(&self, index: usize) -> bool {
325        if index >= self.data.len() {
326            return false;
327        }
328
329        self.data[index].is_inner()
330    }
331
332    /// Inserts a value into the map, returning the generated key, for it.
333    ///
334    /// # Examples
335    /// ```
336    /// use index_map::IndexMap;
337    ///
338    /// let mut map = IndexMap::new();
339    /// assert_eq!(map.insert("a"), 0);
340    /// assert_eq!(map.is_empty(), false);
341    ///
342    /// let b = map.insert("b");
343    /// assert_eq!(map[b], "b");
344    /// ```
345    pub fn insert(&mut self, value: T) -> usize {
346        // The operation can't fail (unless Vec panics internally) since the key is generated by us.
347        self.len += 1;
348
349        if let Some(head) = self.head {
350            self.head = self.data[head].take().into_index();
351            self.data[head] = OptionIndex::Some(value);
352            head
353        } else {
354            self.data.push(OptionIndex::Some(value));
355            self.data.len() - 1
356        }
357    }
358
359    /// Removes a key from the map, returning the value at the key if the key was previously in
360    /// the map.
361    ///
362    /// # Examples
363    /// ```
364    /// use index_map::IndexMap;
365    ///
366    /// let mut map = IndexMap::new();
367    /// let a = map.insert("a");
368    /// assert_eq!(map.remove(a), Some("a"));
369    /// assert_eq!(map.remove(a), None);
370    /// ```
371    pub fn remove(&mut self, index: usize) -> Option<T> {
372        if !self.data.get(index)?.is_inner() {
373            return None;
374        }
375
376        let val = self.data.get_mut(index)?.take().into_inner()?;
377
378        if let Some(head) = self.head {
379            self.data[index] = OptionIndex::Index(head);
380        } else {
381            self.data[index] = OptionIndex::NoIndex;
382        }
383
384        self.head = Some(index);
385        self.len -= 1;
386
387        Some(val)
388    }
389
390    /// Removes a key from the map, returning the key and value if the key was previously in the map.
391    ///
392    /// # Examples
393    /// ```
394    /// use index_map::IndexMap;
395    ///
396    /// let mut map = IndexMap::new();
397    /// let a = map.insert("a");
398    /// assert_eq!(map.remove_entry(a), Some((0, "a")));
399    /// assert_eq!(map.remove(a), None);
400    /// ```
401    pub fn remove_entry(&mut self, index: usize) -> Option<(usize, T)> {
402        Some((index, self.remove(index)?))
403    }
404
405    /// Returns a reference to the value corresponding to the key.
406    ///
407    /// # Examples
408    /// ```
409    /// use index_map::IndexMap;
410    ///
411    /// let mut map = IndexMap::new();
412    /// map.insert("a");
413    /// assert_eq!(map.get(0), Some(&"a"));
414    /// assert_eq!(map.get(1), None);
415    /// ```
416    pub fn get(&self, index: usize) -> Option<&T> {
417        self.data.get(index)?.as_ref().into_inner()
418    }
419
420    /// Returns the key-value pair corresponding to the key.
421    ///
422    /// # Examples
423    /// ```
424    /// use index_map::IndexMap;
425    ///
426    /// let mut map = IndexMap::new();
427    /// map.insert("a");
428    /// assert_eq!(map.get_key_value(0), Some((0, &"a")));
429    /// assert_eq!(map.get_key_value(1), None);
430    /// ```
431    pub fn get_key_value(&self, index: usize) -> Option<(usize, &T)> {
432        Some((index, self.get(index)?))
433    }
434
435    /// Returns a mutable reference to the value corresponding to the key.
436    ///
437    /// # Examples
438    /// ```
439    /// use index_map::IndexMap;
440    ///
441    /// let mut map = IndexMap::new();
442    /// let a = map.insert("a");
443    /// if let Some(x) = map.get_mut(a) {
444    ///     *x = "b";
445    /// }
446    /// assert_eq!(map[a], "b");
447    /// ```
448    pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
449        self.data.get_mut(index)?.as_mut().into_inner()
450    }
451
452    /// Retains only the elements specified by the predicate.
453    ///
454    /// In other words, remove all pairs `(k, v)` such that `f(k, &mut v)` returns `false`.
455    ///
456    /// # Examples
457    /// ```
458    /// use index_map::IndexMap;
459    ///
460    /// let mut map = IndexMap::new();
461    /// for i in 0..6 {
462    ///     map.insert(i*2);
463    /// }
464    /// map.retain(|k, _| k % 2 == 0);
465    /// assert_eq!(map.len(), 3);
466    /// ```
467    pub fn retain<P>(&mut self, mut predicate: P)
468    where
469        P: FnMut(usize, &mut T) -> bool,
470    {
471        // Cannot use `self.iter_mut` as we need the pointer to the `OptionIndex` and not the value
472        // contained in it.
473        for (i, v) in self.data.iter_mut().enumerate() {
474            if let OptionIndex::Some(val) = v {
475                if !predicate(i, val) {
476                    *v = if let Some(head) = self.head {
477                        OptionIndex::Index(head)
478                    } else {
479                        OptionIndex::NoIndex
480                    };
481
482                    self.len -= 1;
483                    self.head = Some(i)
484                }
485            }
486        }
487    }
488}
489
490impl<T: Clone> Clone for IndexMap<T> {
491    fn clone(&self) -> Self {
492        Self {
493            data: self.data.clone(),
494            head: self.head,
495            len: self.len,
496        }
497    }
498}
499
500impl<T> Default for IndexMap<T> {
501    /// Creates an empty `IndexMap`, same as calling new.
502    fn default() -> Self {
503        Self::new()
504    }
505}
506
507use core::fmt;
508
509impl<T: fmt::Debug> fmt::Debug for IndexMap<T> {
510    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
511        f.debug_map().entries(self.iter()).finish()
512    }
513}
514
515use core::ops::{Index, IndexMut};
516
517impl<T> Index<usize> for IndexMap<T> {
518    type Output = T;
519
520    /// Returns a reference to the value corresponding to the supplied key.
521    ///
522    /// # Panics
523    /// Panics if the key is not present in the `IndexMap`.
524    fn index(&self, key: usize) -> &T {
525        self.get(key).unwrap()
526    }
527}
528
529impl<T> IndexMut<usize> for IndexMap<T> {
530    /// Returns a mutable reference to the value corresponding to the supplied key.
531    ///
532    /// # Panics
533    /// Panics if the key is not present in the `IndexMap`.
534    fn index_mut(&mut self, key: usize) -> &mut T {
535        self.get_mut(key).unwrap()
536    }
537}
538
539#[cfg(test)]
540mod tests {
541    use super::{IndexMap, OptionIndex as OI};
542
543    fn assert_state<T: Eq + core::fmt::Debug>(
544        map: &IndexMap<T>,
545        data: &[OI<T>],
546        head: Option<usize>,
547    ) {
548        assert_eq!(map.data[..], data[..]);
549        assert_eq!(map.head, head);
550    }
551
552    #[test]
553    fn test_map() {
554        let mut map = IndexMap::new();
555
556        let _ = map.insert('a');
557        let b = map.insert('b');
558        let c = map.insert('c');
559        let _ = map.insert('d');
560        let e = map.insert('e');
561
562        assert_state(
563            &map,
564            &[
565                OI::Some('a'),
566                OI::Some('b'),
567                OI::Some('c'),
568                OI::Some('d'),
569                OI::Some('e'),
570            ],
571            None,
572        );
573
574        assert_eq!(map.remove(b), Some('b'));
575        assert_state(
576            &map,
577            &[
578                OI::Some('a'),
579                OI::NoIndex,
580                OI::Some('c'),
581                OI::Some('d'),
582                OI::Some('e'),
583            ],
584            Some(1),
585        );
586
587        assert_eq!(map.remove(e), Some('e'));
588        assert_state(
589            &map,
590            &[
591                OI::Some('a'),
592                OI::NoIndex,
593                OI::Some('c'),
594                OI::Some('d'),
595                OI::Index(1),
596            ],
597            Some(4),
598        );
599
600        assert_eq!(map.remove(c), Some('c'));
601        assert_state(
602            &map,
603            &[
604                OI::Some('a'),
605                OI::NoIndex,
606                OI::Index(4),
607                OI::Some('d'),
608                OI::Index(1),
609            ],
610            Some(2),
611        );
612
613        map.shrink_to_fit();
614        assert_state(
615            &map,
616            &[OI::Some('a'), OI::NoIndex, OI::Index(1), OI::Some('d')],
617            Some(2),
618        );
619    }
620
621    #[test]
622    fn test_shrink_to_fit() {
623        let mut map = IndexMap::new();
624
625        let a = map.insert('a');
626        let b = map.insert('b');
627        let c = map.insert('c');
628        let d = map.insert('d');
629        let e = map.insert('e');
630
631        map.remove(e);
632        map.remove(b);
633        map.remove(d);
634
635        assert_state(
636            &map,
637            &[
638                OI::Some('a'),
639                OI::Index(4),
640                OI::Some('c'),
641                OI::Index(1),
642                OI::NoIndex,
643            ],
644            Some(3),
645        );
646
647        map.shrink_to_fit();
648
649        assert_state(&map, &[OI::Some('a'), OI::NoIndex, OI::Some('c')], Some(1));
650
651        map.remove(c);
652        map.shrink_to_fit();
653
654        assert_state(&map, &[OI::Some('a')], None);
655
656        map.remove(a);
657        assert_state(&map, &[OI::NoIndex], Some(0));
658
659        map.shrink_to_fit();
660        assert_state(&map, &[], None);
661
662        let mut map = IndexMap::new();
663
664        let _ = map.insert('a');
665        let b = map.insert('b');
666        let _ = map.insert('c');
667        let d = map.insert('d');
668        let e = map.insert('e');
669
670        map.remove(b);
671        map.remove(d);
672        map.remove(e);
673
674        assert_state(
675            &map,
676            &[
677                OI::Some('a'),
678                OI::NoIndex,
679                OI::Some('c'),
680                OI::Index(1),
681                OI::Index(3),
682            ],
683            Some(4),
684        );
685
686        map.shrink_to_fit();
687
688        assert_state(&map, &[OI::Some('a'), OI::NoIndex, OI::Some('c')], Some(1));
689    }
690}