mule_map/mule_map/entry.rs
1use super::key::PrimInt;
2use Entry::{Occupied, Vacant};
3
4/// A view into a single entry in a map, which may either be vacant or occupied.
5///
6/// This enum is constructed from the entry method on [`crate::MuleMap`].
7///
8/// Analogous to [`std::collections::hash_map::Entry`]
9pub enum Entry<'a, K: 'a, V: 'a> {
10 Occupied(OccupiedEntry<'a, K, V>),
11 Vacant(VacantEntry<'a, K, V>),
12}
13
14pub enum OccupiedEntry<'a, K: 'a, V: 'a> {
15 HashMap(OccupiedHashMapEntry<'a, K, V>),
16 Vec(OccupiedVecEntry<'a, K, V>),
17}
18
19pub enum VacantEntry<'a, K: 'a, V: 'a> {
20 HashMap(VacantHashMapEntry<'a, K, V>),
21 Vec(VacantVecEntry<'a, K, V>),
22}
23
24#[derive(Debug)]
25pub struct OccupiedHashMapEntry<'a, K: 'a, V: 'a> {
26 pub(crate) base: std::collections::hash_map::OccupiedEntry<'a, K, V>,
27}
28
29#[derive(Debug)]
30pub struct OccupiedVecEntry<'a, K: 'a, V: 'a> {
31 pub(crate) value: &'a mut Option<V>,
32 pub(crate) key: K,
33}
34
35#[derive(Debug)]
36pub struct VacantHashMapEntry<'a, K: 'a, V: 'a> {
37 pub(crate) base: std::collections::hash_map::VacantEntry<'a, K, V>,
38}
39
40#[derive(Debug)]
41pub struct VacantVecEntry<'a, K: 'a, V: 'a> {
42 pub(crate) value: &'a mut Option<V>,
43 pub(crate) key: K,
44}
45
46impl<'a, K, V> Entry<'a, K, V>
47where
48 K: PrimInt,
49 V: PartialEq,
50{
51 /// Ensures a value is in the entry by inserting the default if empty, and returns a mutable reference to the value
52 /// in the entry.
53 ///
54 /// # Example
55 /// ```
56 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
57 /// mule_map.entry(5).or_insert(3);
58 /// ```
59 ///
60 /// Analogous to [`std::collections::hash_map::Entry::or_insert`]
61 #[inline]
62 pub fn or_insert(self, default: V) -> &'a mut V {
63 match self {
64 Occupied(entry) => entry.into_mut(),
65 Vacant(entry) => entry.insert(default),
66 }
67 }
68
69 /// Ensures a value is in the entry by inserting the result of the default function if empty, and returns a mutable
70 /// reference to the value in the entry.
71 ///
72 /// # Example
73 /// ```
74 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
75 /// mule_map.entry(5).or_insert_with(|| 1 + 1);
76 /// ```
77 ///
78 /// Analogous to [`std::collections::hash_map::Entry::or_insert_with`]
79 #[inline]
80 pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
81 match self {
82 Occupied(entry) => entry.into_mut(),
83 Vacant(entry) => entry.insert(default()),
84 }
85 }
86
87 /// Ensures a value is in the entry by inserting, if empty, the result of the default function.
88 ///
89 /// # Example
90 /// ```
91 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
92 /// mule_map.entry(5).or_insert_with_key(|key| key as usize + 1);
93 /// ```
94 ///
95 /// Analogous to [`std::collections::hash_map::Entry::or_insert_with_key`]
96 #[inline]
97 pub fn or_insert_with_key<F: FnOnce(K) -> V>(self, default: F) -> &'a mut V {
98 match self {
99 Occupied(entry) => entry.into_mut(),
100 Vacant(entry) => {
101 let value = default(entry.key());
102 entry.insert(value)
103 }
104 }
105 }
106
107 /// Returns this entry’s key.
108 ///
109 /// # Example
110 /// ```
111 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
112 /// assert_eq!(mule_map.entry(5).key(), 5);
113 /// ```
114 ///
115 /// Analogous to [`std::collections::hash_map::Entry::key`]
116 #[inline]
117 #[must_use]
118 pub fn key(&self) -> K {
119 match *self {
120 Occupied(ref entry) => entry.key(),
121 Vacant(ref entry) => entry.key(),
122 }
123 }
124
125 /// Provides in-place mutable access to an occupied entry before any potential inserts into the map.
126 ///
127 /// # Example
128 /// ```
129 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
130 /// mule_map.entry(5).and_modify(|e| *e += 1).or_insert(1);
131 /// ```
132 ///
133 /// Analogous to [`std::collections::hash_map::Entry::and_modify`]
134 #[inline]
135 #[allow(clippy::return_self_not_must_use)]
136 pub fn and_modify<F>(self, f: F) -> Self
137 where
138 F: FnOnce(&mut V),
139 {
140 match self {
141 Occupied(mut entry) => {
142 f(entry.get_mut());
143 Occupied(entry)
144 }
145 Vacant(entry) => Vacant(entry),
146 }
147 }
148
149 /// Sets the value of the entry, and returns an [`OccupiedEntry`].
150 ///
151 /// # Example
152 /// ```
153 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
154 /// let entry = mule_map.entry(5).insert_entry(10);
155 /// ```
156 ///
157 /// Analogous to [`std::collections::hash_map::Entry::insert_entry`]
158 #[inline]
159 pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
160 match self {
161 Occupied(mut entry) => {
162 entry.insert(value);
163 entry
164 }
165 Vacant(entry) => entry.insert_entry(value),
166 }
167 }
168}
169
170impl<'a, K, V> OccupiedEntry<'a, K, V>
171where
172 K: PrimInt,
173 V: PartialEq,
174{
175 /// Returns this entry’s key.
176 ///
177 /// # Example
178 /// ```
179 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
180 /// mule_map.entry(5).or_insert(12);
181 /// assert_eq!(mule_map.entry(5).key(), 5);
182 /// ```
183 ///
184 /// Analogous to [`std::collections::hash_map::OccupiedEntry::key`]
185 #[inline]
186 #[must_use]
187 pub fn key(&self) -> K {
188 match self {
189 OccupiedEntry::HashMap(entry) => *entry.base.key(),
190 OccupiedEntry::Vec(entry) => entry.key(),
191 }
192 }
193
194 /// Take the ownership of the key and value from the map.
195 ///
196 /// # Example
197 /// ```
198 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
199 /// mule_map.entry(5).or_insert(12);
200 /// if let mule_map::Entry::Occupied(o) = mule_map.entry(5) {
201 /// o.remove_entry();
202 /// }
203 ///
204 /// assert_eq!(mule_map.contains_key(5), false);
205 /// ```
206 ///
207 /// Analogous to [`std::collections::hash_map::OccupiedEntry::remove_entry`]
208 #[inline]
209 pub fn remove_entry(self) -> (K, V)
210 where
211 V: Clone,
212 {
213 match self {
214 OccupiedEntry::HashMap(entry) => entry.base.remove_entry(),
215 OccupiedEntry::Vec(entry) => entry.remove_entry(),
216 }
217 }
218
219 /// Gets a reference to the value in the entry.
220 ///
221 /// # Example
222 /// ```
223 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
224 /// mule_map.entry(5).or_insert(12);
225 /// if let mule_map::Entry::Occupied(o) = mule_map.entry(5) {
226 /// assert_eq!(o.get(), &12);
227 /// }
228 /// ```
229 ///
230 /// Analogous to [`std::collections::hash_map::OccupiedEntry::get`]
231 #[inline]
232 #[must_use]
233 pub fn get(&self) -> &V {
234 match self {
235 OccupiedEntry::HashMap(entry) => entry.base.get(),
236 OccupiedEntry::Vec(entry) => entry.get(),
237 }
238 }
239
240 /// Gets a mutable reference to the value in the entry.
241 ///
242 /// If you need a reference to the [`OccupiedEntry`] which may outlive the destruction of the [`Entry`] value, see
243 /// [`OccupiedEntry::into_mut`].
244 ///
245 /// # Example
246 /// ```
247 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
248 /// mule_map.entry(5).or_insert(12);
249 /// if let mule_map::Entry::Occupied(mut o) = mule_map.entry(5) {
250 /// *o.get_mut() += 10;
251 /// assert_eq!(o.get(), &22);
252 /// *o.get_mut() += 2;
253 /// }
254 /// assert_eq!(mule_map.get(5), Some(&24));
255 /// ```
256 ///
257 /// Analogous to [`std::collections::hash_map::OccupiedEntry::get_mut`]
258 #[inline]
259 #[must_use]
260 pub fn get_mut(&mut self) -> &mut V {
261 match self {
262 OccupiedEntry::HashMap(entry) => entry.base.get_mut(),
263 OccupiedEntry::Vec(entry) => entry.get_mut(),
264 }
265 }
266
267 /// Converts the [`OccupiedEntry`] into a mutable reference to the value in the entry with a lifetime bound to the
268 /// map itself.
269 ///
270 /// If you need multiple references to the [`OccupiedEntry`], see [`OccupiedEntry::get_mut`].
271 ///
272 /// # Example
273 /// ```
274 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
275 /// mule_map.entry(5).or_insert(12);
276 /// if let mule_map::Entry::Occupied(mut o) = mule_map.entry(5) {
277 /// *o.into_mut() += 10;
278 /// }
279 /// assert_eq!(mule_map.get(5), Some(&22));
280 /// ```
281 ///
282 /// Analogous to [`std::collections::hash_map::OccupiedEntry::into_mut`]
283 #[inline]
284 #[must_use]
285 pub fn into_mut(self) -> &'a mut V {
286 match self {
287 OccupiedEntry::HashMap(entry) => entry.base.into_mut(),
288 OccupiedEntry::Vec(entry) => entry.into_mut(),
289 }
290 }
291
292 /// Sets the value of the entry, and returns the entry’s old value.
293 ///
294 /// # Example
295 /// ```
296 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
297 /// mule_map.entry(5).or_insert(12);
298 /// if let mule_map::Entry::Occupied(mut o) = mule_map.entry(5) {
299 /// assert_eq!(o.insert(15), 12);
300 /// }
301 /// assert_eq!(mule_map.get(5), Some(&15));
302 /// ```
303 ///
304 /// Analogous to [`std::collections::hash_map::OccupiedEntry::insert`]
305 #[inline]
306 pub fn insert(&mut self, value: V) -> V {
307 match self {
308 OccupiedEntry::HashMap(entry) => entry.base.insert(value),
309 OccupiedEntry::Vec(entry) => entry.insert(value),
310 }
311 }
312
313 /// Takes the value out of the entry, and returns it.
314 ///
315 /// # Example
316 /// ```
317 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
318 /// mule_map.entry(5).or_insert(12);
319 /// if let mule_map::Entry::Occupied(mut o) = mule_map.entry(5) {
320 /// assert_eq!(o.remove(), 12);
321 /// }
322 /// assert_eq!(mule_map.contains_key(5), false);
323 /// ```
324 ///
325 /// Analogous to [`std::collections::hash_map::OccupiedEntry::remove`]
326 #[inline]
327 pub fn remove(self) -> V
328 where
329 V: Clone,
330 {
331 match self {
332 OccupiedEntry::HashMap(entry) => entry.base.remove(),
333 OccupiedEntry::Vec(entry) => entry.remove(),
334 }
335 }
336}
337
338impl<'a, K, V> OccupiedVecEntry<'a, K, V>
339where
340 K: PrimInt,
341{
342 #[inline]
343 #[must_use]
344 pub(crate) fn key(&self) -> K {
345 self.key
346 }
347 #[inline]
348 pub(crate) fn remove_entry(self) -> (K, V) {
349 (
350 self.key,
351 self.value.take().expect("Value should be occupied."),
352 )
353 }
354 #[inline]
355 #[must_use]
356 pub(crate) fn get(&self) -> &V {
357 self.value.as_ref().expect("Value should be occupied.")
358 }
359 #[inline]
360 #[must_use]
361 pub(crate) fn get_mut(&mut self) -> &mut V {
362 self.value.as_mut().expect("Value should be occupied.")
363 }
364 #[inline]
365 #[must_use]
366 pub(crate) fn into_mut(self) -> &'a mut V {
367 self.value.as_mut().expect("Value should be occupied.")
368 }
369 #[inline]
370 pub(crate) fn insert(&mut self, value: V) -> V {
371 let mut value = value;
372 std::mem::swap(&mut value, self.get_mut());
373 value
374 }
375 #[inline]
376 pub(crate) fn remove(self) -> V {
377 self.value.take().expect("Value should be occupied.")
378 }
379}
380
381impl<'a, K, V> VacantEntry<'a, K, V>
382where
383 K: PrimInt,
384{
385 /// Returns this entry’s key.
386 ///
387 /// # Example
388 /// ```
389 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
390 /// assert_eq!(mule_map.entry(5).key(), 5);
391 /// ```
392 ///
393 /// Analogous to [`std::collections::hash_map::VacantEntry::key`]
394 #[inline]
395 #[must_use]
396 pub fn key(&self) -> K {
397 match self {
398 VacantEntry::HashMap(entry) => *entry.base.key(),
399 VacantEntry::Vec(entry) => entry.key(),
400 }
401 }
402
403 /// Sets the value of the entry with the VacantEntry’s key, and returns a mutable reference to it.
404 ///
405 /// # Example
406 /// ```
407 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
408 /// if let mule_map::Entry::Vacant(o) = mule_map.entry(5) {
409 /// o.insert(37);
410 /// }
411 /// assert_eq!(mule_map.get(5), Some(&37));
412 /// ```
413 ///
414 /// Analogous to [`std::collections::hash_map::VacantEntry::insert`]
415 #[inline]
416 pub fn insert(self, value: V) -> &'a mut V {
417 match self {
418 VacantEntry::HashMap(entry) => entry.base.insert(value),
419 VacantEntry::Vec(entry) => entry.insert(value),
420 }
421 }
422
423 /// Sets the value of the entry with the VacantEntry’s key, and returns an [`OccupiedEntry`].
424 ///
425 /// # Example
426 /// ```
427 /// let mut mule_map = mule_map::MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
428 /// if let mule_map::Entry::Vacant(o) = mule_map.entry(5) {
429 /// o.insert_entry(37);
430 /// }
431 /// assert_eq!(mule_map.get(5), Some(&37));
432 /// ```
433 ///
434 /// Analogous to [`std::collections::hash_map::VacantEntry::insert_entry`]
435 #[inline]
436 pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
437 match self {
438 VacantEntry::HashMap(entry) => OccupiedEntry::HashMap(OccupiedHashMapEntry {
439 base: entry.base.insert_entry(value),
440 }),
441 VacantEntry::Vec(entry) => entry.insert_entry(value),
442 }
443 }
444}
445
446impl<'a, K, V> VacantVecEntry<'a, K, V>
447where
448 K: PrimInt,
449{
450 #[inline]
451 #[must_use]
452 pub(crate) fn key(&self) -> K {
453 self.key
454 }
455
456 #[inline]
457 pub(crate) fn insert(self, value: V) -> &'a mut V {
458 self.value.insert(value)
459 }
460
461 #[inline]
462 pub(crate) fn insert_entry(self, value: V) -> OccupiedEntry<'a, K, V> {
463 _ = self.value.insert(value);
464
465 OccupiedEntry::Vec(OccupiedVecEntry {
466 value: self.value,
467 key: self.key,
468 })
469 }
470}
471
472#[cfg(test)]
473mod tests {
474 use crate::MuleMap;
475
476 #[test]
477 fn test_entry() {
478 let mut mule_map = MuleMap::<u32, usize, fnv_rs::FnvBuildHasher>::new();
479 assert_eq!(mule_map.entry(5).and_modify(|e| *e += 1).or_insert(1), &1);
480 assert_eq!(mule_map.entry(5).and_modify(|e| *e += 1).or_insert(1), &2);
481 }
482}