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}