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
241 #[test]
242 fn test_track_guard_auto_drop() {
243 reset();
244 {
245 let _x = track_new_guard("x", 42);
246 }
247 let events = get_events();
248 assert_eq!(events.len(), 2);
249 assert!(events[0].is_new());
250 assert!(events[1].is_drop());
251 }
252
253 #[test]
254 fn test_track_guard_deref() {
255 reset();
256 let x = track_new_guard("x", vec![1, 2, 3]);
257 assert_eq!(x.len(), 3);
258 assert_eq!(x[0], 1);
259 }
260
261 #[test]
262 fn test_track_guard_deref_mut() {
263 reset();
264 let mut x = track_new_guard("x", vec![1, 2, 3]);
265 x.push(4);
266 assert_eq!(x.len(), 4);
267 }
268
269 #[test]
270 fn test_into_inner_no_drop() {
271 reset();
272 let x = track_new_guard("x", 42);
273 let _val = x.into_inner();
274 let events = get_events();
275 assert_eq!(events.len(), 1); }
277
278 #[test]
279 fn test_borrow_guard() {
280 reset();
281 let data = track_new_guard("data", 42);
282 {
283 let _r = track_borrow_guard("r", &*data);
284 }
285 let events = get_events();
286 assert_eq!(events.len(), 3); }
288
289 #[test]
290 fn test_borrow_mut_guard() {
291 reset();
292 let mut data = track_new_guard("data", vec![1]);
293 {
294 let mut r = track_borrow_mut_guard("r", &mut *data);
295 r.push(2);
296 }
297 assert_eq!(data.len(), 2);
298 }
299}