use std::path::Path;
use socket2::SockAddr;
#[cfg(target_os = "linux")]
use crate::{
buf::PooledBuf,
io::{AsyncReadManaged, AsyncReadMulti, Stream},
};
use crate::{
buf::{BufResult, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut},
driver::helpers::socket::Socket,
io::{AsyncRead, AsyncWrite, IntoOwnedSplit, ReuniteError, ReuniteOwned},
net::split::{OwnedReadHalf, OwnedWriteHalf, ReadHalf, WriteHalf, split},
};
pub struct UnixStream {
pub(super) inner: Socket,
}
impl UnixStream {
pub async fn connect<P: AsRef<Path>>(path: P) -> std::io::Result<UnixStream> {
let socket = Socket::new_unix(libc::SOCK_STREAM)?;
socket.connect(SockAddr::unix(path)?).await?;
let unix_stream = UnixStream { inner: socket };
Ok(unix_stream)
}
pub async fn close(self) -> std::io::Result<()> {
self.inner.close().await
}
pub fn shutdown(&self, how: std::net::Shutdown) -> std::io::Result<()> {
self.inner.shutdown(how)
}
pub fn local_addr(&self) -> std::io::Result<std::os::unix::net::SocketAddr> {
self.inner
.handle
.local_addr()?
.as_unix()
.ok_or_else(|| std::io::Error::other("Could not get socket path"))
}
pub fn peer_addr(&self) -> std::io::Result<std::os::unix::net::SocketAddr> {
self.inner
.handle
.peer_addr()?
.as_unix()
.ok_or_else(|| std::io::Error::other("Could not get peer path"))
}
pub fn split(&self) -> (ReadHalf<'_, Self>, WriteHalf<'_, Self>) {
split(self)
}
pub fn into_split(self) -> (OwnedReadHalf<Self>, OwnedWriteHalf<Self>) {
<Self as IntoOwnedSplit>::into_split(self)
}
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(target_os = "linux")))]
pub async fn recv_managed(&self, len: usize) -> std::io::Result<Option<PooledBuf>> {
self.inner.recv_managed(len).await
}
#[cfg(target_os = "linux")]
#[cfg_attr(docsrs, doc(cfg(target_os = "linux")))]
pub fn recv_multi(&self) -> std::io::Result<impl Stream<Item = std::io::Result<PooledBuf>> + use<>> {
self.inner.recv_multi()
}
}
impl AsyncRead for &UnixStream {
async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B> {
self.inner.recv(buf).await
}
async fn read_vectored<V: IoVectoredBufMut>(&mut self, bufs: V) -> BufResult<usize, V> {
let (result, bufs) = self.inner.recvmsg(bufs).await.into_parts();
BufResult(result.map(|(n, _)| n), bufs)
}
}
impl AsyncRead for UnixStream {
async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B> {
self.inner.recv(buf).await
}
async fn read_vectored<V: IoVectoredBufMut>(&mut self, bufs: V) -> BufResult<usize, V> {
let (result, bufs) = self.inner.recvmsg(bufs).await.into_parts();
BufResult(result.map(|(n, _)| n), bufs)
}
}
#[cfg(target_os = "linux")]
impl AsyncReadManaged for UnixStream {
type Buffer = PooledBuf;
async fn read_managed(&mut self, len: usize) -> std::io::Result<Option<Self::Buffer>> {
self.recv_managed(len).await
}
}
#[cfg(target_os = "linux")]
impl AsyncReadManaged for &UnixStream {
type Buffer = PooledBuf;
async fn read_managed(&mut self, len: usize) -> std::io::Result<Option<Self::Buffer>> {
self.recv_managed(len).await
}
}
#[cfg(target_os = "linux")]
impl AsyncReadMulti for UnixStream {
fn read_multi(&mut self) -> std::io::Result<impl Stream<Item = std::io::Result<Self::Buffer>>> {
self.recv_multi()
}
}
#[cfg(target_os = "linux")]
impl AsyncReadMulti for &UnixStream {
fn read_multi(&mut self) -> std::io::Result<impl Stream<Item = std::io::Result<Self::Buffer>>> {
self.recv_multi()
}
}
impl AsyncWrite for &UnixStream {
async fn write<B: IoBuf>(&mut self, buf: B) -> BufResult<usize, B> {
self.inner.send(buf).await
}
async fn write_vectored<V: IoVectoredBuf>(&mut self, bufs: V) -> BufResult<usize, V> {
let (res, bufs) = self.inner.sendmsg(bufs, None, None::<Vec<u8>>).await.into_parts();
BufResult(res.map(|(n, _)| n), bufs)
}
async fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
async fn shutdown(&mut self) -> std::io::Result<()> {
self.inner.shutdown(std::net::Shutdown::Write)
}
}
impl AsyncWrite for UnixStream {
async fn write<B: IoBuf>(&mut self, buf: B) -> BufResult<usize, B> {
self.inner.send(buf).await
}
async fn write_vectored<V: IoVectoredBuf>(&mut self, bufs: V) -> BufResult<usize, V> {
let (res, bufs) = self.inner.sendmsg(bufs, None, None::<Vec<u8>>).await.into_parts();
BufResult(res.map(|(n, _)| n), bufs)
}
async fn flush(&mut self) -> std::io::Result<()> {
Ok(())
}
async fn shutdown(&mut self) -> std::io::Result<()> {
self.inner.shutdown(std::net::Shutdown::Write)
}
}
impl From<Socket> for UnixStream {
fn from(inner: Socket) -> Self {
Self { inner }
}
}
impl IntoOwnedSplit for UnixStream {
type ReadHalf = OwnedReadHalf<Self>;
type WriteHalf = OwnedWriteHalf<Self>;
fn into_split(self) -> (Self::ReadHalf, Self::WriteHalf) {
let read = OwnedReadHalf {
inner: self.inner.clone(),
_stream: std::marker::PhantomData,
};
let write = OwnedWriteHalf {
inner: self.inner,
shutdown_on_drop: true,
_stream: std::marker::PhantomData,
};
(read, write)
}
}
impl ReuniteOwned for UnixStream {
fn reunite(
read: Self::ReadHalf,
write: Self::WriteHalf,
) -> Result<Self, ReuniteError<Self::ReadHalf, Self::WriteHalf>> {
read.reunite(write)
}
}
impl UnixStream {
pub fn from_std(socket: std::os::unix::net::UnixStream) -> std::io::Result<Self> {
let inner = Socket::from_socket(socket2::Socket::from(socket))?;
Ok(Self { inner })
}
}