vecmap.rs

  1/// A collection that provides a map interface but is backed by vectors.
  2///
  3/// This is suitable for small key-value stores where the item count is not
  4/// large enough to overcome the overhead of a more complex algorithm.
  5///
  6/// If this meets your use cases, then [`VecMap`] should be a drop-in
  7/// replacement for [`std::collections::HashMap`] or [`crate::HashMap`]. Note
  8/// that we are adding APIs on an as-needed basis. If the API you need is not
  9/// present yet, please add it!
 10///
 11/// Because it uses vectors as a backing store, the map also iterates over items
 12/// in insertion order, like [`crate::IndexMap`].
 13///
 14/// This struct uses a struct-of-arrays (SoA) representation which tends to be
 15/// more cache efficient and promotes autovectorization when using simple key or
 16/// value types.
 17#[derive(Default)]
 18pub struct VecMap<K, V> {
 19    keys: Vec<K>,
 20    values: Vec<V>,
 21}
 22
 23impl<K, V> VecMap<K, V> {
 24    pub fn new() -> Self {
 25        Self {
 26            keys: Vec::new(),
 27            values: Vec::new(),
 28        }
 29    }
 30
 31    pub fn iter(&self) -> Iter<'_, K, V> {
 32        Iter {
 33            iter: self.keys.iter().zip(self.values.iter()),
 34        }
 35    }
 36}
 37
 38impl<K: Eq, V> VecMap<K, V> {
 39    pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
 40        match self.keys.iter().position(|k| k == &key) {
 41            Some(index) => Entry::Occupied(OccupiedEntry {
 42                key: &self.keys[index],
 43                value: &mut self.values[index],
 44            }),
 45            None => Entry::Vacant(VacantEntry { map: self, key }),
 46        }
 47    }
 48}
 49
 50pub struct Iter<'a, K, V> {
 51    iter: std::iter::Zip<std::slice::Iter<'a, K>, std::slice::Iter<'a, V>>,
 52}
 53
 54impl<'a, K, V> Iterator for Iter<'a, K, V> {
 55    type Item = (&'a K, &'a V);
 56
 57    fn next(&mut self) -> Option<Self::Item> {
 58        self.iter.next()
 59    }
 60}
 61
 62pub enum Entry<'a, K, V> {
 63    Occupied(OccupiedEntry<'a, K, V>),
 64    Vacant(VacantEntry<'a, K, V>),
 65}
 66
 67impl<'a, K, V> Entry<'a, K, V> {
 68    pub fn key(&self) -> &K {
 69        match self {
 70            Entry::Occupied(entry) => entry.key,
 71            Entry::Vacant(entry) => &entry.key,
 72        }
 73    }
 74
 75    pub fn or_insert_with_key<F>(self, default: F) -> &'a mut V
 76    where
 77        F: FnOnce(&K) -> V,
 78    {
 79        match self {
 80            Entry::Occupied(entry) => entry.value,
 81            Entry::Vacant(entry) => {
 82                entry.map.values.push(default(&entry.key));
 83                entry.map.keys.push(entry.key);
 84                match entry.map.values.last_mut() {
 85                    Some(value) => value,
 86                    None => unreachable!("vec empty after pushing to it"),
 87                }
 88            }
 89        }
 90    }
 91
 92    pub fn or_insert_with<F>(self, default: F) -> &'a mut V
 93    where
 94        F: FnOnce() -> V,
 95    {
 96        self.or_insert_with_key(|_| default())
 97    }
 98
 99    pub fn or_insert(self, value: V) -> &'a mut V {
100        self.or_insert_with_key(|_| value)
101    }
102
103    pub fn or_insert_default(self) -> &'a mut V
104    where
105        V: Default,
106    {
107        self.or_insert_with_key(|_| Default::default())
108    }
109}
110
111pub struct OccupiedEntry<'a, K, V> {
112    key: &'a K,
113    value: &'a mut V,
114}
115
116pub struct VacantEntry<'a, K, V> {
117    map: &'a mut VecMap<K, V>,
118    key: K,
119}