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