use crate::RuChatError;
use std::io::stdin;
use tokio::io::{AsyncWrite, AsyncWriteExt};
pub(crate) struct Io {
stdin: std::io::Stdin,
stdout: tokio::io::Stdout,
stderr: tokio::io::Stderr,
}
impl Io {
pub(crate) fn new() -> Self {
Self {
stdin: stdin(),
stdout: tokio::io::stdout(),
stderr: tokio::io::stderr(),
}
}
pub(crate) async fn read_line(&mut self) -> Result<String, RuChatError> {
let mut input = String::new();
self.stdin.read_line(&mut input)?;
Ok(input.trim_end().to_string())
}
pub(crate) async fn write_line(&mut self, line: &str) -> Result<(), RuChatError> {
write_flushed(&mut self.stdout, line.as_bytes()).await
}
pub(crate) async fn write_error_line(&mut self, line: &str) -> Result<(), RuChatError> {
write_flushed(&mut self.stderr, line.as_bytes()).await
}
pub(crate) async fn write(&mut self, s: &str) -> Result<(), RuChatError> {
write_flushed(&mut self.stdout, s.as_bytes()).await
}
pub(crate) async fn clear_status_line(&mut self) -> Result<(), RuChatError> {
write_flushed(&mut self.stdout, b"\r\x1b[2K").await
}
}
async fn write_flushed<W: AsyncWrite + Unpin>(w: &mut W, bytes: &[u8]) -> Result<(), RuChatError> {
w.write_all(bytes).await?;
w.flush().await?;
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_write_line() {
let mut io = Io::new();
let line = "Hello, world!";
let result = io.write_line(line).await;
assert!(result.is_ok());
}
#[tokio::test]
async fn test_write() {
let mut io = Io::new();
let text = "Hello, world!";
let result = io.write(text).await;
assert!(result.is_ok());
}
}