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 (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 (hash, dormant)
123 };
124
125 // SAFETY: the item above is not used after this point.
126 let awakened_item = unsafe { dormant.awaken() };
127 let ref_mut = RefMut::new(hash, awakened_item);
128 f(ref_mut);
129 }
130 Entry::Occupied(entry)
131 }
132 Entry::Vacant(entry) => Entry::Vacant(entry),
133 }
134 }
135}
136
137/// A vacant entry.
138pub struct VacantEntry<'a, T: IdOrdItem> {
139 map: DormantMutRef<'a, IdOrdMap<T>>,
140}
141
142impl<'a, T: IdOrdItem> fmt::Debug for VacantEntry<'a, T> {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 f.debug_struct("VacantEntry").finish_non_exhaustive()
145 }
146}
147
148impl<'a, T: IdOrdItem> VacantEntry<'a, T> {
149 pub(super) unsafe fn new(map: DormantMutRef<'a, IdOrdMap<T>>) -> Self {
150 VacantEntry { map }
151 }
152
153 /// Sets the entry to a new value, returning a shared reference to the
154 /// value.
155 ///
156 /// # Panics
157 ///
158 /// Panics if the key is already present in the map. (The intention is that
159 /// the key should be what was passed into [`IdOrdMap::entry`], but that
160 /// isn't checked in this API due to borrow checker limitations.)
161 pub fn insert_ref(self, value: T) -> &'a T {
162 // SAFETY: The safety assumption behind `Self::new` guarantees that the
163 // original reference to the map is not used at this point.
164 let map = unsafe { self.map.awaken() };
165 let Ok(index) = map.insert_unique_impl(value) else {
166 panic!("key already present in map");
167 };
168 map.get_by_index(index).expect("index is known to be valid")
169 }
170
171 /// Sets the entry to a new value, returning a mutable reference to the
172 /// value.
173 pub fn insert(self, value: T) -> RefMut<'a, T>
174 where
175 T::Key<'a>: Hash,
176 {
177 // SAFETY: The safety assumption behind `Self::new` guarantees that the
178 // original reference to the map is not used at this point.
179 let map = unsafe { self.map.awaken() };
180 let Ok(index) = map.insert_unique_impl(value) else {
181 panic!("key already present in map");
182 };
183 map.get_by_index_mut(index).expect("index is known to be valid")
184 }
185
186 /// Sets the value of the entry, and returns an `OccupiedEntry`.
187 #[inline]
188 pub fn insert_entry(mut self, value: T) -> OccupiedEntry<'a, T> {
189 let index = {
190 // SAFETY: The safety assumption behind `Self::new` guarantees that the
191 // original reference to the map is not used at this point.
192 let map = unsafe { self.map.reborrow() };
193 let Ok(index) = map.insert_unique_impl(value) else {
194 panic!("key already present in map");
195 };
196 index
197 };
198
199 // SAFETY: map, as well as anything that was borrowed from it, is
200 // dropped once the above block exits.
201 unsafe { OccupiedEntry::new(self.map, index) }
202 }
203}
204
205/// A view into an occupied entry in an [`IdOrdMap`]. Part of the [`Entry`]
206/// enum.
207pub struct OccupiedEntry<'a, T: IdOrdItem> {
208 map: DormantMutRef<'a, IdOrdMap<T>>,
209 // index is a valid index into the map's internal hash table.
210 index: usize,
211}
212
213impl<'a, T: IdOrdItem> fmt::Debug for OccupiedEntry<'a, T> {
214 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
215 f.debug_struct("OccupiedEntry")
216 .field("index", &self.index)
217 .finish_non_exhaustive()
218 }
219}
220
221impl<'a, T: IdOrdItem> OccupiedEntry<'a, T> {
222 /// # Safety
223 ///
224 /// After self is created, the original reference created by
225 /// `DormantMutRef::new` must not be used.
226 pub(super) unsafe fn new(
227 map: DormantMutRef<'a, IdOrdMap<T>>,
228 index: usize,
229 ) -> Self {
230 OccupiedEntry { map, index }
231 }
232
233 /// Gets a reference to the value.
234 ///
235 /// If you need a reference to `T` that may outlive the destruction of the
236 /// `Entry` value, see [`into_ref`](Self::into_ref).
237 pub fn get(&self) -> &T {
238 // SAFETY: The safety assumption behind `Self::new` guarantees that the
239 // original reference to the map is not used at this point.
240 unsafe { self.map.reborrow_shared() }
241 .get_by_index(self.index)
242 .expect("index is known to be valid")
243 }
244
245 /// Gets a mutable reference to the value.
246 ///
247 /// If you need a reference to `T` that may outlive the destruction of the
248 /// `Entry` value, see [`into_mut`](Self::into_mut).
249 pub fn get_mut<'b>(&'b mut self) -> RefMut<'b, T>
250 where
251 T::Key<'b>: Hash,
252 {
253 // SAFETY: The safety assumption behind `Self::new` guarantees that the
254 // original reference to the map is not used at this point.
255 unsafe { self.map.reborrow() }
256 .get_by_index_mut(self.index)
257 .expect("index is known to be valid")
258 }
259
260 /// Converts self into a reference to the value.
261 ///
262 /// If you need multiple references to the `OccupiedEntry`, see
263 /// [`get`](Self::get).
264 pub fn into_ref(self) -> &'a T {
265 // SAFETY: The safety assumption behind `Self::new` guarantees that the
266 // original reference to the map is not used at this point.
267 unsafe { self.map.awaken() }
268 .get_by_index(self.index)
269 .expect("index is known to be valid")
270 }
271
272 /// Converts self into a mutable reference to the value.
273 ///
274 /// If you need multiple references to the `OccupiedEntry`, see
275 /// [`get_mut`](Self::get_mut).
276 pub fn into_mut(self) -> RefMut<'a, T>
277 where
278 T::Key<'a>: Hash,
279 {
280 // SAFETY: The safety assumption behind `Self::new` guarantees that the
281 // original reference to the map is not used at this point.
282 unsafe { self.map.awaken() }
283 .get_by_index_mut(self.index)
284 .expect("index is known to be valid")
285 }
286
287 /// Sets the entry to a new value, returning the old value.
288 ///
289 /// # Panics
290 ///
291 /// Panics if `value.key()` is different from the key of the entry.
292 pub fn insert(&mut self, value: T) -> T {
293 // SAFETY: The safety assumption behind `Self::new` guarantees that the
294 // original reference to the map is not used at this point.
295 //
296 // Note that `replace_at_index` panics if the keys don't match.
297 unsafe { self.map.reborrow() }.replace_at_index(self.index, value)
298 }
299
300 /// Takes ownership of the value from the map.
301 pub fn remove(mut self) -> T {
302 // SAFETY: The safety assumption behind `Self::new` guarantees that the
303 // original reference to the map is not used at this point.
304 unsafe { self.map.reborrow() }
305 .remove_by_index(self.index)
306 .expect("index is known to be valid")
307 }
308}