classicube_helpers\traits/
with_borrow.rs

1use 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}