Skip to main content

acktor_ipc/double_map/
entry.rs

1//! The [`Entry`] API for in-place manipulation of a [`DoubleMap`][super::DoubleMap].
2//!
3//! Mirrors [`std::collections::hash_map::Entry`] as closely as possible, adapted to
4//! the two-key shape of `DoubleMap`.
5
6use std::collections::hash_map;
7use std::mem;
8
9/// A view into a single entry in a [`DoubleMap`][super::DoubleMap], which may be
10/// either vacant or occupied.
11pub enum Entry<'a, K1, K2, V> {
12    /// Both provided keys identify the same existing entry.
13    Occupied(OccupiedEntry<'a, K1, K2, V>),
14    /// Neither of the provided keys is present — a new entry can be inserted.
15    Vacant(VacantEntry<'a, K1, K2, V>),
16}
17
18impl<K1, K2, V> Entry<'_, K1, K2, V> {
19    /// Returns a reference to the `K1` key of this entry.
20    pub fn key1(&self) -> &K1 {
21        match self {
22            Entry::Occupied(e) => e.key1(),
23            Entry::Vacant(e) => e.key1(),
24        }
25    }
26
27    /// Returns a reference to the `K2` key of this entry.
28    pub fn key2(&self) -> &K2 {
29        match self {
30            Entry::Occupied(e) => e.key2(),
31            Entry::Vacant(e) => e.key2(),
32        }
33    }
34
35    /// Returns a reference to the keys of type `K1` and `K2` of this entry.
36    pub fn keys(&self) -> (&K1, &K2) {
37        match self {
38            Entry::Occupied(e) => e.keys(),
39            Entry::Vacant(e) => e.keys(),
40        }
41    }
42}
43
44impl<'a, K1, K2, V> Entry<'a, K1, K2, V>
45where
46    K1: Clone,
47    K2: Clone,
48{
49    /// Ensures a value is in the entry by inserting `default` if vacant, and returns
50    /// a mutable reference to the value.
51    pub fn or_insert(self, default: V) -> &'a mut V {
52        match self {
53            Entry::Occupied(e) => e.into_mut(),
54            Entry::Vacant(e) => e.insert(default),
55        }
56    }
57
58    /// Ensures a value is in the entry by inserting the result of `default` if
59    /// vacant, and returns a mutable reference to the value.
60    pub fn or_insert_with<F>(self, default: F) -> &'a mut V
61    where
62        F: FnOnce() -> V,
63    {
64        match self {
65            Entry::Occupied(e) => e.into_mut(),
66            Entry::Vacant(e) => e.insert(default()),
67        }
68    }
69
70    /// Ensures a value is in the entry by inserting the result of `default` if
71    /// vacant, and returns a mutable reference to the value. The `default` closure
72    /// receives references to the keys of the entry.
73    pub fn or_insert_with_keys<F>(self, default: F) -> &'a mut V
74    where
75        F: FnOnce(&K1, &K2) -> V,
76    {
77        match self {
78            Entry::Occupied(e) => e.into_mut(),
79            Entry::Vacant(e) => {
80                let (key1, key2) = e.keys();
81                let v = default(key1, key2);
82                e.insert(v)
83            }
84        }
85    }
86
87    /// Provides in-place mutation of an occupied entry before any potential
88    /// insertion, then returns the entry unchanged for further chaining.
89    pub fn and_modify<F>(mut self, f: F) -> Self
90    where
91        F: FnOnce(&mut V),
92    {
93        if let Entry::Occupied(e) = &mut self {
94            f(e.get_mut());
95        }
96        self
97    }
98
99    /// Sets the value of the entry, and returns an `OccupiedEntry`.
100    pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K1, K2, V> {
101        match self {
102            Entry::Occupied(mut e) => {
103                e.insert(value);
104                e
105            }
106            Entry::Vacant(e) => e.insert_entry(value),
107        }
108    }
109
110    /// Ensures a value is in the entry by inserting the default value if vacant.
111    pub fn or_default(self) -> &'a mut V
112    where
113        V: Default,
114    {
115        self.or_insert_with(V::default)
116    }
117}
118
119/// A view into a vacant entry of a [`DoubleMap`][super::DoubleMap].
120pub struct VacantEntry<'a, K1, K2, V> {
121    primary: hash_map::VacantEntry<'a, K1, (K2, V)>,
122    secondary: hash_map::VacantEntry<'a, K2, K1>,
123}
124
125impl<'a, K1, K2, V> VacantEntry<'a, K1, K2, V> {
126    pub(super) fn new(
127        primary: hash_map::VacantEntry<'a, K1, (K2, V)>,
128        secondary: hash_map::VacantEntry<'a, K2, K1>,
129    ) -> Self {
130        Self { primary, secondary }
131    }
132}
133
134impl<K1, K2, V> VacantEntry<'_, K1, K2, V> {
135    /// Returns a reference to the `K1` key that would be inserted.
136    pub fn key1(&self) -> &K1 {
137        self.primary.key()
138    }
139
140    /// Returns a reference to the `K2` key that would be inserted.
141    pub fn key2(&self) -> &K2 {
142        self.secondary.key()
143    }
144
145    /// Returns a reference to the keys of type `K1` and `K2` that would be inserted.
146    pub fn keys(&self) -> (&K1, &K2) {
147        (self.key1(), self.key2())
148    }
149
150    /// Consumes this entry and returns the `(K1, K2)` keys it was holding.
151    pub fn into_keys(self) -> (K1, K2) {
152        (self.primary.into_key(), self.secondary.into_key())
153    }
154}
155
156impl<'a, K1, K2, V> VacantEntry<'a, K1, K2, V>
157where
158    K1: Clone,
159    K2: Clone,
160{
161    /// Sets the value of the entry with the VacantEntry’s key, and returns a mutable
162    /// reference to it.
163    pub fn insert(self, value: V) -> &'a mut V {
164        let key1 = self.primary.key().clone();
165        let key2 = self.secondary.key().clone();
166        self.secondary.insert(key1);
167        let (_, v) = self.primary.insert((key2, value));
168        v
169    }
170
171    /// Sets the value of the entry with the VacantEntry’s key, and returns an
172    /// OccupiedEntry.
173    pub fn insert_entry(self, value: V) -> OccupiedEntry<'a, K1, K2, V> {
174        let key1 = self.primary.key().clone();
175        let key2 = self.secondary.key().clone();
176        let occupied_secondary = self.secondary.insert_entry(key1.clone());
177        let occupied_primary = self.primary.insert_entry((key2.clone(), value));
178        OccupiedEntry {
179            primary: occupied_primary,
180            secondary: occupied_secondary,
181        }
182    }
183}
184
185/// A view into an occupied entry of a [`DoubleMap`][super::DoubleMap].
186pub struct OccupiedEntry<'a, K1, K2, V> {
187    primary: hash_map::OccupiedEntry<'a, K1, (K2, V)>,
188    secondary: hash_map::OccupiedEntry<'a, K2, K1>,
189}
190
191impl<'a, K1, K2, V> OccupiedEntry<'a, K1, K2, V> {
192    pub(super) fn new(
193        primary: hash_map::OccupiedEntry<'a, K1, (K2, V)>,
194        secondary: hash_map::OccupiedEntry<'a, K2, K1>,
195    ) -> Self {
196        Self { primary, secondary }
197    }
198}
199
200impl<'a, K1, K2, V> OccupiedEntry<'a, K1, K2, V> {
201    /// Returns a reference to the `K1` key of the entry.
202    pub fn key1(&self) -> &K1 {
203        self.primary.key()
204    }
205
206    /// Returns a reference to the `K2` key of the entry.
207    pub fn key2(&self) -> &K2 {
208        self.secondary.key()
209    }
210
211    /// Returns a reference to the keys of type `K1` and `K2` of the entry.
212    pub fn keys(&self) -> (&K1, &K2) {
213        (self.key1(), self.key2())
214    }
215
216    /// Returns a reference to the value in the entry.
217    pub fn get(&self) -> &V {
218        &self.primary.get().1
219    }
220
221    /// Returns a mutable reference to the value in the entry.
222    pub fn get_mut(&mut self) -> &mut V {
223        &mut self.primary.get_mut().1
224    }
225
226    /// Converts this entry into a mutable reference to its value.
227    pub fn into_mut(self) -> &'a mut V {
228        &mut self.primary.into_mut().1
229    }
230
231    /// Replaces the value in the entry and returns the old value.
232    pub fn insert(&mut self, value: V) -> V {
233        mem::replace(self.get_mut(), value)
234    }
235
236    /// Removes the entry from the map and returns its value.
237    pub fn remove(self) -> V {
238        self.remove_entry().2
239    }
240
241    /// Removes the entry from the map and returns its full `(K1, K2, V)` triple.
242    pub fn remove_entry(self) -> (K1, K2, V) {
243        self.secondary.remove_entry();
244        let (key1, (key2, value)) = self.primary.remove_entry();
245        (key1, key2, value)
246    }
247}