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}