pub fn defer<T: FnMut()>(f: T) -> impl Drop {
Defer(f)
}
pub struct Defer<T: FnMut()>(T);
impl<T: FnMut()> Drop for Defer<T> {
fn drop(&mut self) {
(self.0)();
}
}
#[cfg(test)]
mod tests {
use crate::prelude::*;
use std::{
cell::Cell,
panic::{self, catch_unwind, AssertUnwindSafe},
};
fn supress_panic_err() {
panic::set_hook(Box::new(|_| {}));
}
#[test]
fn test_defer_fires_even_with_panic() {
supress_panic_err();
let obj = Cell::new(1);
let _ = catch_unwind(AssertUnwindSafe(|| {
defer!(obj.set(2));
panic!();
}));
assert_eq!(obj.get(), 2);
}
#[test]
fn test_defer_actually_waits_until_end() {
let obj = Cell::new(1);
let _defer = defer(|| obj.set(2));
assert_eq!(1, obj.get());
}
}