1#![forbid(unsafe_code)]
6
7use fxhash::FxHashMap;
8use malloc_size_of::{MallocShallowSizeOf, MallocSizeOfOps};
9use std::collections::hash_map;
10use std::hash::Hash;
11use std::mem;
12
13pub(super) struct Map<K, V> {
14 inner: MapInner<K, V>,
15}
16
17enum MapInner<K, V> {
18 Empty,
19 One(V),
20 Map(Box<FxHashMap<K, V>>),
21}
22
23pub(super) struct MapIter<'a, K, V> {
24 inner: MapIterInner<'a, K, V>,
25}
26
27enum MapIterInner<'a, K, V> {
28 One(std::option::IntoIter<&'a V>),
29 Map(std::collections::hash_map::Values<'a, K, V>),
30}
31
32pub(super) enum Entry<'a, K, V> {
33 Occupied(&'a mut V),
34 Vacant(VacantEntry<'a, K, V>),
35}
36
37pub(super) struct VacantEntry<'a, K, V> {
38 inner: VacantEntryInner<'a, K, V>,
39}
40
41enum VacantEntryInner<'a, K, V> {
42 One(&'a mut MapInner<K, V>),
43 Map(hash_map::VacantEntry<'a, K, V>),
44}
45
46impl<K, V> Default for Map<K, V> {
47 fn default() -> Self {
48 Map {
49 inner: MapInner::Empty,
50 }
51 }
52}
53
54impl<'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
69impl<'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
80impl<K, V> Map<K, V>
81where
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 let one_key = key_from_value(&one);
125 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
173impl<'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
188impl<K, V> MallocShallowSizeOf for Map<K, V>
189where
190 K: Eq + Hash,
191{
192 fn shallow_size_of(&self, ops: &mut MallocSizeOfOps) -> usize {
193 match &self.inner {
194 MapInner::Map(m) => {
195 m.shallow_size_of(ops) + (**m).shallow_size_of(ops)
197 },
198 MapInner::One(_) | MapInner::Empty => 0,
199 }
200 }
201}