pub struct DropTrigger<F: FnOnce()> {
trigger: Option<F>,
}
impl<F: FnOnce()> DropTrigger<F> {
pub fn new(trigger: F) -> Self {
Self {
trigger: Some(trigger),
}
}
pub fn disarm(&mut self) -> bool {
self.trigger.take().is_some()
}
}
impl<F: FnOnce()> Drop for DropTrigger<F> {
fn drop(&mut self) {
if let Some(trigger) = self.trigger.take() {
trigger()
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn trigger_called_on_drop() {
let mut x = 0;
let dt = DropTrigger::new(|| x += 1);
drop(dt);
assert_eq!(1, x);
}
#[test]
fn trigger_not_called_when_disarmed() {
let mut x = 0;
let mut dt = DropTrigger::new(|| x += 1);
let was_armed = dt.disarm();
drop(dt);
assert!(was_armed);
assert_eq!(0, x);
}
#[test]
fn disarm_returns_false_if_was_not_armed() {
let mut x = 0;
let mut dt = DropTrigger::new(|| x += 1);
let first = dt.disarm();
let second = dt.disarm();
drop(dt);
assert!(first);
assert!(!second);
}
}