1use std::{
2 io::{stdin, BufRead, BufReader, Error},
3 process::{Command, Stdio},
4 sync::{mpsc, mpsc::Sender},
5 thread,
6};
7
8use anyhow::Result;
9
10#[derive(Debug)]
11pub struct StdinHandler {
12 receiver: mpsc::Receiver<String>,
13 pub sender: mpsc::Sender<String>,
14}
15
16impl Default for StdinHandler {
17 fn default() -> Self {
18 Self::new()
19 }
20}
21
22impl StdinHandler {
23 pub fn new() -> Self {
24 let (sender, receiver) = mpsc::channel();
25 Self { receiver, sender }
26 }
27
28 pub fn init(&self, cmd: Option<Vec<String>>) -> Result<()> {
29 let sender = self.sender.clone();
30 match cmd {
31 Some(inner_cmd) => {
32 let child = Command::new(&inner_cmd[0])
33 .args(&inner_cmd[1..])
34 .stderr(Stdio::null())
35 .stdout(Stdio::piped())
36 .spawn()?;
37
38 let stdout = child
39 .stdout
40 .ok_or_else(|| Error::other("Failed to run command"))?;
41 let reader = BufReader::new(stdout);
42 read_lines_and_send(reader, sender);
43 }
44 None => {
46 let stdin = stdin();
47 let reader = BufReader::new(stdin);
48
49 read_lines_and_send(reader, sender);
50 }
51 }
52
53 Ok(())
54 }
55
56 pub fn recv(&self) -> Result<String, mpsc::RecvError> {
57 self.receiver.recv()
58 }
59
60 pub fn try_recv(&self) -> Result<String, mpsc::TryRecvError> {
61 self.receiver.try_recv()
62 }
63}
64
65fn read_lines_and_send<R>(mut reader: R, sender: Sender<String>)
66where
67 R: BufRead + Send + 'static,
68{
69 let mut line = String::new();
70 thread::spawn(move || loop {
71 match reader.read_line(&mut line) {
72 Ok(len) => {
73 if len == 0 {
74 break;
75 } else {
76 sender.send(line.clone()).ok();
77 }
78 }
79 Err(e) => {
80 sender.send(e.to_string()).ok();
81 break;
82 }
83 }
84 line.clear();
85 });
86}