tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

map.rs (6120B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
      4 
      5 #![forbid(unsafe_code)]
      6 
      7 use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
      8 use rustc_hash::FxHashMap;
      9 use std::collections::hash_map;
     10 use std::hash::Hash;
     11 use std::mem;
     12 
     13 pub(super) struct Map<K, V> {
     14    inner: MapInner<K, V>,
     15 }
     16 
     17 enum MapInner<K, V> {
     18    Empty,
     19    One(V),
     20    Map(Box<FxHashMap<K, V>>),
     21 }
     22 
     23 pub(super) struct MapIter<'a, K, V> {
     24    inner: MapIterInner<'a, K, V>,
     25 }
     26 
     27 enum MapIterInner<'a, K, V> {
     28    One(std::option::IntoIter<&'a V>),
     29    Map(std::collections::hash_map::Values<'a, K, V>),
     30 }
     31 
     32 pub(super) enum Entry<'a, K, V> {
     33    Occupied(&'a mut V),
     34    Vacant(VacantEntry<'a, K, V>),
     35 }
     36 
     37 pub(super) struct VacantEntry<'a, K, V> {
     38    inner: VacantEntryInner<'a, K, V>,
     39 }
     40 
     41 enum VacantEntryInner<'a, K, V> {
     42    One(&'a mut MapInner<K, V>),
     43    Map(hash_map::VacantEntry<'a, K, V>),
     44 }
     45 
     46 impl<K, V> Default for Map<K, V> {
     47    fn default() -> Self {
     48        Map {
     49            inner: MapInner::Empty,
     50        }
     51    }
     52 }
     53 
     54 impl<'a, K, V> IntoIterator for &'a Map<K, V> {
     55    type Item = &'a V;
     56    type IntoIter = MapIter<'a, K, V>;
     57 
     58    fn into_iter(self) -> Self::IntoIter {
     59        MapIter {
     60            inner: match &self.inner {
     61                MapInner::Empty => MapIterInner::One(None.into_iter()),
     62                MapInner::One(one) => MapIterInner::One(Some(one).into_iter()),
     63                MapInner::Map(map) => MapIterInner::Map(map.values()),
     64            },
     65        }
     66    }
     67 }
     68 
     69 impl<'a, K, V> Iterator for MapIter<'a, K, V> {
     70    type Item = &'a V;
     71 
     72    fn next(&mut self) -> Option<Self::Item> {
     73        match &mut self.inner {
     74            MapIterInner::One(one_iter) => one_iter.next(),
     75            MapIterInner::Map(map_iter) => map_iter.next(),
     76        }
     77    }
     78 }
     79 
     80 impl<K, V> Map<K, V>
     81 where
     82    K: Eq + Hash,
     83 {
     84    pub(super) fn is_empty(&self) -> bool {
     85        match &self.inner {
     86            MapInner::Empty => true,
     87            MapInner::One(_) => false,
     88            MapInner::Map(map) => map.is_empty(),
     89        }
     90    }
     91 
     92    #[cfg(debug_assertions)]
     93    pub(super) fn len(&self) -> usize {
     94        match &self.inner {
     95            MapInner::Empty => 0,
     96            MapInner::One(_) => 1,
     97            MapInner::Map(map) => map.len(),
     98        }
     99    }
    100 
    101    pub(super) fn get(&self, key: &K, key_from_value: impl FnOnce(&V) -> K) -> Option<&V> {
    102        match &self.inner {
    103            MapInner::One(one) if *key == key_from_value(one) => Some(one),
    104            MapInner::Map(map) => map.get(key),
    105            MapInner::Empty | MapInner::One(_) => None,
    106        }
    107    }
    108 
    109    pub(super) fn entry(
    110        &mut self,
    111        key: K,
    112        key_from_value: impl FnOnce(&V) -> K,
    113    ) -> Entry<'_, K, V> {
    114        match self.inner {
    115            ref mut inner @ MapInner::Empty => Entry::Vacant(VacantEntry {
    116                inner: VacantEntryInner::One(inner),
    117            }),
    118            MapInner::One(_) => {
    119                let one = match mem::replace(&mut self.inner, MapInner::Empty) {
    120                    MapInner::One(one) => one,
    121                    _ => unreachable!(),
    122                };
    123                // If this panics, the child `one` will be lost.
    124                let one_key = key_from_value(&one);
    125                // Same for the equality test.
    126                if key == one_key {
    127                    self.inner = MapInner::One(one);
    128                    let one = match &mut self.inner {
    129                        MapInner::One(one) => one,
    130                        _ => unreachable!(),
    131                    };
    132                    return Entry::Occupied(one);
    133                }
    134                self.inner = MapInner::Map(Box::new(FxHashMap::with_capacity_and_hasher(
    135                    2,
    136                    Default::default(),
    137                )));
    138                let map = match &mut self.inner {
    139                    MapInner::Map(map) => map,
    140                    _ => unreachable!(),
    141                };
    142                map.insert(one_key, one);
    143                match map.entry(key) {
    144                    hash_map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry {
    145                        inner: VacantEntryInner::Map(entry),
    146                    }),
    147                    _ => unreachable!(),
    148                }
    149            },
    150            MapInner::Map(ref mut map) => match map.entry(key) {
    151                hash_map::Entry::Occupied(entry) => Entry::Occupied(entry.into_mut()),
    152                hash_map::Entry::Vacant(entry) => Entry::Vacant(VacantEntry {
    153                    inner: VacantEntryInner::Map(entry),
    154                }),
    155            },
    156        }
    157    }
    158 
    159    pub(super) fn remove(&mut self, key: &K, key_from_value: impl FnOnce(&V) -> K) -> Option<V> {
    160        match &mut self.inner {
    161            MapInner::One(one) if *key == key_from_value(one) => {
    162                match mem::replace(&mut self.inner, MapInner::Empty) {
    163                    MapInner::One(one) => Some(one),
    164                    _ => unreachable!(),
    165                }
    166            },
    167            MapInner::Map(map) => map.remove(key),
    168            MapInner::Empty | MapInner::One(_) => None,
    169        }
    170    }
    171 }
    172 
    173 impl<'a, K, V> VacantEntry<'a, K, V> {
    174    pub(super) fn insert(self, value: V) -> &'a mut V {
    175        match self.inner {
    176            VacantEntryInner::One(map) => {
    177                *map = MapInner::One(value);
    178                match map {
    179                    MapInner::One(one) => one,
    180                    _ => unreachable!(),
    181                }
    182            },
    183            VacantEntryInner::Map(entry) => entry.insert(value),
    184        }
    185    }
    186 }
    187 
    188 impl<K, V> MallocShallowSizeOf for Map<K, V>
    189 where
    190    K: Eq + Hash,
    191 {
    192    fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
    193        match &self.inner {
    194            MapInner::Map(m) => {
    195                // We want to account for both the box and the hashmap.
    196                m.shallow_size_of(ops) + (**m).shallow_size_of(ops)
    197            },
    198            MapInner::One(_) | MapInner::Empty => 0,
    199        }
    200    }
    201 }