rune_alloc/btree/map/entry.rs
1use core::fmt::{self, Debug};
2use core::marker::PhantomData;
3use core::mem;
4
5use crate::alloc::{Allocator, Global};
6
7use super::super::borrow::DormantMutRef;
8use super::super::node::{marker, Handle, NodeRef};
9use super::BTreeMap;
10
11use crate::alloc::AllocError;
12#[cfg(test)]
13use crate::testing::*;
14
15use Entry::*;
16
17/// A view into a single entry in a map, which may either be vacant or occupied.
18///
19/// This `enum` is constructed from the [`entry`] method on [`BTreeMap`].
20///
21/// [`entry`]: BTreeMap::entry
22pub enum Entry<'a, K: 'a, V: 'a, A: Allocator = Global> {
23 /// A vacant entry.
24 Vacant(VacantEntry<'a, K, V, A>),
25
26 /// An occupied entry.
27 Occupied(OccupiedEntry<'a, K, V, A>),
28}
29
30impl<K: Debug + Ord, V: Debug, A: Allocator> Debug for Entry<'_, K, V, A> {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 match *self {
33 Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(),
34 Occupied(ref o) => f.debug_tuple("Entry").field(o).finish(),
35 }
36 }
37}
38
39/// A view into a vacant entry in a `BTreeMap`.
40/// It is part of the [`Entry`] enum.
41pub struct VacantEntry<'a, K, V, A: Allocator = Global> {
42 pub(super) key: K,
43 /// `None` for a (empty) map without root
44 pub(super) handle: Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>>,
45 pub(super) dormant_map: DormantMutRef<'a, BTreeMap<K, V, A>>,
46
47 /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`.
48 pub(super) alloc: &'a A,
49
50 // Be invariant in `K` and `V`
51 pub(super) _marker: PhantomData<&'a mut (K, V)>,
52}
53
54impl<K: Debug + Ord, V, A: Allocator> Debug for VacantEntry<'_, K, V, A> {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.debug_tuple("VacantEntry").field(self.key()).finish()
57 }
58}
59
60/// A view into an occupied entry in a `BTreeMap`.
61/// It is part of the [`Entry`] enum.
62pub struct OccupiedEntry<'a, K, V, A: Allocator = Global> {
63 pub(super) handle: Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>,
64 pub(super) dormant_map: DormantMutRef<'a, BTreeMap<K, V, A>>,
65
66 /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`.
67 pub(super) alloc: &'a A,
68
69 // Be invariant in `K` and `V`
70 pub(super) _marker: PhantomData<&'a mut (K, V)>,
71}
72
73impl<K: Debug + Ord, V: Debug, A: Allocator> Debug for OccupiedEntry<'_, K, V, A> {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 f.debug_struct("OccupiedEntry")
76 .field("key", self.key())
77 .field("value", self.get())
78 .finish()
79 }
80}
81
82/// The error returned by [`try_insert`](BTreeMap::try_insert) when the key already exists.
83///
84/// Contains the occupied entry, and the value that was not inserted.
85pub struct OccupiedError<'a, K: 'a, V: 'a, A: Allocator = Global> {
86 /// The entry in the map that was already occupied.
87 pub entry: OccupiedEntry<'a, K, V, A>,
88 /// The value which was not inserted, because the entry was already occupied.
89 pub value: V,
90}
91
92impl<K: Debug + Ord, V: Debug, A: Allocator> Debug for OccupiedError<'_, K, V, A> {
93 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94 f.debug_struct("OccupiedError")
95 .field("key", self.entry.key())
96 .field("old_value", self.entry.get())
97 .field("new_value", &self.value)
98 .finish()
99 }
100}
101
102impl<K: Debug + Ord, V: Debug, A: Allocator> fmt::Display for OccupiedError<'_, K, V, A> {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 write!(
105 f,
106 "failed to insert {:?}, key {:?} already exists with value {:?}",
107 self.value,
108 self.entry.key(),
109 self.entry.get(),
110 )
111 }
112}
113
114impl<'a, K: Ord, V, A: Allocator> Entry<'a, K, V, A> {
115 /// Ensures a value is in the entry by inserting the default if empty, and
116 /// returns a mutable reference to the value in the entry.
117 ///
118 /// # Examples
119 ///
120 /// ```
121 /// use rune::alloc::BTreeMap;
122 ///
123 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
124 /// map.entry("poneyland").or_try_insert(12)?;
125 ///
126 /// assert_eq!(map["poneyland"], 12);
127 /// # Ok::<_, rune::alloc::Error>(())
128 /// ```
129 pub fn or_try_insert(self, default: V) -> Result<&'a mut V, AllocError> {
130 match self {
131 Occupied(entry) => Ok(entry.into_mut()),
132 Vacant(entry) => entry.try_insert(default),
133 }
134 }
135
136 /// Ensures a value is in the entry by inserting the result of the default
137 /// function if empty, and returns a mutable reference to the value in the
138 /// entry.
139 ///
140 /// # Examples
141 ///
142 /// ```
143 /// use rune::alloc::BTreeMap;
144 ///
145 /// let mut map: BTreeMap<&str, String> = BTreeMap::new();
146 /// let s = "hoho".to_string();
147 ///
148 /// map.entry("poneyland").or_try_insert_with(|| s)?;
149 ///
150 /// assert_eq!(map["poneyland"], "hoho".to_string());
151 /// # Ok::<_, rune::alloc::Error>(())
152 /// ```
153 pub fn or_try_insert_with<F: FnOnce() -> V>(self, default: F) -> Result<&'a mut V, AllocError> {
154 match self {
155 Occupied(entry) => Ok(entry.into_mut()),
156 Vacant(entry) => entry.try_insert(default()),
157 }
158 }
159
160 /// Ensures a value is in the entry by inserting, if empty, the result of
161 /// the default function. This method allows for generating key-derived
162 /// values for insertion by providing the default function a reference to
163 /// the key that was moved during the `.entry(key)` method call.
164 ///
165 /// The reference to the moved key is provided so that cloning or copying
166 /// the key is unnecessary, unlike with `.or_insert_with(|| ... )`.
167 ///
168 /// # Examples
169 ///
170 /// ```
171 /// use rune::alloc::BTreeMap;
172 ///
173 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
174 ///
175 /// map.entry("poneyland").or_try_insert_with_key(|key| key.chars().count())?;
176 ///
177 /// assert_eq!(map["poneyland"], 9);
178 /// # Ok::<_, rune::alloc::Error>(())
179 /// ```
180 #[inline]
181 pub fn or_try_insert_with_key<F: FnOnce(&K) -> V>(
182 self,
183 default: F,
184 ) -> Result<&'a mut V, AllocError> {
185 match self {
186 Occupied(entry) => Ok(entry.into_mut()),
187 Vacant(entry) => {
188 let value = default(entry.key());
189 entry.try_insert(value)
190 }
191 }
192 }
193
194 /// Returns a reference to this entry's key.
195 ///
196 /// # Examples
197 ///
198 /// ```
199 /// use rune::alloc::BTreeMap;
200 ///
201 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
202 /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
203 /// # Ok::<_, rune::alloc::Error>(())
204 /// ```
205 pub fn key(&self) -> &K {
206 match *self {
207 Occupied(ref entry) => entry.key(),
208 Vacant(ref entry) => entry.key(),
209 }
210 }
211
212 /// Provides in-place mutable access to an occupied entry before any
213 /// potential inserts into the map.
214 ///
215 /// # Examples
216 ///
217 /// ```
218 /// use rune::alloc::BTreeMap;
219 ///
220 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
221 ///
222 /// map.entry("poneyland")
223 /// .and_modify(|e| { *e += 1 })
224 /// .or_try_insert(42)?;
225 /// assert_eq!(map["poneyland"], 42);
226 ///
227 /// map.entry("poneyland")
228 /// .and_modify(|e| { *e += 1 })
229 /// .or_try_insert(42)?;
230 /// assert_eq!(map["poneyland"], 43);
231 /// # Ok::<_, rune::alloc::Error>(())
232 /// ```
233 pub fn and_modify<F>(self, f: F) -> Self
234 where
235 F: FnOnce(&mut V),
236 {
237 match self {
238 Occupied(mut entry) => {
239 f(entry.get_mut());
240 Occupied(entry)
241 }
242 Vacant(entry) => Vacant(entry),
243 }
244 }
245}
246
247impl<'a, K: Ord, V: Default, A: Allocator> Entry<'a, K, V, A> {
248 /// Ensures a value is in the entry by inserting the default value if empty,
249 /// and returns a mutable reference to the value in the entry.
250 ///
251 /// # Examples
252 ///
253 /// ```
254 /// use rune::alloc::BTreeMap;
255 ///
256 /// let mut map: BTreeMap<&str, Option<usize>> = BTreeMap::new();
257 /// map.entry("poneyland").or_try_default()?;
258 ///
259 /// assert_eq!(map["poneyland"], None);
260 /// # Ok::<_, rune::alloc::Error>(())
261 /// ```
262 pub fn or_try_default(self) -> Result<&'a mut V, AllocError> {
263 match self {
264 Occupied(entry) => Ok(entry.into_mut()),
265 Vacant(entry) => entry.try_insert(Default::default()),
266 }
267 }
268}
269
270impl<'a, K, V, A: Allocator> VacantEntry<'a, K, V, A> {
271 /// Gets a reference to the key that would be used when inserting a value
272 /// through the VacantEntry.
273 ///
274 /// # Examples
275 ///
276 /// ```
277 /// use rune::alloc::BTreeMap;
278 ///
279 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
280 /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
281 /// ```
282 pub fn key(&self) -> &K {
283 &self.key
284 }
285
286 /// Take ownership of the key.
287 ///
288 /// # Examples
289 ///
290 /// ```
291 /// use rune::alloc::BTreeMap;
292 /// use rune::alloc::btree_map::Entry;
293 ///
294 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
295 ///
296 /// if let Entry::Vacant(v) = map.entry("poneyland") {
297 /// v.into_key();
298 /// }
299 /// ```
300 pub fn into_key(self) -> K {
301 self.key
302 }
303
304 /// Sets the value of the entry with the `VacantEntry`'s key,
305 /// and returns a mutable reference to it.
306 ///
307 /// # Examples
308 ///
309 /// ```
310 /// use rune::alloc::BTreeMap;
311 /// use rune::alloc::btree_map::Entry;
312 ///
313 /// let mut map: BTreeMap<&str, u32> = BTreeMap::new();
314 ///
315 /// if let Entry::Vacant(o) = map.entry("poneyland") {
316 /// o.try_insert(37)?;
317 /// }
318 ///
319 /// assert_eq!(map["poneyland"], 37);
320 /// # Ok::<_, rune::alloc::Error>(())
321 /// ```
322 pub fn try_insert(mut self, value: V) -> Result<&'a mut V, AllocError> {
323 let out_ptr = match self.handle {
324 None => {
325 // SAFETY: There is no tree yet so no reference to it exists.
326 let map = unsafe { self.dormant_map.awaken() };
327 let mut root = NodeRef::new_leaf(self.alloc)?;
328 let val_ptr = root.borrow_mut().push(self.key, value) as *mut V;
329 map.root = Some(root.forget_type());
330 map.length = 1;
331 val_ptr
332 }
333 Some(handle) => {
334 let new_handle = handle.insert_recursing(self.key, value, self.alloc, |ins| {
335 drop(ins.left);
336 // SAFETY: Pushing a new root node doesn't invalidate
337 // handles to existing nodes.
338 let map = unsafe { self.dormant_map.reborrow() };
339 let root = map.root.as_mut().unwrap(); // same as ins.left
340 root.push_internal_level(self.alloc)?
341 .push(ins.kv.0, ins.kv.1, ins.right);
342 Ok(())
343 })?;
344
345 // Get the pointer to the value
346 let val_ptr = new_handle.into_val_mut();
347
348 // SAFETY: We have consumed self.handle.
349 let map = unsafe { self.dormant_map.awaken() };
350 map.length += 1;
351 val_ptr
352 }
353 };
354
355 // Now that we have finished growing the tree using borrowed references,
356 // dereference the pointer to a part of it, that we picked up along the way.
357 Ok(unsafe { &mut *out_ptr })
358 }
359
360 #[cfg(test)]
361 pub(crate) fn insert(self, value: V) -> &'a mut V {
362 self.try_insert(value).abort()
363 }
364}
365
366impl<'a, K, V, A: Allocator> OccupiedEntry<'a, K, V, A> {
367 /// Gets a reference to the key in the entry.
368 ///
369 /// # Examples
370 ///
371 /// ```
372 /// use rune::alloc::BTreeMap;
373 ///
374 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
375 /// map.entry("poneyland").or_try_insert(12)?;
376 /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
377 /// # Ok::<_, rune::alloc::Error>(())
378 /// ```
379 #[must_use]
380 pub fn key(&self) -> &K {
381 self.handle.reborrow().into_kv().0
382 }
383
384 /// Take ownership of the key and value from the map.
385 ///
386 /// # Examples
387 ///
388 /// ```
389 /// use rune::alloc::BTreeMap;
390 /// use rune::alloc::btree_map::Entry;
391 ///
392 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
393 /// map.entry("poneyland").or_try_insert(12)?;
394 ///
395 /// if let Entry::Occupied(o) = map.entry("poneyland") {
396 /// // We delete the entry from the map.
397 /// assert_eq!(o.remove_entry(), ("poneyland", 12));
398 /// }
399 ///
400 /// // If now try to get the value, it will panic:
401 /// // println!("{}", map["poneyland"]);
402 /// # Ok::<_, rune::alloc::Error>(())
403 /// ```
404 pub fn remove_entry(self) -> (K, V) {
405 self.remove_kv()
406 }
407
408 /// Gets a reference to the value in the entry.
409 ///
410 /// # Examples
411 ///
412 /// ```
413 /// use rune::alloc::BTreeMap;
414 /// use rune::alloc::btree_map::Entry;
415 ///
416 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
417 /// map.entry("poneyland").or_try_insert(12)?;
418 ///
419 /// if let Entry::Occupied(o) = map.entry("poneyland") {
420 /// assert_eq!(o.get(), &12);
421 /// }
422 /// # Ok::<_, rune::alloc::Error>(())
423 /// ```
424 #[must_use]
425 pub fn get(&self) -> &V {
426 self.handle.reborrow().into_kv().1
427 }
428
429 /// Gets a mutable reference to the value in the entry.
430 ///
431 /// If you need a reference to the `OccupiedEntry` that may outlive the
432 /// destruction of the `Entry` value, see [`into_mut`].
433 ///
434 /// [`into_mut`]: OccupiedEntry::into_mut
435 ///
436 /// # Examples
437 ///
438 /// ```
439 /// use rune::alloc::BTreeMap;
440 /// use rune::alloc::btree_map::Entry;
441 ///
442 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
443 /// map.entry("poneyland").or_try_insert(12)?;
444 ///
445 /// assert_eq!(map["poneyland"], 12);
446 /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
447 /// *o.get_mut() += 10;
448 /// assert_eq!(*o.get(), 22);
449 ///
450 /// // We can use the same Entry multiple times.
451 /// *o.get_mut() += 2;
452 /// }
453 /// assert_eq!(map["poneyland"], 24);
454 /// # Ok::<_, rune::alloc::Error>(())
455 /// ```
456 pub fn get_mut(&mut self) -> &mut V {
457 self.handle.kv_mut().1
458 }
459
460 /// Converts the entry into a mutable reference to its value.
461 ///
462 /// If you need multiple references to the `OccupiedEntry`, see [`get_mut`].
463 ///
464 /// [`get_mut`]: OccupiedEntry::get_mut
465 ///
466 /// # Examples
467 ///
468 /// ```
469 /// use rune::alloc::BTreeMap;
470 /// use rune::alloc::btree_map::Entry;
471 ///
472 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
473 /// map.entry("poneyland").or_try_insert(12)?;
474 ///
475 /// assert_eq!(map["poneyland"], 12);
476 /// if let Entry::Occupied(o) = map.entry("poneyland") {
477 /// *o.into_mut() += 10;
478 /// }
479 /// assert_eq!(map["poneyland"], 22);
480 /// # Ok::<_, rune::alloc::Error>(())
481 /// ```
482 #[must_use = "`self` will be dropped if the result is not used"]
483 pub fn into_mut(self) -> &'a mut V {
484 self.handle.into_val_mut()
485 }
486
487 /// Sets the value of the entry with the `OccupiedEntry`'s key,
488 /// and returns the entry's old value.
489 ///
490 /// # Examples
491 ///
492 /// ```
493 /// use rune::alloc::BTreeMap;
494 /// use rune::alloc::btree_map::Entry;
495 ///
496 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
497 /// map.entry("poneyland").or_try_insert(12)?;
498 ///
499 /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
500 /// assert_eq!(o.insert(15), 12);
501 /// }
502 ///
503 /// assert_eq!(map["poneyland"], 15);
504 /// # Ok::<_, rune::alloc::Error>(())
505 /// ```
506 pub fn insert(&mut self, value: V) -> V {
507 mem::replace(self.get_mut(), value)
508 }
509
510 /// Takes the value of the entry out of the map, and returns it.
511 ///
512 /// # Examples
513 ///
514 /// ```
515 /// use rune::alloc::BTreeMap;
516 /// use rune::alloc::btree_map::Entry;
517 ///
518 /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
519 /// map.entry("poneyland").or_try_insert(12)?;
520 ///
521 /// if let Entry::Occupied(o) = map.entry("poneyland") {
522 /// assert_eq!(o.remove(), 12);
523 /// }
524 ///
525 /// // If we try to get "poneyland"'s value, it'll panic:
526 /// // println!("{}", map["poneyland"]);
527 /// # Ok::<_, rune::alloc::Error>(())
528 /// ```
529 pub fn remove(self) -> V {
530 self.remove_kv().1
531 }
532
533 // Body of `remove_entry`, probably separate because the name reflects the returned pair.
534 pub(super) fn remove_kv(self) -> (K, V) {
535 let mut emptied_internal_root = false;
536 let (old_kv, _) = self
537 .handle
538 .remove_kv_tracking(|| emptied_internal_root = true, self.alloc);
539 // SAFETY: we consumed the intermediate root borrow, `self.handle`.
540 let map = unsafe { self.dormant_map.awaken() };
541 map.length -= 1;
542 if emptied_internal_root {
543 let root = map.root.as_mut().unwrap();
544 root.pop_internal_level(self.alloc);
545 }
546 old_kv
547 }
548}