hashbrown/
scopeguard.rs

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::new(guard);
34        unsafe {
35            let value = 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}