use crate::procserv::config::KeyBindings;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Action {
None,
KillChild,
RestartChild,
ToggleRestartMode,
LogoutClient,
QuitServer,
}
impl Action {
pub fn evaluate(byte: u8, keys: &KeyBindings, child_alive: bool) -> Self {
if !child_alive {
if let Some(c) = keys.restart
&& byte == c
{
return Self::RestartChild;
}
if let Some(c) = keys.kill
&& byte == c
{
return Self::RestartChild;
}
if let Some(c) = keys.quit
&& byte == c
{
return Self::QuitServer;
}
}
if let Some(c) = keys.logout
&& byte == c
{
return Self::LogoutClient;
}
if let Some(c) = keys.toggle_restart
&& byte == c
{
return Self::ToggleRestartMode;
}
if let Some(c) = keys.kill
&& byte == c
{
return Self::KillChild;
}
Self::None
}
}
pub fn scan(buf: &[u8], keys: &KeyBindings, child_alive: bool) -> Vec<Action> {
buf.iter()
.map(|&b| Action::evaluate(b, keys, child_alive))
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
fn keys() -> KeyBindings {
KeyBindings {
kill: Some(0x18), toggle_restart: Some(0x14), restart: Some(0x12), quit: Some(0x11), logout: Some(0x1d), }
}
#[test]
fn restart_only_when_child_dead() {
let k = keys();
assert_eq!(Action::evaluate(0x12, &k, true), Action::None);
assert_eq!(Action::evaluate(0x12, &k, false), Action::RestartChild);
}
#[test]
fn kill_signals_a_live_child_but_restarts_a_dead_one() {
let k = keys();
assert_eq!(Action::evaluate(0x18, &k, true), Action::KillChild);
assert_eq!(Action::evaluate(0x18, &k, false), Action::RestartChild);
}
#[test]
fn kill_restarts_dead_child_even_when_restart_key_disabled() {
let mut k = keys();
k.restart = None;
assert_eq!(Action::evaluate(0x18, &k, false), Action::RestartChild);
}
#[test]
fn unbound_key_returns_none() {
let mut k = keys();
k.kill = None;
assert_eq!(Action::evaluate(0x18, &k, true), Action::None);
}
#[test]
fn scan_buffer() {
let k = keys();
let actions = scan(&[b'a', 0x18, b'b'], &k, true);
assert_eq!(actions, vec![Action::None, Action::KillChild, Action::None]);
}
}