iddqd/id_ord_map/entry.rs
1use super::{IdOrdItem, IdOrdMap, RefMut};
2use crate::support::borrow::DormantMutRef;
3use core::{fmt, hash::Hash};
4
5/// An implementation of the Entry API for [`IdOrdMap`].
6pub enum Entry<'a, T: IdOrdItem> {
7 /// A vacant entry.
8 Vacant(VacantEntry<'a, T>),
9 /// An occupied entry.
10 Occupied(OccupiedEntry<'a, T>),
11}
12
13impl<'a, T: IdOrdItem> fmt::Debug for Entry<'a, T> {
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 match self {
16 Entry::Vacant(entry) => {
17 f.debug_tuple("Vacant").field(entry).finish()
18 }
19 Entry::Occupied(entry) => {
20 f.debug_tuple("Occupied").field(entry).finish()
21 }
22 }
23 }
24}
25
26impl<'a, T: IdOrdItem> Entry<'a, T> {
27 /// Ensures a value is in the entry by inserting the default if empty, and
28 /// returns a shared reference to the value in the entry.
29 ///
30 /// # Panics
31 ///
32 /// Panics if the key is already present in the map. (The intention is that
33 /// the key should be what was passed into [`IdOrdMap::entry`], but that
34 /// isn't checked in this API due to borrow checker limitations.)
35 #[inline]
36 pub fn or_insert_ref(self, default: T) -> &'a T {
37 match self {
38 Entry::Occupied(entry) => entry.into_ref(),
39 Entry::Vacant(entry) => entry.insert_ref(default),
40 }
41 }
42
43 /// Ensures a value is in the entry by inserting the default if empty, and
44 /// returns a mutable reference to the value in the entry.
45 ///
46 /// # Panics
47 ///
48 /// Panics if the key is already present in the map. (The intention is that
49 /// the key should be what was passed into [`IdOrdMap::entry`], but that
50 /// isn't checked in this API due to borrow checker limitations.)
51 #[inline]
52 pub fn or_insert(self, default: T) -> RefMut<'a, T>
53 where
54 T::Key<'a>: Hash,
55 {
56 match self {
57 Entry::Occupied(entry) => entry.into_mut(),
58 Entry::Vacant(entry) => entry.insert(default),
59 }
60 }
61
62 /// Ensures a value is in the entry by inserting the result of the default
63 /// function if empty, and returns a shared reference to the value in the
64 /// entry.
65 ///
66 /// # Panics
67 ///
68 /// Panics if the key is already present in the map. (The intention is that
69 /// the key should be what was passed into [`IdOrdMap::entry`], but that
70 /// isn't checked in this API due to borrow checker limitations.)
71 #[inline]
72 pub fn or_insert_with_ref<F: FnOnce() -> T>(self, default: F) -> &'a T {
73 match self {
74 Entry::Occupied(entry) => entry.into_ref(),
75 Entry::Vacant(entry) => entry.insert_ref(default()),
76 }
77 }
78
79 /// Ensures a value is in the entry by inserting the result of the default
80 /// function if empty, and returns a mutable reference to the value in the
81 /// entry.
82 ///
83 /// # Panics
84 ///
85 /// Panics if the key is already present in the map. (The intention is that
86 /// the key should be what was passed into [`IdOrdMap::entry`], but that
87 /// isn't checked in this API due to borrow checker limitations.)
88 #[inline]
89 pub fn or_insert_with<F: FnOnce() -> T>(self, default: F) -> RefMut<'a, T>
90 where
91 T::Key<'a>: Hash,
92 {
93 match self {
94 Entry::Occupied(entry) => entry.into_mut(),
95 Entry::Vacant(entry) => entry.insert(default()),
96 }
97 }
98
99 /// Provides in-place mutable access to an occupied entry before any
100 /// potential inserts into the map.
101 #[inline]
102 pub fn and_modify<F>(self, f: F) -> Self
103 where
104 F: FnOnce(RefMut<'_, T>),
105 T::Key<'a>: Hash,
106 {
107 match self {
108 Entry::Occupied(mut entry) => {
109 {
110 let (state, hash, dormant) = {
111 // SAFETY: The safety assumption behind
112 // `OccupiedEntry::new` guarantees that the original
113 // reference to the map is not used at this point.
114 let map = unsafe { entry.map.reborrow() };
115 let item = map
116 .items
117 .get_mut(entry.index)
118 .expect("index is valid");
119
120 let (item, dormant) = DormantMutRef::new(item);
121 let hash = map.tables.make_hash(item);
122 let state = map.tables.state().clone();
123 (state, hash, dormant)
124 };
125
126 // SAFETY: the item above is not used after this point.
127 let awakened_item = unsafe { dormant.awaken() };
128 let ref_mut = RefMut::new(state, hash, awakened_item);
129 f(ref_mut);
130 }
131 Entry::Occupied(entry)
132 }
133 Entry::Vacant(entry) => Entry::Vacant(entry),
134 }
135 }
136}
137
138/// A vacant entry.
139pub struct VacantEntry<'a, T: IdOrdItem> {
140 map: DormantMutRef<'a, IdOrdMap<T>>,
141}
142
143impl<'a, T: IdOrdItem> fmt::Debug for VacantEntry<'a, T> {
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 f.debug_struct("VacantEntry").finish_non_exhaustive()
146 }
147}
148
149impl<'a, T: IdOrdItem> VacantEntry<'a, T> {
150 pub(super) unsafe fn new(map: DormantMutRef<'a, IdOrdMap<T>>) -> Self {
151 VacantEntry { map }
152 }
153
154 /// Sets the entry to a new value, returning a shared reference to the
155 /// value.
156 ///
157 /// # Panics
158 ///
159 /// Panics if the key is already present in the map. (The intention is that
160 /// the key should be what was passed into [`IdOrdMap::entry`], but that
161 /// isn't checked in this API due to borrow checker limitations.)
162 pub fn insert_ref(self, value: T) -> &'a T {
163 // SAFETY: The safety assumption behind `Self::new` guarantees that the
164 // original reference to the map is not used at this point.
165 let map = unsafe { self.map.awaken() };
166 let Ok(index) = map.insert_unique_impl(value) else {
167 panic!("key already present in map");
168 };
169 map.get_by_index(index).expect("index is known to be valid")
170 }
171
172 /// Sets the entry to a new value, returning a mutable reference to the
173 /// value.
174 pub fn insert(self, value: T) -> RefMut<'a, T>
175 where
176 T::Key<'a>: Hash,
177 {
178 // SAFETY: The safety assumption behind `Self::new` guarantees that the
179 // original reference to the map is not used at this point.
180 let map = unsafe { self.map.awaken() };
181 let Ok(index) = map.insert_unique_impl(value) else {
182 panic!("key already present in map");
183 };
184 map.get_by_index_mut(index).expect("index is known to be valid")
185 }
186
187 /// Sets the value of the entry, and returns an `OccupiedEntry`.
188 #[inline]
189 pub fn insert_entry(mut self, value: T) -> OccupiedEntry<'a, T> {
190 let index = {
191 // SAFETY: The safety assumption behind `Self::new` guarantees that the
192 // original reference to the map is not used at this point.
193 let map = unsafe { self.map.reborrow() };
194 let Ok(index) = map.insert_unique_impl(value) else {
195 panic!("key already present in map");
196 };
197 index
198 };
199
200 // SAFETY: map, as well as anything that was borrowed from it, is
201 // dropped once the above block exits.
202 unsafe { OccupiedEntry::new(self.map, index) }
203 }
204}
205
206/// A view into an occupied entry in an [`IdOrdMap`]. Part of the [`Entry`]
207/// enum.
208pub struct OccupiedEntry<'a, T: IdOrdItem> {
209 map: DormantMutRef<'a, IdOrdMap<T>>,
210 // index is a valid index into the map's internal hash table.
211 index: usize,
212}
213
214impl<'a, T: IdOrdItem> fmt::Debug for OccupiedEntry<'a, T> {
215 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
216 f.debug_struct("OccupiedEntry")
217 .field("index", &self.index)
218 .finish_non_exhaustive()
219 }
220}
221
222impl<'a, T: IdOrdItem> OccupiedEntry<'a, T> {
223 /// # Safety
224 ///
225 /// After self is created, the original reference created by
226 /// `DormantMutRef::new` must not be used.
227 pub(super) unsafe fn new(
228 map: DormantMutRef<'a, IdOrdMap<T>>,
229 index: usize,
230 ) -> Self {
231 OccupiedEntry { map, index }
232 }
233
234 /// Gets a reference to the value.
235 ///
236 /// If you need a reference to `T` that may outlive the destruction of the
237 /// `Entry` value, see [`into_ref`](Self::into_ref).
238 pub fn get(&self) -> &T {
239 // SAFETY: The safety assumption behind `Self::new` guarantees that the
240 // original reference to the map is not used at this point.
241 unsafe { self.map.reborrow_shared() }
242 .get_by_index(self.index)
243 .expect("index is known to be valid")
244 }
245
246 /// Gets a mutable reference to the value.
247 ///
248 /// If you need a reference to `T` that may outlive the destruction of the
249 /// `Entry` value, see [`into_mut`](Self::into_mut).
250 pub fn get_mut<'b>(&'b mut self) -> RefMut<'b, T>
251 where
252 T::Key<'b>: Hash,
253 {
254 // SAFETY: The safety assumption behind `Self::new` guarantees that the
255 // original reference to the map is not used at this point.
256 unsafe { self.map.reborrow() }
257 .get_by_index_mut(self.index)
258 .expect("index is known to be valid")
259 }
260
261 /// Converts self into a reference to the value.
262 ///
263 /// If you need multiple references to the `OccupiedEntry`, see
264 /// [`get`](Self::get).
265 pub fn into_ref(self) -> &'a T {
266 // SAFETY: The safety assumption behind `Self::new` guarantees that the
267 // original reference to the map is not used at this point.
268 unsafe { self.map.awaken() }
269 .get_by_index(self.index)
270 .expect("index is known to be valid")
271 }
272
273 /// Converts self into a mutable reference to the value.
274 ///
275 /// If you need multiple references to the `OccupiedEntry`, see
276 /// [`get_mut`](Self::get_mut).
277 pub fn into_mut(self) -> RefMut<'a, T>
278 where
279 T::Key<'a>: Hash,
280 {
281 // SAFETY: The safety assumption behind `Self::new` guarantees that the
282 // original reference to the map is not used at this point.
283 unsafe { self.map.awaken() }
284 .get_by_index_mut(self.index)
285 .expect("index is known to be valid")
286 }
287
288 /// Sets the entry to a new value, returning the old value.
289 ///
290 /// # Panics
291 ///
292 /// Panics if `value.key()` is different from the key of the entry.
293 pub fn insert(&mut self, value: T) -> T {
294 // SAFETY: The safety assumption behind `Self::new` guarantees that the
295 // original reference to the map is not used at this point.
296 //
297 // Note that `replace_at_index` panics if the keys don't match.
298 unsafe { self.map.reborrow() }.replace_at_index(self.index, value)
299 }
300
301 /// Takes ownership of the value from the map.
302 pub fn remove(mut self) -> T {
303 // SAFETY: The safety assumption behind `Self::new` guarantees that the
304 // original reference to the map is not used at this point.
305 unsafe { self.map.reborrow() }
306 .remove_by_index(self.index)
307 .expect("index is known to be valid")
308 }
309}