1use std::{
2 cell::{Ref as StdRef, RefCell, RefMut as StdRefMut},
3 ops::{Deref, DerefMut},
4 rc::Rc,
5};
6
7#[derive(Debug)]
9struct Dropper {
10 borrower: String,
11 borrowers: Rc<RefCell<Vec<String>>>,
12}
13
14impl Drop for Dropper {
15 fn drop(&mut self) {
16 let index = self
17 .borrowers
18 .borrow()
19 .iter()
20 .position(|b| *b == self.borrower)
21 .expect(&format!(
22 "Cannot find a borrower with name: {}",
23 self.borrower
24 ));
25 self.borrowers.borrow_mut().remove(index);
26 }
27}
28
29#[derive(Debug)]
31pub struct Ref<'a, T> {
32 value: StdRef<'a, T>,
33 _dropper: Dropper,
34}
35
36impl<'a, T> Ref<'a, T> {
37 pub fn new(value: StdRef<'a, T>, borrower: &str, borrowers: Rc<RefCell<Vec<String>>>) -> Self {
38 Self {
39 value,
40 _dropper: Dropper {
41 borrower: borrower.to_string(),
42 borrowers,
43 },
44 }
45 }
46}
47
48impl<'a, T> Deref for Ref<'a, T> {
49 type Target = T;
50
51 fn deref(&self) -> &T {
52 &self.value
53 }
54}
55
56#[derive(Debug)]
58pub struct RefMut<'a, T> {
59 value: StdRefMut<'a, T>,
60 _dropper: Dropper,
61}
62
63impl<'a, T> RefMut<'a, T> {
64 pub fn new(
65 value: StdRefMut<'a, T>,
66 borrower: &str,
67 borrowers: Rc<RefCell<Vec<String>>>,
68 ) -> Self {
69 Self {
70 value,
71 _dropper: Dropper {
72 borrower: borrower.to_string(),
73 borrowers,
74 },
75 }
76 }
77}
78
79impl<'a, T> Deref for RefMut<'a, T> {
80 type Target = T;
81
82 fn deref(&self) -> &T {
83 &self.value
84 }
85}
86
87impl<'a, T> DerefMut for RefMut<'a, T> {
88 fn deref_mut(&mut self) -> &mut T {
89 &mut self.value
90 }
91}
92
93#[derive(Debug)]
96pub struct Lender<T> {
97 value: Rc<RefCell<T>>,
98 borrowers: Rc<RefCell<Vec<String>>>,
99}
100
101impl<T> Lender<T> {
102 pub fn new(value: T) -> Self {
104 Self {
105 value: Rc::new(RefCell::new(value)),
106 borrowers: Rc::new(RefCell::new(vec![])),
107 }
108 }
109
110 pub fn borrow(&self, borrower: &str) -> Result<Ref<T>, String> {
113 if let Ok(value) = self.value.try_borrow() {
114 self.borrowers.borrow_mut().push(borrower.to_string());
115 Ok(Ref::new(value, borrower, self.borrowers.clone()))
116 } else {
117 Err(format!(
118 "Failed to borrow immutable reference. Currently borrowed by: {:?}",
119 self.borrowers.borrow()
120 ))
121 }
122 }
123
124 pub fn borrow_mut(&self, borrower: &str) -> Result<RefMut<T>, String> {
128 if let Ok(value) = self.value.try_borrow_mut() {
129 self.borrowers.borrow_mut().push(borrower.to_string());
130 Ok(RefMut::new(value, borrower, self.borrowers.clone()))
131 } else {
132 Err(format!(
133 "Failed to borrow mutable reference. Currently borrowed by: {:?}",
134 self.borrowers.borrow()
135 ))
136 }
137 }
138}
139
140impl<T> Clone for Lender<T> {
142 fn clone(&self) -> Self {
143 Self {
144 value: self.value.clone(),
145 borrowers: self.borrowers.clone(),
146 }
147 }
148}
149
150#[cfg(test)]
151mod tests {
152 use super::Lender;
153
154 #[test]
155 fn borrow_twice() -> Result<(), String> {
156 let d = Lender::new(1);
157
158 let b1 = d.borrow("b1")?;
159 let b2 = d.borrow("b2")?;
160
161 assert_eq!(*b1, 1);
162 assert_eq!(*b2, 1);
163
164 Ok(())
165 }
166
167 #[test]
168 fn borrow_once_borrow_mut_once() -> Result<(), String> {
169 let d = Lender::new(1);
170
171 let _b1 = d.borrow("b1")?;
172 let b2 = d.borrow_mut("b2");
173
174 assert!(b2.is_err());
175 if let Err(b) = b2 {
176 b.contains("Currently borrowed by: [\"b1\"]");
177 }
178
179 Ok(())
180 }
181
182 #[test]
183 fn borrow_twice_borrow_mut_once() -> Result<(), String> {
184 let d = Lender::new(1);
185
186 let _b1 = d.borrow("b1")?;
187 let _b2 = d.borrow("b2")?;
188 let b3 = d.borrow_mut("b3");
189
190 assert!(b3.is_err());
191 if let Err(b) = b3 {
192 b.contains("Currently borrowed by: [\"b1\", \"b2\"]");
193 }
194
195 Ok(())
196 }
197
198 #[test]
199 fn borrow_mut_once_borrow_once() -> Result<(), String> {
200 let d = Lender::new(1);
201
202 let _b1 = d.borrow_mut("b1")?;
203 let b2 = d.borrow("b2");
204
205 assert!(b2.is_err());
206 if let Err(b) = b2 {
207 b.contains("Currently borrowed by: [\"b1\"]");
208 }
209
210 Ok(())
211 }
212
213 #[test]
214 fn borrow_mut_twice() -> Result<(), String> {
215 let d = Lender::new(1);
216
217 let _b1 = d.borrow_mut("b1")?;
218 let b2 = d.borrow_mut("b2");
219
220 assert!(b2.is_err());
221 if let Err(b) = b2 {
222 b.contains("Currently borrowed by: [\"b1\"]");
223 }
224
225 Ok(())
226 }
227
228 #[test]
229 fn clone_and_borrow_mut() -> Result<(), String> {
230 let d = Lender::new(1);
231 let _b1 = d.borrow_mut("b1")?;
232
233 let _d2 = d.clone();
234 let b2 = d.borrow_mut("b2");
235
236 assert!(b2.is_err());
237 if let Err(b) = b2 {
238 b.contains("Currently borrowed by: [\"b1\"]");
239 }
240
241 Ok(())
242 }
243}