use crate::Result;
use std::{
process::{Child, Command},
time::Duration,
};
pub trait Timer {
fn time_left(&mut self, idle_time: Duration) -> Result<Option<Duration>>;
fn abort_urgency(&self) -> Option<Duration> {
None
}
fn activate(&mut self) -> Result<()> {
Ok(())
}
fn abort(&mut self) -> Result<()> {
Ok(())
}
fn deactivate(&mut self) -> Result<()> {
Ok(())
}
fn disabled(&mut self) -> bool {
false
}
}
#[derive(Debug, Default)]
pub struct CmdTimer {
pub time: Duration,
pub activation: Option<Command>,
pub abortion: Option<Command>,
pub deactivation: Option<Command>,
pub disabled: bool,
pub activation_child: Option<Child>,
}
impl Timer for CmdTimer {
fn time_left(&mut self, idle_time: Duration) -> Result<Option<Duration>> {
Ok(self
.time
.checked_sub(idle_time)
.filter(|&dur| dur != Duration::default()))
}
fn abort_urgency(&self) -> Option<Duration> {
self.abortion.as_ref().map(|_| Duration::from_secs(1))
}
fn activate(&mut self) -> Result<()> {
if let Some(ref mut activation) = self.activation {
self.activation_child = Some(activation.spawn()?);
}
Ok(())
}
fn abort(&mut self) -> Result<()> {
if let Some(ref mut abortion) = self.abortion {
abortion.spawn()?;
}
Ok(())
}
fn deactivate(&mut self) -> Result<()> {
if let Some(ref mut deactivation) = self.deactivation {
deactivation.spawn()?;
}
Ok(())
}
fn disabled(&mut self) -> bool {
if let Some(Ok(None)) = self.activation_child.as_mut().map(|child| child.try_wait()) {
true
} else {
self.disabled
}
}
}
#[derive(Debug)]
pub struct CallbackTimer<F>
where
F: FnMut(),
{
time: Duration,
f: F,
pub disabled: bool,
}
impl<'a> CallbackTimer<Box<dyn FnMut() + 'a>> {
pub fn new<F>(time: Duration, f: F) -> Self
where
F: FnMut() + 'a,
{
Self::new_unboxed(time, Box::new(f))
}
}
impl<F> CallbackTimer<F>
where
F: FnMut(),
{
pub fn new_unboxed(time: Duration, f: F) -> Self {
Self {
time,
f,
disabled: false,
}
}
}
impl<F> Timer for CallbackTimer<F>
where
F: FnMut(),
{
fn time_left(&mut self, idle_time: Duration) -> Result<Option<Duration>> {
Ok(self
.time
.checked_sub(idle_time)
.filter(|&d| d != Duration::default()))
}
fn activate(&mut self) -> Result<()> {
(self.f)();
Ok(())
}
fn disabled(&mut self) -> bool {
self.disabled
}
}