1use std::{
2 borrow::Borrow,
3 collections::HashMap,
4 fmt,
5 hash::Hash,
6 ops::{Deref, DerefMut},
7};
8
9use rt_ref::{BorrowFail, Cell, Ref, RefMut};
10
11use crate::Entry;
12
13#[derive(Debug)]
15pub struct RtMap<K, V>(HashMap<K, Cell<V>>);
16
17impl<K, V> Default for RtMap<K, V> {
18 fn default() -> Self {
19 Self(Default::default())
20 }
21}
22
23macro_rules! borrow_panic {
24 ($key:ident) => {
25 panic!(
26 "Expected to borrow `{key:?}`, but it does not exist.",
27 key = $key
28 )
29 };
30}
31
32impl<K, V> RtMap<K, V>
47where
48 K: Hash + Eq,
49{
50 pub fn new() -> Self {
62 Self::default()
63 }
64
65 pub fn with_capacity(capacity: usize) -> Self {
77 Self(HashMap::with_capacity(capacity))
78 }
79
80 pub fn capacity(&self) -> usize {
93 self.0.capacity()
94 }
95
96 pub fn into_inner(self) -> HashMap<K, Cell<V>> {
98 self.0
99 }
100
101 pub fn entry(&mut self, k: K) -> Entry<'_, K, V> {
104 Entry::new(self.0.entry(k))
105 }
106
107 pub fn insert(&mut self, k: K, v: V) -> Option<V> {
129 self.0.insert(k, Cell::new(v)).map(Cell::into_inner)
130 }
131
132 pub fn is_empty(&self) -> bool {
145 self.0.is_empty()
146 }
147
148 pub fn remove<Q>(&mut self, k: &Q) -> Option<V>
165 where
166 Q: ?Sized + Hash + Eq,
167 K: Borrow<Q>,
168 {
169 self.0.remove(k).map(Cell::into_inner)
170 }
171
172 pub fn contains_key<Q>(&self, k: &Q) -> bool
177 where
178 Q: ?Sized + Hash + Eq,
179 K: Borrow<Q>,
180 {
181 self.0.contains_key(k)
182 }
183
184 pub fn borrow<Q>(&self, k: &Q) -> Ref<V>
198 where
199 Q: ?Sized + Hash + Eq + fmt::Debug,
200 K: Borrow<Q>,
201 {
202 self.0
203 .get(k)
204 .map(|cell| Ref::new(cell.borrow()))
205 .unwrap_or_else(|| borrow_panic!(k))
206 }
207
208 pub fn try_borrow<Q>(&self, k: &Q) -> Result<Ref<V>, BorrowFail>
211 where
212 Q: ?Sized + Hash + Eq,
213 K: Borrow<Q>,
214 {
215 self.0
216 .get(k)
217 .ok_or(BorrowFail::ValueNotFound)
218 .and_then(|cell| cell.try_borrow().map(Ref::new))
219 }
220
221 pub fn borrow_mut<Q>(&self, k: &Q) -> RefMut<V>
229 where
230 Q: ?Sized + Hash + Eq + fmt::Debug,
231 K: Borrow<Q>,
232 {
233 self.0
234 .get(k)
235 .map(|cell| RefMut::new(cell.borrow_mut()))
236 .unwrap_or_else(|| borrow_panic!(k))
237 }
238
239 pub fn try_borrow_mut<Q>(&self, k: &Q) -> Result<RefMut<V>, BorrowFail>
241 where
242 Q: ?Sized + Hash + Eq,
243 K: Borrow<Q>,
244 {
245 self.0
246 .get(k)
247 .ok_or(BorrowFail::ValueNotFound)
248 .and_then(|r_cell| r_cell.try_borrow_mut().map(RefMut::new))
249 }
250
251 pub fn get_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
254 where
255 Q: ?Sized + Hash + Eq,
256 K: Borrow<Q>,
257 {
258 self.get_resource_mut(k)
259 }
260
261 pub fn get_resource_mut<Q>(&mut self, k: &Q) -> Option<&mut V>
264 where
265 Q: ?Sized + Hash + Eq,
266 K: Borrow<Q>,
267 {
268 self.0.get_mut(k).map(Cell::get_mut)
269 }
270
271 pub fn get_raw<Q>(&self, k: &Q) -> Option<&Cell<V>>
273 where
274 Q: ?Sized + Hash + Eq,
275 K: Borrow<Q>,
276 {
277 self.0.get(k)
278 }
279}
280
281impl<K, V> Deref for RtMap<K, V> {
282 type Target = HashMap<K, Cell<V>>;
283
284 fn deref(&self) -> &Self::Target {
285 &self.0
286 }
287}
288
289impl<K, V> DerefMut for RtMap<K, V> {
290 fn deref_mut(&mut self) -> &mut Self::Target {
291 &mut self.0
292 }
293}
294
295#[cfg(test)]
296mod tests {
297 use rt_ref::BorrowFail;
298
299 use super::RtMap;
300
301 #[derive(Debug, Default, PartialEq)]
302 struct Res;
303
304 #[derive(Debug, Default, PartialEq)]
305 struct Value(u32);
306
307 #[test]
308 fn insert() {
309 let mut rt_map = RtMap::new();
310 rt_map.insert('a', Res);
311
312 assert!(rt_map.contains_key(&'a'));
313 assert!(!rt_map.contains_key(&'b'));
314 }
315
316 #[test]
317 fn with_capacity_reserves_enough_capacity() {
318 let map: RtMap<i32, i32> = RtMap::with_capacity(100);
319 assert!(map.capacity() >= 100);
320 }
321
322 #[test]
323 fn into_inner() {
324 let mut rt_map = RtMap::new();
325 rt_map.insert('a', Res);
326 let inner_map = rt_map.into_inner();
327
328 assert!(inner_map.contains_key(&'a'));
329 }
330
331 #[test]
332 fn deref_and_deref_mut() {
333 let mut rt_map = RtMap::new();
334 rt_map.insert('a', 0);
335 rt_map.insert('b', 1);
336
337 rt_map.iter_mut().for_each(|(_k, v)| *v.borrow_mut() += 1);
338
339 let a = rt_map.remove(&'a');
340 assert_eq!(Some(1), a);
341
342 let b = rt_map.iter().next();
343 assert_eq!(Some(2), b.map(|(_k, v)| *v.borrow()));
344 }
345
346 #[test]
347 fn is_empty_returns_true_when_map_does_not_contain_items() {
348 let rt_map = RtMap::<char, u32>::new();
349
350 assert!(rt_map.is_empty());
351 }
352
353 #[test]
354 fn is_empty_returns_false_when_map_contains_items() {
355 let mut rt_map = RtMap::new();
356
357 rt_map.insert('a', 0);
358
359 assert!(!rt_map.is_empty());
360 }
361
362 #[test]
363 fn entry_insert_value() {
364 let mut rt_map = RtMap::new();
365
366 let ref_mut = rt_map.entry('a').or_insert(1);
367
368 assert_eq!(1, *ref_mut);
369 drop(ref_mut);
370
371 let ref_mut = rt_map.entry('a').or_insert(2);
372
373 assert_eq!(1, *ref_mut);
374 drop(ref_mut);
375
376 rt_map.remove(&'a');
377
378 let ref_mut = rt_map.entry('a').or_insert_with(|| 3);
379
380 assert_eq!(3, *ref_mut);
381 drop(ref_mut);
382 }
383
384 #[test]
385 fn get_mut_returns_mutable_reference_to_value() {
386 let mut rt_map = RtMap::new();
387 rt_map.insert('a', Value(1));
388
389 let value = rt_map.get_mut(&'a');
390
391 assert!(value.is_some());
392
393 if let Some(value) = value {
394 *value = Value(2);
395 }
396
397 let value = rt_map.get_mut(&'a').map(|value| value.0);
398
399 assert_eq!(Some(2), value);
400 }
401
402 #[test]
403 #[should_panic(expected = "but it was already borrowed")]
404 fn read_write_fails() {
405 let mut rt_map = RtMap::new();
406 rt_map.insert('a', Res);
407
408 let _read = rt_map.borrow(&'a');
409 let _write = rt_map.borrow_mut(&'a');
410 }
411
412 #[test]
413 #[should_panic(expected = "but it was already borrowed mutably")]
414 fn write_read_fails() {
415 let mut rt_map = RtMap::new();
416 rt_map.insert('a', Res);
417
418 let _write = rt_map.borrow_mut(&'a');
419 let _read = rt_map.borrow(&'a');
420 }
421
422 #[test]
423 fn remove_insert() {
424 let mut rt_map = RtMap::new();
425 rt_map.insert('a', Res);
426
427 assert!(rt_map.contains_key(&'a'));
428
429 rt_map.remove(&'a').unwrap();
430
431 assert!(!rt_map.contains_key(&'a'));
432
433 rt_map.insert('a', Res);
434
435 assert!(rt_map.contains_key(&'a'));
436 }
437
438 #[test]
439 #[should_panic(expected = "Expected to borrow `'a'`, but it does not exist.")]
440 fn borrow_before_insert_panics() {
441 let rt_map = RtMap::<char, i32>::new();
442
443 rt_map.borrow(&'a');
444 }
445
446 #[test]
447 #[should_panic(expected = "Expected to borrow `'a'`, but it does not exist.")]
448 fn borrow_mut_before_insert_panics() {
449 let rt_map = RtMap::<char, i32>::new();
450
451 rt_map.borrow_mut(&'a');
452 }
453
454 #[test]
455 fn borrow_mut_try_borrow_returns_borrow_conflict_imm() {
456 let mut rt_map = RtMap::new();
457 rt_map.insert('a', Res);
458
459 let _res = rt_map.borrow_mut(&'a');
460
461 assert_eq!(Err(BorrowFail::BorrowConflictImm), rt_map.try_borrow(&'a'));
462 }
463
464 #[test]
465 fn borrow_try_borrow_mut_returns_borrow_conflict_mut() {
466 let mut rt_map = RtMap::new();
467 rt_map.insert('a', Res);
468
469 let _res = rt_map.borrow(&'a');
470
471 assert_eq!(
472 Err(BorrowFail::BorrowConflictMut),
473 rt_map.try_borrow_mut(&'a')
474 );
475 }
476
477 #[test]
478 fn borrow_mut_borrow_mut_returns_borrow_conflict_mut() {
479 let mut rt_map = RtMap::new();
480 rt_map.insert('a', Res);
481
482 let _res = rt_map.borrow_mut(&'a');
483
484 assert_eq!(
485 Err(BorrowFail::BorrowConflictMut),
486 rt_map.try_borrow_mut(&'a')
487 );
488 }
489
490 #[test]
491 fn try_borrow_before_insert_returns_value_not_found() {
492 let rt_map = RtMap::<char, Res>::new();
493
494 assert_eq!(Err(BorrowFail::ValueNotFound), rt_map.try_borrow(&'a'));
495 }
496
497 #[test]
498 fn try_borrow_mut_before_insert_returns_value_not_found() {
499 let rt_map = RtMap::<char, Res>::new();
500
501 assert_eq!(Err(BorrowFail::ValueNotFound), rt_map.try_borrow_mut(&'a'));
502 }
503
504 #[test]
505 #[should_panic(expected = "Expected to borrow `'a'`, but it does not exist.")]
506 fn borrow_before_insert_panics_value_not_found() {
507 let rt_map = RtMap::<char, Res>::new();
508
509 rt_map.borrow(&'a');
510 }
511
512 #[test]
513 #[should_panic(expected = "Expected to borrow `'a'`, but it does not exist.")]
514 fn borrow_mut_before_insert_panics_value_not_found() {
515 let rt_map = RtMap::<char, Res>::new();
516
517 rt_map.borrow_mut(&'a');
518 }
519}