1// Extracted from the scopeguard crate
2use core::{
3 mem::ManuallyDrop,
4 ops::{Deref, DerefMut},
5 ptr,
6};
7
8pub struct ScopeGuard<T, F>
9where
10 F: FnMut(&mut T),
11{
12 dropfn: F,
13 value: T,
14}
15
16#[inline]
17pub fn guard<T, F>(value: T, dropfn: F) -> ScopeGuard<T, F>
18where
19 F: FnMut(&mut T),
20{
21 ScopeGuard { dropfn, value }
22}
23
24impl<T, F> ScopeGuard<T, F>
25where
26 F: FnMut(&mut T),
27{
28 #[inline]
29 pub fn into_inner(guard: Self) -> T {
30 // Cannot move out of Drop-implementing types, so
31 // ptr::read the value out of a ManuallyDrop<Self>
32 // Don't use mem::forget as that might invalidate value
33 let guard: ManuallyDrop> = ManuallyDrop::new(guard);
34 unsafe {
35 let value: T = ptr::read(&guard.value);
36 // read the closure so that it is dropped
37 let _ = ptr::read(&guard.dropfn);
38 value
39 }
40 }
41}
42
43impl<T, F> Deref for ScopeGuard<T, F>
44where
45 F: FnMut(&mut T),
46{
47 type Target = T;
48 #[inline]
49 fn deref(&self) -> &T {
50 &self.value
51 }
52}
53
54impl<T, F> DerefMut for ScopeGuard<T, F>
55where
56 F: FnMut(&mut T),
57{
58 #[inline]
59 fn deref_mut(&mut self) -> &mut T {
60 &mut self.value
61 }
62}
63
64impl<T, F> Drop for ScopeGuard<T, F>
65where
66 F: FnMut(&mut T),
67{
68 #[inline]
69 fn drop(&mut self) {
70 (self.dropfn)(&mut self.value);
71 }
72}
73