use std::{
io,
net::Shutdown,
os::unix::prelude::{AsRawFd, FromRawFd, RawFd},
path::Path,
};
use socket2::SockAddr;
use crate::{
UnsubmittedWrite,
buf::{BoundedBuf, BoundedBufMut, fixed::FixedBuf},
io::{AsyncBufRead, AsyncBufWrite, SharedFd, Socket},
};
#[derive(Clone)]
pub struct UnixStream {
pub(super) inner: Socket,
}
impl UnixStream {
pub async fn connect<P: AsRef<Path>>(path: P) -> 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 fn from_std(socket: std::os::unix::net::UnixStream) -> UnixStream {
let inner = Socket::from_std(socket);
Self { inner }
}
pub(crate) fn from_socket(inner: Socket) -> Self {
Self { inner }
}
pub async fn read<T: BoundedBufMut>(&self, buf: T) -> crate::BufResult<usize, T> {
self.inner.read(buf).await
}
pub async fn read_fixed<T>(&self, buf: T) -> crate::BufResult<usize, T>
where
T: BoundedBufMut<BufMut = FixedBuf>,
{
self.inner.read_fixed(buf).await
}
pub fn write<T: BoundedBuf>(&self, buf: T) -> UnsubmittedWrite<T> {
self.inner.write(buf)
}
pub async fn write_all<T: BoundedBuf>(&self, buf: T) -> crate::BufResult<(), T> {
self.inner.write_all(buf).await
}
pub async fn write_fixed<T>(&self, buf: T) -> crate::BufResult<usize, T>
where
T: BoundedBuf<Buf = FixedBuf>,
{
self.inner.write_fixed(buf).await
}
pub async fn write_fixed_all<T>(&self, buf: T) -> crate::BufResult<(), T>
where
T: BoundedBuf<Buf = FixedBuf>,
{
self.inner.write_fixed_all(buf).await
}
pub async fn writev<T: BoundedBuf>(&self, buf: Vec<T>) -> crate::BufResult<usize, Vec<T>> {
self.inner.writev(buf).await
}
pub fn shutdown(&self, how: std::net::Shutdown) -> io::Result<()> {
self.inner.shutdown(how)
}
pub fn split(self) -> (UnixStreamRead, UnixStreamWrite) {
(
UnixStreamRead(Self {
inner: self.inner.clone(),
}),
UnixStreamWrite(self),
)
}
pub fn unsplit(read: UnixStreamRead, write: UnixStreamWrite) -> Option<Self> {
(read.0.as_raw_fd() == write.0.as_raw_fd()).then_some(read.0)
}
}
impl AsyncBufRead for UnixStream {
#[inline(always)]
async fn read<B>(&self, buf: B) -> (io::Result<usize>, B)
where
B: BoundedBufMut,
{
UnixStream::read(self, buf).await
}
}
impl AsyncBufWrite for UnixStream {
#[inline(always)]
async fn write<B>(&self, buf: B) -> (io::Result<usize>, B)
where
B: BoundedBuf,
{
UnixStream::write(self, buf).submit().await
}
#[inline(always)]
async fn shutdown(self, direction: Shutdown) -> io::Result<()> {
UnixStream::shutdown(&self, direction)
}
}
impl FromRawFd for UnixStream {
unsafe fn from_raw_fd(fd: RawFd) -> Self {
UnixStream::from_socket(Socket::from_shared_fd(SharedFd::new(fd)))
}
}
impl AsRawFd for UnixStream {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}
pub struct UnixStreamRead(UnixStream);
impl UnixStreamRead {
#[inline]
pub async fn read<T: BoundedBufMut>(&self, buf: T) -> crate::BufResult<usize, T> {
self.0.read(buf).await
}
}
pub struct UnixStreamWrite(UnixStream);
impl UnixStreamWrite {
#[inline]
pub fn write<T: BoundedBuf>(&self, buf: T) -> UnsubmittedWrite<T> {
self.0.write(buf)
}
#[inline]
pub async fn write_all<T: BoundedBuf>(&self, buf: T) -> crate::BufResult<(), T> {
self.0.write_all(buf).await
}
}