ctrlc_handler/
lib.rs

1use crossbeam_channel::{unbounded, Sender, Receiver, TryRecvError};
2
3#[derive(Debug, Clone, Copy)]
4pub enum CtrlCResponse {
5    Quit,
6    Continue,
7    Error,
8}
9
10#[derive(Debug, Clone)]
11pub struct CtrlCHandler {
12    rx: Receiver<CtrlCResponse>,
13    tx: Sender<CtrlCResponse>,
14}
15
16impl CtrlCHandler {
17    pub fn new() -> Self {
18        let (tx, rx) = unbounded::<CtrlCResponse>();
19        let tx_clone = tx.clone();
20        ctrlc::set_handler(move || tx_clone.send(CtrlCResponse::Quit).expect("Could not send signal on channel."))
21        .expect("Error setting Ctrl-C handler");
22        Self {
23            rx: rx,
24            tx: tx.clone(),
25        }
26    }
27    /// Tries to receive a response from the receiver channel.  Returns the result.
28    pub fn respond(&self) -> CtrlCResponse {
29        match self.rx.try_recv() {
30            Ok(rx) => rx,
31            Err(TryRecvError::Empty) => CtrlCResponse::Continue,
32            Err(TryRecvError::Disconnected) => CtrlCResponse::Error, 
33        }
34    }
35    /// Makes it so should_continue returns false.
36    pub fn send_quit(&self) {
37        self.tx.clone().send(CtrlCResponse::Quit).unwrap();
38    }
39    /// Checks if CTRL-C has beed pushed. Returns true if it hasn't.
40    pub fn should_continue(&self) -> bool {
41        if let CtrlCResponse::Continue = self.respond() {
42            true
43        } else {
44            false
45        }
46    }
47    /// Gets the channel sender so it can be used outside of the module.
48    pub fn get_tx(&self) -> Sender<CtrlCResponse> {
49        self.tx.clone()
50    }
51}