use std::{fmt, io}; use tokio::io::{Lines, AsyncBufRead, AsyncBufReadExt, AsyncWrite, AsyncWriteExt}; use log::debug; use super::message::{Message, parse, ParseError}; #[derive(Debug)] pub enum ReadMessageError { String(&'static str), ParseError(ParseError), Io(std::io::Error), } impl fmt::Display for ReadMessageError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { ReadMessageError::String(e) => write!(f, "{e}"), ReadMessageError::ParseError(e) => write!(f, "{e}"), ReadMessageError::Io(e) => write!(f, "{e}"), } } } impl std::error::Error for ReadMessageError {} pub struct MessageReader { reader: Lines, buf: String, } impl MessageReader { pub fn new(reader: R) -> Self { Self { reader: reader.lines(), buf: String::with_capacity(0), } } pub async fn read_message(&mut self) -> Result { match self.reader.next_line().await { Ok(Some(line)) => { self.buf = line; parse(&self.buf).map_err(ReadMessageError::ParseError) } Ok(None) => Err(ReadMessageError::String("Lost connection to peer server")), Err(e) => Err(ReadMessageError::Io(e)), } } } pub struct MessageWriter { writer: W, } impl MessageWriter { pub fn new(writer: W) -> Self { Self { writer } } pub async fn write_msg<'a>(&mut self, msg: Message<'a>) -> Result<(), io::Error> { let msg = format!("{}\r\n", msg); debug!("sending message: {:?}", msg); self.writer.write_all(msg.as_bytes()).await } pub async fn flush(&mut self) -> Result<(), io::Error> { self.writer.flush().await } }