use tokio::{
io::{AsyncRead, AsyncWrite, empty, sink},
net::{TcpStream, UnixStream},
};
use crate::endpoint::sys::PathGuard;
pub type SyncRead = Box<dyn std::io::Read + Send>;
pub type SyncWrite = Box<dyn std::io::Write + Send>;
pub type BoxRead = Box<dyn AsyncRead + Unpin + Send>;
pub type BoxWrite = Box<dyn AsyncWrite + Unpin + Send>;
pub trait AsyncStream: AsyncRead + AsyncWrite + Unpin + Send {}
impl<T: AsyncRead + AsyncWrite + Unpin + Send> AsyncStream for T {}
#[derive(Default)]
pub struct SyncHalves {
pub reader: Option<SyncRead>,
pub writer: Option<SyncWrite>,
pub guard: Option<PathGuard>,
}
pub struct Connection {
pub stream: EndpointStream,
pub guard: Option<PathGuard>,
}
pub enum EndpointStream {
Duplex(Box<dyn AsyncStream>),
Split(BoxRead, BoxWrite),
Datagram(DatagramSocket),
}
#[derive(Clone)]
pub enum DatagramSocket {
Udp(std::sync::Arc<tokio::net::UdpSocket>),
}
impl DatagramSocket {
pub async fn recv(&self, buf: &mut [u8]) -> std::io::Result<usize> {
match self {
DatagramSocket::Udp(socket) => socket.recv(buf).await,
}
}
pub async fn send(&self, buf: &[u8]) -> std::io::Result<usize> {
match self {
DatagramSocket::Udp(socket) => socket.send(buf).await,
}
}
}
pub enum ReadHalf {
Stream(BoxRead),
Datagram(DatagramSocket),
}
pub enum WriteHalf {
Stream(BoxWrite),
Datagram(DatagramSocket),
}
impl EndpointStream {
pub fn into_connection(self) -> Connection {
Connection {
stream: self,
guard: None,
}
}
pub fn into_connection_with_guard(self, guard: PathGuard) -> Connection {
Connection {
stream: self,
guard: Some(guard),
}
}
pub fn tcp(s: TcpStream) -> Self {
Self::Duplex(Box::new(s))
}
pub fn unix(s: UnixStream) -> Self {
Self::Duplex(Box::new(s))
}
pub fn stdio() -> Self {
Self::Split(Box::new(tokio::io::stdin()), Box::new(tokio::io::stdout()))
}
pub fn read_only(r: impl AsyncRead + Unpin + Send + 'static) -> Self {
Self::Split(Box::new(r), Box::new(sink()))
}
pub fn write_only(w: impl AsyncWrite + Unpin + Send + 'static) -> Self {
Self::Split(Box::new(empty()), Box::new(w))
}
pub fn datagram(socket: tokio::net::UdpSocket) -> Self {
Self::Datagram(DatagramSocket::Udp(std::sync::Arc::new(socket)))
}
pub fn into_halves(self) -> (ReadHalf, WriteHalf) {
match self {
Self::Duplex(s) => {
let (r, w) = tokio::io::split(s);
(
ReadHalf::Stream(Box::new(r)),
WriteHalf::Stream(Box::new(w)),
)
}
Self::Split(r, w) => (ReadHalf::Stream(r), WriteHalf::Stream(w)),
Self::Datagram(socket) => (
ReadHalf::Datagram(socket.clone()),
WriteHalf::Datagram(socket),
),
}
}
}