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