use tokio::io::{AsyncBufReadExt, BufReader, AsyncWriteExt}; pub struct CliChannel { read: BufReader, write: tokio::io::Stdout, } impl CliChannel { pub fn new() -> Self { Self { read: BufReader::new(tokio::io::stdin()), write: tokio::io::stdout(), } } pub async fn read_line(&mut self, prompt: &str) -> Result, std::io::Error> { print!("{}", prompt); self.write.flush().await?; let mut line = String::new(); let bytes_read = self.read.read_line(&mut line).await?; if bytes_read == 0 { return Ok(None); } Ok(Some(line.trim_end().to_string())) } pub async fn write_line(&mut self, content: &str) -> Result<(), std::io::Error> { self.write.write_all(content.as_bytes()).await?; self.write.write_all(b"\n").await?; self.write.flush().await } pub async fn write_response(&mut self, content: &str) -> Result<(), std::io::Error> { for line in content.lines() { self.write.write_all(b" ").await?; self.write.write_all(line.as_bytes()).await?; self.write.write_all(b"\n").await?; } self.write.flush().await } } impl Default for CliChannel { fn default() -> Self { Self::new() } }