use {
super::{c_wrappers, FdOps},
crate::{
os::unix::unixprelude::*,
unnamed_pipe::{Recver as PubRecver, Sender as PubSender},
Sealed,
},
std::{
fmt::{self, Debug, Formatter},
io,
os::fd::OwnedFd,
},
};
#[cfg(feature = "tokio")]
pub(crate) mod tokio;
#[allow(private_bounds)]
pub trait UnnamedPipeExt: AsFd + Sealed {
#[inline]
fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
c_wrappers::set_nonblocking(self.as_fd(), nonblocking)
}
}
#[cfg_attr(feature = "doc_cfg", doc(cfg(unix)))]
impl UnnamedPipeExt for PubRecver {}
#[cfg_attr(feature = "doc_cfg", doc(cfg(unix)))]
impl UnnamedPipeExt for PubSender {}
pub fn pipe(nonblocking: bool) -> io::Result<(PubSender, PubRecver)> {
let (success, fds) = unsafe {
let mut fds: [c_int; 2] = [0; 2];
let result;
#[cfg(any(target_os = "linux", target_os = "android"))]
{
result =
libc::pipe2(fds.as_mut_ptr(), if nonblocking { libc::O_NONBLOCK } else { 0 });
}
#[cfg(not(any(target_os = "linux", target_os = "android")))]
{
result = libc::pipe(fds.as_mut_ptr());
}
(result == 0, fds)
};
if success {
let (w, r) = unsafe {
let w = OwnedFd::from_raw_fd(fds[1]);
let r = OwnedFd::from_raw_fd(fds[0]);
(w, r)
};
let w = PubSender(Sender(FdOps(w)));
let r = PubRecver(Recver(FdOps(r)));
#[cfg(not(any(target_os = "linux", target_os = "android")))]
{
if nonblocking {
w.set_nonblocking(true)?;
r.set_nonblocking(true)?;
}
}
Ok((w, r))
} else {
Err(io::Error::last_os_error())
}
}
#[inline]
pub(crate) fn pipe_impl() -> io::Result<(PubSender, PubRecver)> { pipe(false) }
pub(crate) struct Recver(FdOps);
impl Sealed for Recver {}
impl Debug for Recver {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Recver").field("fd", &self.0 .0.as_raw_fd()).finish()
}
}
multimacro! {
Recver,
forward_rbv(FdOps, &),
forward_sync_ref_read,
forward_try_clone,
forward_handle,
derive_sync_mut_read,
}
pub(crate) struct Sender(FdOps);
impl Sealed for Sender {}
impl Debug for Sender {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct("Sender").field("fd", &self.0 .0.as_raw_fd()).finish()
}
}
multimacro! {
Sender,
forward_rbv(FdOps, &),
forward_sync_ref_write,
forward_try_clone,
forward_handle,
derive_sync_mut_write,
}