intmap/lib.rs
1#![forbid(unsafe_code)]
2
3//! Specialized hashmap for integer based keys.
4//!
5//! For more information see the [README](https://github.com/JesperAxelsson/rust-intmap/blob/master/README.md).
6//!
7//! <div class="warning">
8//! Be aware that no effort is made against DoS attacks.
9//! </div>
10
11#[cfg(feature = "serde")]
12mod serde;
13
14mod entry;
15mod int;
16mod int_key;
17mod iter;
18
19use core::iter::{IntoIterator, Iterator};
20use int::SealedInt;
21
22pub use entry::*;
23pub use int::Int;
24pub use int_key::IntKey;
25pub use iter::*;
26
27// Test examples from the README.
28#[doc = include_str!("../README.md")]
29#[cfg(doctest)]
30pub struct ReadmeDoctests;
31
32/// A hashmap that maps an integer based `K` to `V`.
33#[derive(Clone)]
34pub struct IntMap<K, V> {
35 // The slots for the key/value pairs.
36 //
37 // The number of slots is what we call "capacity". Two or more key/value pairs occupy the same
38 // slot if they have a hash collision.
39 // The size of `cache` as binary exponent. The actual size of `cache` is `2^size`.
40 cache: Vec<Vec<(K, V)>>,
41 // The size of `cache` as binary exponent. The actual size of `cache` is `2^size`.
42 size: u32,
43 // A bit mask for calculating an index for `cache`. Must be recomputed if `size` changes.
44 mod_mask: usize,
45 // The number of stored key/value pairs.
46 count: usize,
47 // The ratio between key/value pairs and available slots that we try to ensure.
48 //
49 // Multiplied by 1000, e.g. a load factor of 90.9% will result in the value 909.
50 load_factor: usize,
51}
52
53impl<K, V> IntMap<K, V> {
54 /// Creates a new [`IntMap`].
55 ///
56 /// The [`IntMap`] is initially created with a capacity of 0, so it will not allocate until it
57 /// is first inserted into.
58 ///
59 /// The [`IntMap`] is initially created with a capacity of 0, so it will not allocate until it
60 /// is first inserted into.
61 ///
62 /// # Examples
63 ///
64 /// ```
65 /// use intmap::IntMap;
66 ///
67 /// let mut map: IntMap<u64, u64> = IntMap::new();
68 /// assert_eq!(map, IntMap::default());
69 /// ```
70 pub const fn new() -> Self {
71 Self {
72 cache: Vec::new(),
73 size: 0,
74 count: 0,
75 mod_mask: 0,
76 load_factor: 909, // 90.9%
77 }
78 }
79}
80
81impl<K: IntKey, V> IntMap<K, V> {
82 /// Creates a new [`IntMap`] with at least the given capacity.
83 ///
84 /// If the capacity is 0, the [`IntMap`] will not allocate. Otherwise the capacity is rounded
85 /// to the next power of two and space for elements is allocated accordingly.
86 ///
87 /// # Examples
88 ///
89 /// ```
90 /// use intmap::IntMap;
91 ///
92 /// let mut map: IntMap<u64, u64> = IntMap::with_capacity(20);
93 /// ```
94 pub fn with_capacity(capacity: usize) -> Self {
95 let mut map = Self::new();
96 map.reserve(capacity);
97 map
98 }
99
100 /// Sets the load factor of the [`IntMap`] rounded to the first decimal point.
101 ///
102 /// A load factor between 0.0 and 1.0 will reduce hash collisions but use more space.
103 /// A load factor above 1.0 will tolerate hash collisions and use less space.
104 ///
105 /// # Examples
106 ///
107 /// ```
108 /// use intmap::IntMap;
109 ///
110 /// let mut map: IntMap<u64, u64> = IntMap::with_capacity(20);
111 /// map.set_load_factor(0.909); // Sets load factor to 90.9%
112 /// ```
113 pub fn set_load_factor(&mut self, load_factor: f32) {
114 self.load_factor = (load_factor * 1000.) as usize;
115 self.increase_cache_if_needed();
116 }
117
118 /// Returns the current load factor.
119 pub fn get_load_factor(&self) -> f32 {
120 self.load_factor as f32 / 1000.
121 }
122
123 /// Ensures that the [`IntMap`] has space for at least `additional` more elements
124 pub fn reserve(&mut self, additional: usize) {
125 let capacity = self.count + additional;
126 while self.lim() < capacity {
127 self.increase_cache();
128 }
129 }
130
131 /// Inserts a key/value pair into the [`IntMap`].
132 ///
133 /// This function returns the previous value if any otherwise `None`.
134 ///
135 /// # Examples
136 ///
137 /// ```
138 /// use intmap::IntMap;
139 ///
140 /// let mut map: IntMap::<u64, _> = IntMap::new();
141 /// assert_eq!(map.insert(21, "Eat my shorts"), None);
142 /// assert_eq!(map.insert(21, "Ay, caramba"), Some("Eat my shorts"));
143 /// assert_eq!(map.get(21), Some(&"Ay, caramba"));
144 /// ```
145 pub fn insert(&mut self, key: K, value: V) -> Option<V> {
146 self.increase_cache_if_needed();
147
148 let k = key.into_int();
149 let ix = k.calc_index(self.mod_mask, K::PRIME);
150
151 let vals = &mut self.cache[ix];
152 let pos = vals.iter().position(|kv| kv.0.into_int() == k);
153
154 let old = if let Some(pos) = pos {
155 Some(vals.swap_remove(pos).1)
156 } else {
157 // Only increase count if we actually add a new entry
158 self.count += 1;
159 None
160 };
161
162 vals.push((key, value));
163
164 old
165 }
166
167 /// Insert a key/value pair into the [`IntMap`] if the key is not yet inserted.
168 ///
169 /// This function returns true if key/value were inserted and false otherwise.
170 ///
171 /// # Examples
172 ///
173 /// ```
174 /// use intmap::IntMap;
175 ///
176 /// let mut map: IntMap::<u64, _> = IntMap::new();
177 /// assert!(map.insert_checked(21, "Eat my shorts"));
178 /// assert!(!map.insert_checked(21, "Ay, caramba"));
179 /// assert_eq!(map.get(21), Some(&"Eat my shorts"));
180 /// ```
181 pub fn insert_checked(&mut self, key: K, value: V) -> bool {
182 self.increase_cache_if_needed();
183
184 let k = key.into_int();
185 let ix = k.calc_index(self.mod_mask, K::PRIME);
186
187 let vals = &mut self.cache[ix];
188 if vals.iter().any(|kv| kv.0.into_int() == k) {
189 return false;
190 }
191
192 self.count += 1;
193 vals.push((key, value));
194
195 true
196 }
197
198 /// Gets the value for the given key from the [`IntMap`].
199 ///
200 /// # Examples
201 ///
202 /// ```
203 /// use intmap::IntMap;
204 ///
205 /// let mut map: IntMap<u64, u64> = IntMap::new();
206 /// map.insert(21, 42);
207 /// let val = map.get(21);
208 /// assert!(val.is_some());
209 /// assert_eq!(*val.unwrap(), 42);
210 /// assert!(map.contains_key(21));
211 /// ```
212 pub fn get(&self, key: K) -> Option<&V> {
213 if self.is_empty() {
214 return None;
215 }
216
217 let k = key.into_int();
218 let ix = k.calc_index(self.mod_mask, K::PRIME);
219
220 let vals = &self.cache[ix];
221
222 vals.iter()
223 .find_map(|kv| (kv.0.into_int() == k).then(|| &kv.1))
224 }
225
226 /// Gets the mutable value for the given key from the [`IntMap`].
227 ///
228 /// # Examples
229 ///
230 /// ```
231 /// use intmap::IntMap;
232 ///
233 /// let mut map: IntMap<u64, u64> = IntMap::new();
234 /// map.insert(21, 42);
235 ///
236 /// assert_eq!(*map.get(21).unwrap(), 42);
237 /// assert!(map.contains_key(21));
238 ///
239 /// {
240 /// let mut val = map.get_mut(21).unwrap();
241 /// *val+=1;
242 /// }
243 /// assert_eq!(*map.get(21).unwrap(), 43);
244 /// ```
245 pub fn get_mut(&mut self, key: K) -> Option<&mut V> {
246 if self.is_empty() {
247 return None;
248 }
249
250 let k = key.into_int();
251 let ix = k.calc_index(self.mod_mask, K::PRIME);
252
253 let vals = &mut self.cache[ix];
254
255 vals.iter_mut()
256 .find_map(|kv| (kv.0.into_int() == k).then(move || &mut kv.1))
257 }
258
259 /// Removes the value for given key from the [`IntMap`] and returns it.
260 ///
261 /// # Examples
262 ///
263 /// ```
264 /// use intmap::IntMap;
265 ///
266 /// let mut map: IntMap<u64, u64> = IntMap::new();
267 /// map.insert(21, 42);
268 /// let val = map.remove(21);
269 /// assert!(val.is_some());
270 /// assert_eq!(val.unwrap(), 42);
271 /// assert!(!map.contains_key(21));
272 /// ```
273 pub fn remove(&mut self, key: K) -> Option<V> {
274 if self.is_empty() {
275 return None;
276 }
277
278 let k = key.into_int();
279 let ix = k.calc_index(self.mod_mask, K::PRIME);
280
281 let vals = &mut self.cache[ix];
282
283 for i in 0..vals.len() {
284 let peek = &vals[i].0;
285
286 if peek.into_int() == k {
287 self.count -= 1;
288 let kv = vals.swap_remove(i);
289 return Some(kv.1);
290 }
291 }
292
293 None
294 }
295
296 /// Returns true if the key is present in the [`IntMap`].
297 ///
298 /// # Examples
299 ///
300 /// ```
301 /// use intmap::IntMap;
302 ///
303 /// let mut map: IntMap<u64, u64> = IntMap::new();
304 /// map.insert(21, 42);
305 /// assert!(map.contains_key(21));
306 /// ```
307 pub fn contains_key(&self, key: K) -> bool {
308 self.get(key).is_some()
309 }
310
311 /// Removes all elements from the [`IntMap`].
312 ///
313 /// # Examples
314 ///
315 /// ```
316 /// use intmap::IntMap;
317 ///
318 /// let mut map: IntMap<u64, u64> = IntMap::new();
319 /// map.insert(21, 42);
320 /// map.clear();
321 /// assert_eq!(map.len(), 0);
322 /// ```
323 pub fn clear(&mut self) {
324 for vals in &mut self.cache {
325 vals.clear();
326 }
327
328 self.count = 0;
329 }
330
331 /// Retains only the key/value pairs specified by the predicate.
332 ///
333 /// In other words, remove all elements such that `f(key, &value)` returns false.
334 ///
335 /// # Examples
336 ///
337 /// ```
338 /// use intmap::IntMap;
339 ///
340 /// let mut map: IntMap<u64, u64> = IntMap::new();
341 /// map.insert(1, 11);
342 /// map.insert(2, 12);
343 /// map.insert(4, 13);
344 ///
345 /// // retain only the odd values
346 /// map.retain(|k, v| *v % 2 == 1);
347 ///
348 /// assert_eq!(map.len(), 2);
349 /// assert!(map.contains_key(1));
350 /// assert!(map.contains_key(4));
351 /// ```
352 pub fn retain<F>(&mut self, mut f: F)
353 where
354 F: FnMut(K, &V) -> bool,
355 {
356 let mut removed = 0;
357 for vals in &mut self.cache {
358 vals.retain(|(k, v)| {
359 let keep = (f)(*k, v);
360 if !keep {
361 removed += 1;
362 }
363 keep
364 });
365 }
366
367 self.count -= removed;
368 }
369
370 /// Returns true if the [`IntMap`] is empty
371 ///
372 /// # Examples
373 ///
374 /// ```
375 /// use intmap::IntMap;
376 ///
377 /// let mut map: IntMap<u64, u64> = IntMap::new();
378 /// map.insert(21, 42);
379 /// assert!(!map.is_empty());
380 /// map.remove(21);
381 /// assert!(map.is_empty());
382 /// ```
383 pub fn is_empty(&self) -> bool {
384 self.count == 0
385 }
386
387 //**** Iterators *****
388
389 /// Returns an [`Iterator`] over all key/value pairs.
390 pub fn iter(&self) -> Iter<'_, K, V> {
391 Iter::new(&self.cache)
392 }
393
394 /// Returns an [`Iterator`] over all key/value pairs with mutable value.
395 pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
396 IterMut::new(&mut self.cache)
397 }
398
399 /// Returns an [`Iterator`] over all keys.
400 pub fn keys(&self) -> Keys<'_, K, V> {
401 Keys { inner: self.iter() }
402 }
403
404 /// Returns an [`Iterator`] over all values.
405 pub fn values(&self) -> Values<'_, K, V> {
406 Values { inner: self.iter() }
407 }
408
409 /// Returns an [`Iterator`] over all mutable values.
410 pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> {
411 ValuesMut {
412 inner: self.iter_mut(),
413 }
414 }
415
416 /// Returns an [`Iterator`] over all key/value pairs that removes the pairs from the [`IntMap`]
417 /// during iteration.
418 ///
419 /// If the [`Iterator`] is droppend then all remaining key/value pairs will be removed from
420 /// the [`IntMap`].
421 pub fn drain(&mut self) -> Drain<'_, K, V> {
422 Drain::new(&mut self.cache, &mut self.count)
423 }
424
425 //**** Internal hash stuff *****
426
427 #[inline(always)]
428 fn lim(&self) -> usize {
429 if self.size == 0 {
430 0
431 } else {
432 2usize.pow(self.size)
433 }
434 }
435
436 fn increase_cache(&mut self) {
437 self.size += 1;
438 let new_lim = self.lim();
439 self.mod_mask = new_lim - 1;
440
441 let mut vec: Vec<Vec<(K, V)>> = (0..new_lim).map(|_| Vec::new()).collect();
442 std::mem::swap(&mut self.cache, &mut vec);
443
444 for key in vec.into_iter().flatten() {
445 let k = key.0.into_int();
446 let ix = k.calc_index(self.mod_mask, K::PRIME);
447
448 let vals = &mut self.cache[ix];
449 vals.push(key);
450 }
451
452 debug_assert!(
453 self.cache.len() == self.lim(),
454 "cache vector the wrong length, lim: {:?} cache: {:?}",
455 self.lim(),
456 self.cache.len()
457 );
458 }
459
460 #[inline]
461 fn increase_cache_if_needed(&mut self) -> bool {
462 let initial_cache_len = self.cache.len();
463
464 // Handle empty cache to prevent division by zero.
465 if self.cache.is_empty() {
466 self.increase_cache();
467 }
468
469 // Tried using floats here but insert performance tanked.
470 while ((self.count * 1000) / self.cache.len()) > self.load_factor {
471 self.increase_cache();
472 }
473
474 initial_cache_len != self.cache.len()
475 }
476
477 //**** More public methods *****
478
479 /// Returns the number of key/value pairs in the [`IntMap`].
480 pub fn len(&self) -> usize {
481 self.count
482 }
483
484 /// Returns the number of filled slots.
485 pub fn load(&self) -> u64 {
486 self.cache.iter().filter(|vals| !vals.is_empty()).count() as u64
487 }
488
489 /// Returns the ratio between key/value pairs and available slots as percentage.
490 ///
491 /// # Examples
492 ///
493 /// ```
494 /// use intmap::IntMap;
495 ///
496 /// let mut map: IntMap<u64, u64> = IntMap::with_capacity(2);
497 /// map.set_load_factor(2.0);
498 /// assert_eq!(map.load_rate(), 0.0);
499 /// map.insert(1, 42);
500 /// assert_eq!(map.load_rate(), 50.0);
501 /// map.insert(2, 42);
502 /// assert_eq!(map.load_rate(), 100.0);
503 /// map.insert(3, 42);
504 /// assert_eq!(map.load_rate(), 150.0);
505 /// ```
506 pub fn load_rate(&self) -> f64 {
507 (self.count as f64) / (self.cache.len() as f64) * 100f64
508 }
509
510 /// Returns the total number of available slots.
511 pub fn capacity(&self) -> usize {
512 self.cache.len()
513 }
514
515 //**** Testing methods *****
516
517 /// Checks whether the actual count of key/value pairs matches [`IntMap::count`].
518 ///
519 /// Only for testing.
520 #[doc(hidden)]
521 pub fn assert_count(&self) -> bool {
522 let count = self.cache.iter().flatten().count();
523
524 self.count == count
525 }
526
527 /// Returns a new [`IntMap`] that contains only the collisions of the current [`IntMap`].
528 ///
529 /// Only for testing.
530 #[doc(hidden)]
531 pub fn collisions(&self) -> IntMap<u64, u64> {
532 let mut map = IntMap::new();
533
534 for s in self.cache.iter() {
535 let key = s.len() as u64;
536 if key > 1 {
537 if !map.contains_key(key) {
538 map.insert(key, 1);
539 } else {
540 let counter = map.get_mut(key).unwrap();
541 *counter += 1;
542 }
543 }
544 }
545
546 map
547 }
548
549 //**** Entry API *****
550
551 /// Gets the [`Entry`] that corresponds to the given key.
552 ///
553 /// # Examples
554 ///
555 /// ```
556 /// use intmap::{IntMap, Entry};
557 ///
558 /// let mut counters = IntMap::new();
559 ///
560 /// for number in [10, 30, 10, 40, 50, 50, 60, 50] {
561 /// let counter = match counters.entry(number) {
562 /// Entry::Occupied(entry) => entry.into_mut(),
563 /// Entry::Vacant(entry) => entry.insert(0),
564 /// };
565 /// *counter += 1;
566 /// }
567 ///
568 /// assert_eq!(counters.get(10), Some(&2));
569 /// assert_eq!(counters.get(20), None);
570 /// assert_eq!(counters.get(30), Some(&1));
571 /// assert_eq!(counters.get(40), Some(&1));
572 /// assert_eq!(counters.get(50), Some(&3));
573 /// assert_eq!(counters.get(60), Some(&1));
574 /// ```
575 pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
576 Entry::new(key, self)
577 }
578}
579
580impl<K, V> Default for IntMap<K, V> {
581 fn default() -> Self {
582 Self::new()
583 }
584}
585
586// ***************** Equality *********************
587
588impl<K, V> PartialEq for IntMap<K, V>
589where
590 K: IntKey,
591 V: PartialEq,
592{
593 fn eq(&self, other: &IntMap<K, V>) -> bool {
594 self.count == other.count && self.iter().all(|(k, a)| other.get(k) == Some(a))
595 }
596}
597impl<K: IntKey, V: Eq> Eq for IntMap<K, V> {}
598
599// ***************** Debug *********************
600
601impl<K, V> std::fmt::Debug for IntMap<K, V>
602where
603 K: IntKey + std::fmt::Debug,
604 V: std::fmt::Debug,
605{
606 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
607 fmt.debug_map().entries(self.iter()).finish()
608 }
609}