defer/
lib.rs

1#![no_std]
2
3use core::mem::ManuallyDrop;
4
5/// Defer execution of a closure until the return value is dropped.
6pub fn defer<F>(f: F) -> impl Drop
7where
8    F: FnOnce(),
9{
10    struct Defer<F: FnOnce()>(ManuallyDrop<F>);
11
12    impl<F: FnOnce()> Drop for Defer<F> {
13        fn drop(&mut self) {
14            let f: F = unsafe { ManuallyDrop::take(&mut self.0) };
15            f();
16        }
17    }
18
19    Defer(ManuallyDrop::new(f))
20}
21
22/// Defer execution of a closure until the current scope end.
23#[macro_export]
24macro_rules! defer {
25    ($e:expr) => {
26        let _defer = $crate::defer(|| $e);
27    };
28}
29
30#[test]
31fn test() {
32    use core::cell::RefCell;
33
34    let i = RefCell::new(0);
35
36    {
37        let _d = defer(|| *i.borrow_mut() += 1);
38        assert_eq!(*i.borrow(), 0);
39    }
40
41    assert_eq!(*i.borrow(), 1);
42}
43
44#[test]
45fn test_macro() {
46    use core::cell::RefCell;
47
48    let i = RefCell::new(0);
49    let k = RefCell::new(0);
50
51    {
52        defer!(*i.borrow_mut() += 1);
53        defer!(*k.borrow_mut() += 1);
54        assert_eq!(*i.borrow(), 0);
55        assert_eq!(*k.borrow(), 0);
56    }
57
58    assert_eq!(*i.borrow(), 1);
59    assert_eq!(*k.borrow(), 1);
60}