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<O> WithBorrow<'_, 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<O> WithBorrow<'_, 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 use std::sync::LazyLock;
88
89 static STATIC_MUTEX: LazyLock<Mutex<u8>> = LazyLock::new(Mutex::default);
90
91 assert_eq!(
92 STATIC_MUTEX.with_borrow_mut(|o| {
93 *o += 2;
94 *o
95 }),
96 2
97 );
98 assert_eq!(STATIC_MUTEX.with_borrow(|o| o + 2), 4);
99}
100
101#[test]
102fn test_with_borrow_static_rwlock() {
103 use std::sync::LazyLock;
104
105 static STATIC_RWLOCK: LazyLock<RwLock<u8>> = LazyLock::new(RwLock::default);
106
107 assert_eq!(
108 STATIC_RWLOCK.with_borrow_mut(|o| {
109 *o += 2;
110 *o
111 }),
112 2
113 );
114 assert_eq!(STATIC_RWLOCK.with_borrow(|o| o + 2), 4);
115}
116
117#[test]
118fn test_with_borrow_non_static_mutex() {
119 let mutex: Mutex<u8> = Mutex::default();
120 assert_eq!(
121 mutex.with_borrow_mut(|o| {
122 *o += 2;
123 *o
124 }),
125 2
126 );
127 assert_eq!(mutex.with_borrow(|o| o + 2), 4);
128}