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