borrowscope_runtime/
guard.rs1use crate::tracker::{track_drop, track_new};
22
23pub struct TrackGuard<T> {
41 name: &'static str,
42 value: T,
43}
44
45impl<T> TrackGuard<T> {
46 #[inline]
48 fn new(name: &'static str, value: T) -> Self {
49 Self { name, value }
50 }
51
52 #[inline]
54 pub fn name(&self) -> &'static str {
55 self.name
56 }
57
58 #[inline]
62 pub fn into_inner(self) -> T {
63 let value = unsafe { std::ptr::read(&self.value) };
64 std::mem::forget(self);
65 value
66 }
67}
68
69impl<T> std::ops::Deref for TrackGuard<T> {
70 type Target = T;
71
72 #[inline]
73 fn deref(&self) -> &Self::Target {
74 &self.value
75 }
76}
77
78impl<T> std::ops::DerefMut for TrackGuard<T> {
79 #[inline]
80 fn deref_mut(&mut self) -> &mut Self::Target {
81 &mut self.value
82 }
83}
84
85impl<T> Drop for TrackGuard<T> {
86 #[inline]
87 fn drop(&mut self) {
88 track_drop(self.name);
89 }
90}
91
92#[inline]
123pub fn track_new_guard<T>(name: &'static str, value: T) -> TrackGuard<T> {
124 let tracked = track_new(name, value);
125 TrackGuard::new(name, tracked)
126}
127
128pub struct BorrowGuard<'a, T: ?Sized> {
132 name: &'static str,
133 value: &'a T,
134}
135
136impl<'a, T: ?Sized> BorrowGuard<'a, T> {
137 #[inline]
138 fn new(name: &'static str, value: &'a T) -> Self {
139 Self { name, value }
140 }
141}
142
143impl<'a, T: ?Sized> std::ops::Deref for BorrowGuard<'a, T> {
144 type Target = T;
145
146 #[inline]
147 fn deref(&self) -> &Self::Target {
148 self.value
149 }
150}
151
152impl<'a, T: ?Sized> Drop for BorrowGuard<'a, T> {
153 #[inline]
154 fn drop(&mut self) {
155 track_drop(self.name);
156 }
157}
158
159#[inline]
173pub fn track_borrow_guard<'a, T: ?Sized>(name: &'static str, value: &'a T) -> BorrowGuard<'a, T> {
174 let tracked = crate::track_borrow(name, value);
175 BorrowGuard::new(name, tracked)
176}
177
178pub struct BorrowMutGuard<'a, T: ?Sized> {
180 name: &'static str,
181 value: &'a mut T,
182}
183
184impl<'a, T: ?Sized> BorrowMutGuard<'a, T> {
185 #[inline]
186 fn new(name: &'static str, value: &'a mut T) -> Self {
187 Self { name, value }
188 }
189}
190
191impl<'a, T: ?Sized> std::ops::Deref for BorrowMutGuard<'a, T> {
192 type Target = T;
193
194 #[inline]
195 fn deref(&self) -> &Self::Target {
196 self.value
197 }
198}
199
200impl<'a, T: ?Sized> std::ops::DerefMut for BorrowMutGuard<'a, T> {
201 #[inline]
202 fn deref_mut(&mut self) -> &mut Self::Target {
203 self.value
204 }
205}
206
207impl<'a, T: ?Sized> Drop for BorrowMutGuard<'a, T> {
208 #[inline]
209 fn drop(&mut self) {
210 track_drop(self.name);
211 }
212}
213
214#[inline]
228pub fn track_borrow_mut_guard<'a, T: ?Sized>(
229 name: &'static str,
230 value: &'a mut T,
231) -> BorrowMutGuard<'a, T> {
232 let tracked = crate::track_borrow_mut(name, value);
233 BorrowMutGuard::new(name, tracked)
234}
235
236#[cfg(test)]
237mod tests {
238 use super::*;
239 use crate::{get_events, reset};
240 use serial_test::serial;
241
242 #[test]
243 #[serial]
244 fn test_track_guard_auto_drop() {
245 reset();
246 {
247 let _x = track_new_guard("x", 42);
248 }
249 let events = get_events();
250 assert_eq!(events.len(), 2);
251 assert!(events[0].is_new());
252 assert!(events[1].is_drop());
253 }
254
255 #[test]
256 #[serial]
257 fn test_track_guard_deref() {
258 reset();
259 let x = track_new_guard("x", vec![1, 2, 3]);
260 assert_eq!(x.len(), 3);
261 assert_eq!(x[0], 1);
262 }
263
264 #[test]
265 #[serial]
266 fn test_track_guard_deref_mut() {
267 reset();
268 let mut x = track_new_guard("x", vec![1, 2, 3]);
269 x.push(4);
270 assert_eq!(x.len(), 4);
271 }
272
273 #[test]
274 #[serial]
275 fn test_into_inner_no_drop() {
276 reset();
277 let x = track_new_guard("x", 42);
278 let _val = x.into_inner();
279 let events = get_events();
280 assert_eq!(events.len(), 1); }
282
283 #[test]
284 #[serial]
285 fn test_borrow_guard() {
286 reset();
287 let data = track_new_guard("data", 42);
288 {
289 let _r = track_borrow_guard("r", &*data);
290 }
291 let events = get_events();
292 assert_eq!(events.len(), 3); }
294
295 #[test]
296 #[serial]
297 fn test_borrow_mut_guard() {
298 reset();
299 let mut data = track_new_guard("data", vec![1]);
300 {
301 let mut r = track_borrow_mut_guard("r", &mut *data);
302 r.push(2);
303 }
304 assert_eq!(data.len(), 2);
305 }
306}