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}