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}