Skip to main content

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}