#[cfg(feature = "tokio")]
#[cfg_attr(feature = "doc_cfg", doc(cfg(feature = "tokio")))]
pub mod tokio;
use {
crate::{
os::windows::{c_wrappers, security_descriptor::*, winprelude::*},
ref2ptr,
unnamed_pipe::{Recver as PubRecver, Sender as PubSender},
Sealed, TryClone,
},
std::{
fmt::{self, Debug, Formatter},
io::{self, Read, Write},
mem::ManuallyDrop,
num::NonZeroUsize,
},
windows_sys::Win32::System::Pipes::CreatePipe,
};
#[non_exhaustive]
#[derive(Clone, Debug)]
pub struct CreationOptions<'sd> {
pub security_descriptor: Option<BorrowedSecurityDescriptor<'sd>>,
pub inheritable: bool,
pub buffer_size_hint: Option<NonZeroUsize>,
}
impl Sealed for CreationOptions<'_> {}
impl<'sd> CreationOptions<'sd> {
pub const fn new() -> Self {
Self { inheritable: true, security_descriptor: None, buffer_size_hint: None }
}
builder_setters! {
security_descriptor: Option<BorrowedSecurityDescriptor<'sd>>,
inheritable: bool,
buffer_size_hint: Option<NonZeroUsize>,
}
pub fn create(self) -> io::Result<(PubSender, PubRecver)> {
let hint_raw = match self.buffer_size_hint {
Some(num) => num.get(),
None => 0,
}
.try_into()
.unwrap();
let sd = create_security_attributes(self.security_descriptor, self.inheritable);
let [mut w, mut r] = [INVALID_HANDLE_VALUE; 2];
let success =
unsafe { CreatePipe(&mut r, &mut w, ref2ptr(&sd).cast_mut().cast(), hint_raw) } != 0;
if success {
let (w, r) = unsafe {
let w = OwnedHandle::from_raw_handle(w.to_std());
let r = OwnedHandle::from_raw_handle(r.to_std());
(w, r)
};
let w = PubSender(Sender { io: ManuallyDrop::new(w.into()), needs_flush: false });
let r = PubRecver(Recver(r.into()));
Ok((w, r))
} else {
Err(io::Error::last_os_error())
}
}
#[inline]
pub fn build(self) -> io::Result<(PubSender, PubRecver)> { self.create() }
}
impl Default for CreationOptions<'_> {
fn default() -> Self { Self::new() }
}
pub(crate) fn pipe_impl() -> io::Result<(PubSender, PubRecver)> {
CreationOptions::default().build()
}
pub(crate) struct Recver(AdvOwnedHandle);
forward_handle!(Recver);
impl Read for Recver {
#[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
c_wrappers::read(self.as_handle(), buf)
}
}
impl Debug for Recver {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_tuple("Recver").field(&self.0.as_raw_handle()).finish()
}
}
impl TryClone for Recver {
#[inline]
fn try_clone(&self) -> io::Result<Self> {
c_wrappers::duplicate_handle(self.as_handle()).map(AdvOwnedHandle::from).map(Self)
}
}
#[derive(Debug)]
pub(crate) struct Sender {
io: ManuallyDrop<AdvOwnedHandle>,
needs_flush: bool,
}
impl Write for Sender {
#[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let rslt = c_wrappers::write(self.as_handle(), buf);
if rslt.is_ok() {
self.needs_flush = true;
}
rslt
}
#[inline]
fn flush(&mut self) -> io::Result<()> {
if self.needs_flush {
let rslt = c_wrappers::flush(self.as_handle());
if rslt.is_ok() {
self.needs_flush = false;
}
rslt
} else {
Ok(())
}
}
}
impl Drop for Sender {
fn drop(&mut self) {
let h = unsafe { ManuallyDrop::take(&mut self.io) };
if self.needs_flush {
linger_pool::linger(h);
}
}
}
impl TryClone for Sender {
fn try_clone(&self) -> io::Result<Self> {
Ok(Self { io: ManuallyDrop::new(self.io.try_clone()?), needs_flush: self.needs_flush })
}
}
impl AsHandle for Sender {
#[inline]
fn as_handle(&self) -> BorrowedHandle<'_> { self.io.as_handle() }
}
impl From<OwnedHandle> for Sender {
#[inline]
fn from(handle: OwnedHandle) -> Self {
Self { io: ManuallyDrop::new(handle.into()), needs_flush: true }
}
}
impl From<Sender> for OwnedHandle {
#[inline]
fn from(tx: Sender) -> Self {
unsafe { ManuallyDrop::take(&mut ManuallyDrop::new(tx).io).into() }
}
}