use serde::Serialize;
use serde::de::DeserializeOwned;
use tokio::io;
use tokio::net;
use std::fmt;
use std::marker::PhantomData;
pub struct Connection<I, O> {
stream: net::TcpStream,
buffer: Vec<u8>,
_types: PhantomData<(I, O)>,
}
impl<I, O> Connection<I, O> {
pub(crate) fn new(stream: net::TcpStream, buffer: Vec<u8>) -> Self {
Self {
stream,
buffer,
_types: PhantomData,
}
}
pub fn seize(stream: net::TcpStream) -> Self {
Self::new(stream, Vec::new())
}
pub async fn write(&mut self, input: I) -> io::Result<()>
where
I: Serialize,
{
write_json(&mut self.stream, input).await
}
pub async fn write_bytes(&mut self, input: &[u8]) -> io::Result<()>
where
I: Serialize,
{
write(&mut self.stream, input).await
}
pub async fn read(&mut self) -> io::Result<O>
where
O: DeserializeOwned,
{
read_json(&mut self.stream, &mut self.buffer).await
}
pub async fn read_bytes(&mut self) -> io::Result<&[u8]> {
let n = read(&mut self.stream, &mut self.buffer).await?;
Ok(&self.buffer[..n])
}
pub async fn copy<T>(&mut self, to: &mut Connection<T, O>) -> io::Result<u64> {
io::copy(&mut self.stream, &mut to.stream).await
}
pub async fn connect<T>(&mut self, with: &mut Connection<T, O>) -> io::Result<(u64, u64)> {
io::copy_bidirectional(&mut self.stream, &mut with.stream).await
}
}
impl<I, O> fmt::Debug for Connection<I, O> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Connection")
.field("stream", &self.stream)
.field("buffer", &format!("{} bytes", self.buffer.len()))
.finish()
}
}
async fn read(stream: &mut net::TcpStream, buffer: &mut Vec<u8>) -> io::Result<usize> {
use tokio::io::AsyncReadExt;
let message_size = stream.read_u64().await? as usize;
if buffer.len() < message_size {
buffer.resize(message_size, 0);
}
stream.read_exact(&mut buffer[..message_size]).await
}
async fn write(stream: &mut net::TcpStream, bytes: &[u8]) -> io::Result<()> {
use tokio::io::AsyncWriteExt;
stream.write_u64(bytes.len() as u64).await?;
stream.write_all(bytes).await?;
stream.flush().await?;
Ok(())
}
pub async fn read_json<T: DeserializeOwned>(
stream: &mut net::TcpStream,
buffer: &mut Vec<u8>,
) -> io::Result<T> {
let message_size = read(stream, buffer).await?;
let data = serde_json::from_reader(&buffer[..message_size])?;
Ok(data)
}
pub async fn write_json<T: Serialize>(stream: &mut net::TcpStream, data: T) -> io::Result<()> {
let bytes = serde_json::to_vec(&data)?;
write(stream, &bytes).await
}