rb_interval_map/
entry.rs

1use crate::index::{IndexType, NodeIndex};
2use crate::interval::Interval;
3use crate::intervalmap::IntervalMap;
4use crate::node::Node;
5
6/// A view into a single entry in a map, which may either be vacant or occupied.
7#[derive(Debug)]
8pub enum Entry<'a, T, V, Ix> {
9    /// An occupied entry.
10    Occupied(OccupiedEntry<'a, T, V, Ix>),
11    /// A vacant entry.
12    Vacant(VacantEntry<'a, T, V, Ix>),
13}
14
15/// A view into an occupied entry in a `IntervalMap`.
16/// It is part of the [`Entry`] enum.
17#[derive(Debug)]
18pub struct OccupiedEntry<'a, T, V, Ix> {
19    /// Reference to the map
20    pub map_ref: &'a mut IntervalMap<T, V, Ix>,
21    /// The entry node
22    pub node_idx: NodeIndex<Ix>,
23}
24
25/// A view into a vacant entry in a `IntervalMap`.
26/// It is part of the [`Entry`] enum.
27#[derive(Debug)]
28pub struct VacantEntry<'a, T, V, Ix> {
29    /// Mutable reference to the map
30    pub map_ref: &'a mut IntervalMap<T, V, Ix>,
31    /// The interval of this entry
32    pub interval: Interval<T>,
33}
34
35impl<'a, T, V, Ix> Entry<'a, T, V, Ix>
36where
37    T: Ord,
38    Ix: IndexType,
39{
40    /// Ensures a value is in the entry by inserting the default if empty, and returns
41    /// a mutable reference to the value in the entry.
42    ///
43    /// # Example
44    /// ```rust
45    /// use rb_interval_map::{Interval, IntervalMap, Entry};
46    ///
47    /// let mut map = IntervalMap::new();
48    /// assert!(matches!(map.entry(Interval::new(1, 2)), Entry::Vacant(_)));
49    /// map.entry(Interval::new(1, 2)).or_insert(3);
50    /// assert!(matches!(map.entry(Interval::new(1, 2)), Entry::Occupied(_)));
51    /// assert_eq!(map.get(&Interval::new(1, 2)), Some(&3));
52    /// ```
53    #[inline]
54    pub fn or_insert(self, default: V) -> &'a mut V {
55        match self {
56            Entry::Occupied(entry) => entry.map_ref.node_mut(entry.node_idx, Node::value_mut),
57            Entry::Vacant(entry) => {
58                let entry_idx = NodeIndex::new(entry.map_ref.nodes.len());
59                let _ignore = entry.map_ref.insert(entry.interval, default);
60                entry.map_ref.node_mut(entry_idx, Node::value_mut)
61            }
62        }
63    }
64
65    /// Provides in-place mutable access to an occupied entry before any
66    /// potential inserts into the map.
67    ///
68    /// # Panics
69    ///
70    /// This method panics when the node is a sentinel node
71    ///
72    /// # Example
73    /// ```rust
74    /// use rb_interval_map::{Interval, IntervalMap, Entry};
75    ///
76    /// let mut map = IntervalMap::new();
77    ///
78    /// map.insert(Interval::new(6, 7), 3);
79    /// assert!(matches!(map.entry(Interval::new(6, 7)), Entry::Occupied(_)));
80    /// map.entry(Interval::new(6, 7)).and_modify(|v| *v += 1);
81    /// assert_eq!(map.get(&Interval::new(6, 7)), Some(&4));
82    /// ```
83    #[inline]
84    #[must_use]
85    pub fn and_modify<F>(self, f: F) -> Self
86    where
87        F: FnOnce(&mut V),
88    {
89        match self {
90            Entry::Occupied(entry) => {
91                f(entry.map_ref.node_mut(entry.node_idx, Node::value_mut));
92                Self::Occupied(entry)
93            }
94            Entry::Vacant(entry) => Self::Vacant(entry),
95        }
96    }
97}