#[cfg(not(feature = "tokio"))]
mod imports {
pub(super) use std::io::{self, BufRead, BufReader, Stdin, Stdout, Write};
pub(super) use std::net::{Shutdown, TcpStream};
pub(super) use std::process::{Child, ChildStdin, ChildStdout};
}
#[cfg(feature = "tokio")]
mod imports {
pub(super) use tokio::io::{
self, AsyncBufRead as BufRead, AsyncWrite as Write, AsyncWriteExt, BufReader, Stdin, Stdout,
};
pub(super) use tokio::net::tcp::{ReadHalf, WriteHalf};
pub(super) use tokio::net::TcpStream;
pub(super) use tokio::process::{Child, ChildStdin, ChildStdout};
}
use imports::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub struct Connection<R: BufRead, W: Write> {
reader: R,
writer: W,
}
impl<R: BufRead, W: Write> Connection<R, W> {
pub fn new(reader: R, writer: W) -> Self {
Self { reader, writer }
}
}
impl<'a> Connection<BufReader<&'a mut ChildStdout>, &'a mut ChildStdin> {
pub fn new_from_child(child: &'a mut Child) -> Option<Self> {
let stdin = child.stdin.as_mut()?;
let stdout = child.stdout.as_mut()?;
Some(Self {
reader: BufReader::new(stdout),
writer: stdin,
})
}
}
impl Connection<BufReader<Stdin>, Stdout> {
pub fn new_from_stdio() -> Self {
Self {
reader: BufReader::new(io::stdin()),
writer: io::stdout(),
}
}
}
#[cfg(not(feature = "tokio"))]
impl Connection<BufReader<TcpStream>, TcpStream> {
pub fn new_from_tcp_stream(tcp_stream: TcpStream) -> io::Result<Self> {
Ok(Self {
reader: BufReader::new(tcp_stream.try_clone()?),
writer: tcp_stream,
})
}
pub fn shutdown(self) -> io::Result<()> {
self.writer.shutdown(Shutdown::Both)
}
}
#[cfg(feature = "tokio")]
impl<'a> Connection<BufReader<ReadHalf<'a>>, WriteHalf<'a>> {
pub fn new_from_tcp_stream(tcp_stream: &'a mut TcpStream) -> io::Result<Self> {
let (read_half, write_half) = tcp_stream.split();
Ok(Self {
reader: BufReader::new(read_half),
writer: write_half,
})
}
pub async fn shutdown(mut self) -> io::Result<()> {
self.writer.shutdown().await
}
}
#[cfg(not(feature = "tokio"))]
impl<R: BufRead, W: Write> Connection<R, W> {
pub fn read<T: serde::de::DeserializeOwned>(&mut self) -> Result<T, crate::ReadError> {
crate::read(&mut self.reader)
}
pub fn write<T: serde::Serialize>(&mut self, t: &T) -> Result<(), crate::WriteError> {
crate::write(&mut self.writer, t)
}
pub fn flush(&mut self) -> io::Result<()> {
self.writer.flush()
}
}
#[cfg(feature = "tokio")]
impl<R: BufRead + Unpin, W: Write + Unpin> Connection<R, W> {
pub async fn read<T: serde::de::DeserializeOwned>(&mut self) -> Result<T, crate::ReadError> {
crate::read(&mut self.reader).await
}
pub async fn write<T: serde::Serialize>(&mut self, t: &T) -> Result<(), crate::WriteError> {
crate::write(&mut self.writer, t).await
}
pub async fn flush(&mut self) -> io::Result<()> {
self.writer.flush().await
}
}