Skip to content

Commit 04eed9b

Browse files
committed
Initial implementation of annoymous_pipe
Signed-off-by: Jiahao XU <[email protected]>
1 parent a4ce33c commit 04eed9b

File tree

5 files changed

+250
-2
lines changed

5 files changed

+250
-2
lines changed

library/std/src/io/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,8 @@ pub(crate) mod copy;
338338
mod cursor;
339339
mod error;
340340
mod impls;
341+
#[unstable(feature = "annoymous_pipe", issue = "")]
342+
pub mod pipe;
341343
pub mod prelude;
342344
mod stdio;
343345
mod util;

library/std/src/io/pipe/mod.rs

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
use crate::{io, process::Stdio, sys::pipe::AnonPipe};
2+
3+
/// Create annoymous pipe that is close-on-exec and blocking.
4+
#[inline]
5+
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
6+
cfg_if::cfg_if! {
7+
if #[cfg(unix)] {
8+
unix::pipe()
9+
} else {
10+
windows::pipe()
11+
}
12+
}
13+
}
14+
15+
#[derive(Debug)]
16+
pub struct PipeReader(AnonPipe);
17+
18+
#[derive(Debug)]
19+
pub struct PipeWriter(AnonPipe);
20+
21+
pub struct NotAPipeError;
22+
23+
impl PipeReader {
24+
/// Create a new [`PipeReader`] instance that shares the same underlying file description.
25+
pub fn try_clone(&self) -> io::Result<Self> {
26+
self.0.try_clone().map(Self)
27+
}
28+
}
29+
30+
impl PipeWriter {
31+
/// Create a new [`PipeWriter`] instance that shares the same underlying file description.
32+
pub fn try_clone(&self) -> io::Result<Self> {
33+
self.0.try_clone().map(Self)
34+
}
35+
}
36+
37+
macro_rules! forward_io_read_traits {
38+
($name:ty) => {
39+
impl io::Read for $name {
40+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
41+
self.0.read(buf)
42+
}
43+
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
44+
self.0.read_vectored(bufs)
45+
}
46+
fn is_read_vectored(&self) -> bool {
47+
self.0.is_read_vectored()
48+
}
49+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
50+
self.0.read_to_end(buf)
51+
}
52+
fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
53+
self.0.read_buf(buf)
54+
}
55+
}
56+
};
57+
}
58+
forward_io_read_traits!(PipeReader);
59+
forward_io_read_traits!(&PipeReader);
60+
61+
macro_rules! forward_io_write_traits {
62+
($name:ty) => {
63+
impl io::Write for $name {
64+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
65+
self.0.write(buf)
66+
}
67+
fn flush(&mut self) -> io::Result<()> {
68+
Ok(())
69+
}
70+
71+
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
72+
self.0.write_vectored(bufs)
73+
}
74+
fn is_write_vectored(&self) -> bool {
75+
self.0.is_write_vectored()
76+
}
77+
}
78+
};
79+
}
80+
forward_io_write_traits!(PipeWriter);
81+
forward_io_write_traits!(&PipeWriter);
82+
83+
#[cfg(unix)]
84+
mod unix {
85+
use super::*;
86+
87+
use crate::{
88+
os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd},
89+
sys::{
90+
fd::FileDesc,
91+
pipe::{anon_pipe, AnonPipe},
92+
},
93+
sys_common::{FromInner, IntoInner},
94+
};
95+
96+
#[inline]
97+
pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
98+
anon_pipe().map(|(rx, tx)| (PipeReader(rx), PipeWriter(tx)))
99+
}
100+
101+
macro_rules! impl_traits {
102+
($name:ty) => {
103+
impl AsFd for $name {
104+
fn as_fd(&self) -> BorrowedFd<'_> {
105+
self.0.as_fd()
106+
}
107+
}
108+
impl AsRawFd for $name {
109+
fn as_raw_fd(&self) -> RawFd {
110+
self.0.as_raw_fd()
111+
}
112+
}
113+
impl From<$name> for OwnedFd {
114+
fn from(pipe: $name) -> Self {
115+
FileDesc::into_inner(AnonPipe::into_inner(pipe.0))
116+
}
117+
}
118+
impl FromRawFd for $name {
119+
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
120+
Self(AnonPipe::from_raw_fd(raw_fd))
121+
}
122+
}
123+
impl IntoRawFd for $name {
124+
fn into_raw_fd(self) -> RawFd {
125+
self.0.into_raw_fd()
126+
}
127+
}
128+
impl From<$name> for Stdio {
129+
fn from(pipe: $name) -> Self {
130+
Self::from(OwnedFd::from(pipe))
131+
}
132+
}
133+
};
134+
}
135+
impl_traits!(PipeReader);
136+
impl_traits!(PipeWriter);
137+
138+
fn owned_fd_to_anon_pipe(owned_fd: OwnedFd) -> AnonPipe {
139+
AnonPipe::from_inner(FileDesc::from_inner(owned_fd))
140+
}
141+
142+
impl TryFrom<OwnedFd> for PipeReader {
143+
type Error = NotAPipeError;
144+
145+
fn try_from(owned_fd: OwnedFd) -> Result<Self, Self::Error> {
146+
Ok(Self(owned_fd_to_anon_pipe(owned_fd)))
147+
}
148+
}
149+
150+
impl TryFrom<OwnedFd> for PipeWriter {
151+
type Error = NotAPipeError;
152+
153+
fn try_from(owned_fd: OwnedFd) -> Result<Self, Self::Error> {
154+
Ok(Self(owned_fd_to_anon_pipe(owned_fd)))
155+
}
156+
}
157+
}
158+
159+
#[cfg(windows)]
160+
mod windows {
161+
use super::*;
162+
163+
use crate::{
164+
os::windows::io::{
165+
AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle, OwnedHandle,
166+
RawHandle,
167+
},
168+
sys::{
169+
handle::Handle,
170+
pipe::{anon_pipe, AnonPipe, Pipes},
171+
},
172+
sys_common::{FromInner, IntoInner},
173+
};
174+
175+
#[inline]
176+
pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
177+
anon_pipe(true, false).map(|Pipes { ours, their }| (PipeReader(ours), PipeWrite(theirs)))
178+
}
179+
180+
macro_rules! impl_traits {
181+
($name:ty) => {
182+
impl AsHandle for $name {
183+
fn as_handle(&self) -> BorrowedHandle<'_> {
184+
self.0.handle().as_handle()
185+
}
186+
}
187+
impl AsRawHandle for $name {
188+
fn as_raw_handle(&self) -> RawHandle {
189+
self.0.handle().as_raw_handle()
190+
}
191+
}
192+
193+
impl FromRawHandle for $name {
194+
unsafe fn from_raw_handle(raw_handle: RawHandle) -> Self {
195+
Self(AnonPipe::from_inner(Handle::from_raw_handle(raw_handle)))
196+
}
197+
}
198+
impl IntoRawHandle for $name {
199+
fn into_raw_handle(self) -> RawHandle {
200+
self.0.into_handle().into_raw_handle()
201+
}
202+
}
203+
204+
impl From<$name> for OwnedHandle {
205+
fn from(pipe: $name) -> Self {
206+
Handle::into_inner(AnonPipe::into_inner(pipe.0))
207+
}
208+
}
209+
impl From<$name> for Stdio {
210+
fn from(pipe: $name) -> Self {
211+
Self::from(OwnedHandle::from(pipe))
212+
}
213+
}
214+
};
215+
}
216+
impl_traits!(PipeReader);
217+
impl_traits!(PipeWriter);
218+
219+
fn owned_handle_to_anon_pipe(owned_handle: OwnedHandle) -> AnonPipe {
220+
AnonPipe::from_inner(Handle::from_inner(owned_handle))
221+
}
222+
223+
impl TryFrom<OwnedHandle> for PipeReader {
224+
type Error = NotAPipeError;
225+
226+
fn try_from(owned_handle: OwnedHandle) -> Result<Self, Self::Error> {
227+
Ok(Self(owned_handle_to_anon_pipe(owned_handle)))
228+
}
229+
}
230+
231+
impl TryFrom<OwnedHandle> for PipeWriter {
232+
type Error = NotAPipeError;
233+
234+
fn try_from(owned_handle: OwnedHandle) -> Result<Self, Self::Error> {
235+
Ok(Self(owned_handle_to_anon_pipe(owned_handle)))
236+
}
237+
}
238+
}

library/std/src/sys/pal/unix/pipe.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use crate::sys_common::{FromInner, IntoInner};
99
// Anonymous pipes
1010
////////////////////////////////////////////////////////////////////////////////
1111

12+
#[derive(Debug)]
1213
pub struct AnonPipe(FileDesc);
1314

1415
pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
@@ -46,6 +47,10 @@ pub fn anon_pipe() -> io::Result<(AnonPipe, AnonPipe)> {
4647
}
4748

4849
impl AnonPipe {
50+
pub fn try_clone(&self) -> io::Result<Self> {
51+
self.0.duplicate().map(Self)
52+
}
53+
4954
pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
5055
self.0.read(buf)
5156
}

library/std/src/sys/pal/windows/handle.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
1717
/// An owned container for `HANDLE` object, closing them on Drop.
1818
///
1919
/// All methods are inherited through a `Deref` impl to `RawHandle`
20+
#[derive(Debug)]
2021
pub struct Handle(OwnedHandle);
2122

2223
impl Handle {

library/std/src/sys/pal/windows/pipe.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use crate::sys_common::{FromInner, IntoInner};
1919
// Anonymous pipes
2020
////////////////////////////////////////////////////////////////////////////////
2121

22+
#[derive(Debug)]
2223
pub struct AnonPipe {
2324
inner: Handle,
2425
}
@@ -182,7 +183,7 @@ pub fn spawn_pipe_relay(
182183
their_handle_inheritable: bool,
183184
) -> io::Result<AnonPipe> {
184185
// We need this handle to live for the lifetime of the thread spawned below.
185-
let source = source.duplicate()?;
186+
let source = source.try_clone()?;
186187

187188
// create a new pair of anon pipes.
188189
let Pipes { theirs, ours } = anon_pipe(ours_readable, their_handle_inheritable)?;
@@ -238,7 +239,8 @@ impl AnonPipe {
238239
pub fn into_handle(self) -> Handle {
239240
self.inner
240241
}
241-
fn duplicate(&self) -> io::Result<Self> {
242+
243+
pub fn try_clone(&self) -> io::Result<Self> {
242244
self.inner.duplicate(0, false, c::DUPLICATE_SAME_ACCESS).map(|inner| AnonPipe { inner })
243245
}
244246

0 commit comments

Comments
 (0)