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 }