use std::time::Instant;
#[derive(Debug, Clone)]
pub enum ExitState {
Normal,
AwaitingConfirmation {
since: Instant,
timeout_secs: u64,
},
}
impl Default for ExitState {
fn default() -> Self {
Self::Normal
}
}
impl ExitState {
pub fn awaiting_confirmation(timeout_secs: u64) -> Self {
Self::AwaitingConfirmation {
since: Instant::now(),
timeout_secs,
}
}
pub fn is_expired(&self) -> bool {
match self {
Self::Normal => false,
Self::AwaitingConfirmation { since, timeout_secs } => {
since.elapsed().as_secs() >= *timeout_secs
}
}
}
pub fn is_awaiting(&self) -> bool {
match self {
Self::Normal => false,
Self::AwaitingConfirmation { since, timeout_secs } => {
since.elapsed().as_secs() < *timeout_secs
}
}
}
pub fn reset(&mut self) {
*self = Self::Normal;
}
}
pub trait ExitHandler: Send + 'static {
fn on_exit(&mut self) -> bool {
true
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_exit_state_default() {
let state = ExitState::default();
assert!(!state.is_awaiting());
assert!(!state.is_expired());
}
#[test]
fn test_exit_state_awaiting() {
let state = ExitState::awaiting_confirmation(2);
assert!(state.is_awaiting());
assert!(!state.is_expired());
}
#[test]
fn test_exit_state_expired() {
let state = ExitState::AwaitingConfirmation {
since: Instant::now() - Duration::from_secs(3),
timeout_secs: 2,
};
assert!(!state.is_awaiting());
assert!(state.is_expired());
}
#[test]
fn test_exit_state_reset() {
let mut state = ExitState::awaiting_confirmation(2);
assert!(state.is_awaiting());
state.reset();
assert!(!state.is_awaiting());
}
}