classicube_helpers\traits/
with_borrow.rs1use std::{
2 cell::RefCell,
3 sync::{Mutex, RwLock},
4 thread::LocalKey,
5};
6
7pub trait WithBorrow<'a, O> {
8 fn with_borrow<F, R>(&'a self, f: F) -> R
9 where
10 F: FnOnce(&O) -> R;
11
12 fn with_borrow_mut<F, R>(&'a self, f: F) -> R
13 where
14 F: FnOnce(&mut O) -> R;
15}
16
17impl<O> WithBorrow<'static, O> for LocalKey<RefCell<O>> {
18 fn with_borrow<F, T>(&'static self, f: F) -> T
19 where
20 F: FnOnce(&O) -> T,
21 {
22 self.with(|cell| f(&cell.borrow()))
23 }
24
25 fn with_borrow_mut<F, T>(&'static self, f: F) -> T
26 where
27 F: FnOnce(&mut O) -> T,
28 {
29 self.with(|cell| f(&mut cell.borrow_mut()))
30 }
31}
32
33impl<'a, O> WithBorrow<'a, O> for Mutex<O> {
34 fn with_borrow<F, R>(&self, f: F) -> R
35 where
36 F: FnOnce(&O) -> R,
37 {
38 let guard = self.lock().unwrap();
39 f(&*guard)
40 }
41
42 fn with_borrow_mut<F, R>(&self, f: F) -> R
43 where
44 F: FnOnce(&mut O) -> R,
45 {
46 let mut guard = self.lock().unwrap();
47 f(&mut *guard)
48 }
49}
50
51impl<'a, O> WithBorrow<'a, O> for RwLock<O> {
52 fn with_borrow<F, R>(&self, f: F) -> R
53 where
54 F: FnOnce(&O) -> R,
55 {
56 let guard = self.read().unwrap();
57 f(&*guard)
58 }
59
60 fn with_borrow_mut<F, R>(&self, f: F) -> R
61 where
62 F: FnOnce(&mut O) -> R,
63 {
64 let mut guard = self.write().unwrap();
65 f(&mut *guard)
66 }
67}
68
69#[test]
70fn test_with_borrow_thread_local() {
71 use std::cell::RefCell;
72 thread_local!(
73 static THREAD_LOCAL: RefCell<u8> = RefCell::default();
74 );
75 assert_eq!(
76 THREAD_LOCAL.with_borrow_mut(|o| {
77 *o += 2;
78 *o
79 }),
80 2
81 );
82 assert_eq!(THREAD_LOCAL.with_borrow(|o| o + 2), 4);
83}
84
85#[test]
86fn test_with_borrow_static_mutex() {
87 lazy_static::lazy_static! {
88 static ref STATIC_MUTEX: Mutex<u8> = Mutex::default();
89 };
90 assert_eq!(
91 STATIC_MUTEX.with_borrow_mut(|o| {
92 *o += 2;
93 *o
94 }),
95 2
96 );
97 assert_eq!(STATIC_MUTEX.with_borrow(|o| o + 2), 4);
98}
99
100#[test]
101fn test_with_borrow_static_rwlock() {
102 lazy_static::lazy_static! {
103 static ref STATIC_RWLOCK: RwLock<u8> = RwLock::default();
104 };
105 assert_eq!(
106 STATIC_RWLOCK.with_borrow_mut(|o| {
107 *o += 2;
108 *o
109 }),
110 2
111 );
112 assert_eq!(STATIC_RWLOCK.with_borrow(|o| o + 2), 4);
113}
114
115#[test]
116fn test_with_borrow_non_static_mutex() {
117 let mutex: Mutex<u8> = Mutex::default();
118 assert_eq!(
119 mutex.with_borrow_mut(|o| {
120 *o += 2;
121 *o
122 }),
123 2
124 );
125 assert_eq!(mutex.with_borrow(|o| o + 2), 4);
126}