Skip to content

Commit 61eefb5

Browse files
committed
Auto merge of rust-lang#127153 - NobodyXu:pipe, r=jhpratt
Initial implementation of anonymous_pipe API ACP completed in rust-lang/libs-team#375 Tracking issue: rust-lang#127154
2 parents 24d2ac0 + 317bc8d commit 61eefb5

File tree

10 files changed

+426
-3
lines changed

10 files changed

+426
-3
lines changed

library/std/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,9 @@ pub use core::{
685685
module_path, option_env, stringify, trace_macros,
686686
};
687687

688+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
689+
pub use crate::sys::anonymous_pipe as pipe;
690+
688691
#[unstable(
689692
feature = "concat_bytes",
690693
issue = "87555",
+142
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
//! Module for anonymous pipe
2+
//!
3+
//! ```
4+
//! # #![cfg(not(miri))]
5+
//! #![feature(anonymous_pipe)]
6+
//! # fn main() -> std::io::Result<()> {
7+
//! let (reader, writer) = std::pipe::pipe()?;
8+
//! # Ok(())
9+
//! # }
10+
//! ```
11+
12+
use crate::{io, sys::pipe::AnonPipe};
13+
14+
/// Create anonymous pipe that is close-on-exec and blocking.
15+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
16+
#[inline]
17+
pub fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
18+
cfg_if::cfg_if! {
19+
if #[cfg(unix)] {
20+
unix::pipe()
21+
} else if #[cfg(windows)] {
22+
windows::pipe()
23+
} else {
24+
Err(io::Error::UNSUPPORTED_PLATFORM)
25+
}
26+
}
27+
}
28+
29+
/// Read end of the anonymous pipe.
30+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
31+
#[derive(Debug)]
32+
pub struct PipeReader(AnonPipe);
33+
34+
/// Write end of the anonymous pipe.
35+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
36+
#[derive(Debug)]
37+
pub struct PipeWriter(AnonPipe);
38+
39+
impl PipeReader {
40+
/// Create a new [`PipeReader`] instance that shares the same underlying file description.
41+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
42+
pub fn try_clone(&self) -> io::Result<Self> {
43+
self.0.try_clone().map(Self)
44+
}
45+
}
46+
47+
impl PipeWriter {
48+
/// Create a new [`PipeWriter`] instance that shares the same underlying file description.
49+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
50+
pub fn try_clone(&self) -> io::Result<Self> {
51+
self.0.try_clone().map(Self)
52+
}
53+
}
54+
55+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
56+
impl io::Read for &PipeReader {
57+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
58+
self.0.read(buf)
59+
}
60+
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
61+
self.0.read_vectored(bufs)
62+
}
63+
#[inline]
64+
fn is_read_vectored(&self) -> bool {
65+
self.0.is_read_vectored()
66+
}
67+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
68+
self.0.read_to_end(buf)
69+
}
70+
fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
71+
self.0.read_buf(buf)
72+
}
73+
}
74+
75+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
76+
impl io::Read for PipeReader {
77+
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
78+
self.0.read(buf)
79+
}
80+
fn read_vectored(&mut self, bufs: &mut [io::IoSliceMut<'_>]) -> io::Result<usize> {
81+
self.0.read_vectored(bufs)
82+
}
83+
#[inline]
84+
fn is_read_vectored(&self) -> bool {
85+
self.0.is_read_vectored()
86+
}
87+
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
88+
self.0.read_to_end(buf)
89+
}
90+
fn read_buf(&mut self, buf: io::BorrowedCursor<'_>) -> io::Result<()> {
91+
self.0.read_buf(buf)
92+
}
93+
}
94+
95+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
96+
impl io::Write for &PipeWriter {
97+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
98+
self.0.write(buf)
99+
}
100+
#[inline]
101+
fn flush(&mut self) -> io::Result<()> {
102+
Ok(())
103+
}
104+
105+
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
106+
self.0.write_vectored(bufs)
107+
}
108+
109+
#[inline]
110+
fn is_write_vectored(&self) -> bool {
111+
self.0.is_write_vectored()
112+
}
113+
}
114+
115+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
116+
impl io::Write for PipeWriter {
117+
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
118+
self.0.write(buf)
119+
}
120+
#[inline]
121+
fn flush(&mut self) -> io::Result<()> {
122+
Ok(())
123+
}
124+
125+
fn write_vectored(&mut self, bufs: &[io::IoSlice<'_>]) -> io::Result<usize> {
126+
self.0.write_vectored(bufs)
127+
}
128+
129+
#[inline]
130+
fn is_write_vectored(&self) -> bool {
131+
self.0.is_write_vectored()
132+
}
133+
}
134+
135+
#[cfg(unix)]
136+
mod unix;
137+
138+
#[cfg(windows)]
139+
mod windows;
140+
141+
#[cfg(all(test, not(miri)))]
142+
mod tests;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use super::*;
2+
use crate::io::{Read, Write};
3+
4+
#[test]
5+
fn pipe_creation_and_rw() {
6+
let (mut rx, mut tx) = pipe().unwrap();
7+
tx.write_all(b"12345").unwrap();
8+
drop(tx);
9+
10+
let mut s = String::new();
11+
rx.read_to_string(&mut s).unwrap();
12+
assert_eq!(s, "12345");
13+
}
14+
15+
#[test]
16+
fn pipe_try_clone_and_rw() {
17+
let (mut rx, mut tx) = pipe().unwrap();
18+
tx.try_clone().unwrap().write_all(b"12").unwrap();
19+
tx.write_all(b"345").unwrap();
20+
drop(tx);
21+
22+
let mut s = String::new();
23+
rx.try_clone().unwrap().take(3).read_to_string(&mut s).unwrap();
24+
assert_eq!(s, "123");
25+
26+
s.clear();
27+
rx.read_to_string(&mut s).unwrap();
28+
assert_eq!(s, "45");
29+
}
+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
use super::*;
2+
3+
use crate::{
4+
os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd},
5+
process::Stdio,
6+
sys::{
7+
fd::FileDesc,
8+
pipe::{anon_pipe, AnonPipe},
9+
},
10+
sys_common::{FromInner, IntoInner},
11+
};
12+
13+
#[inline]
14+
pub(super) fn pipe() -> io::Result<(PipeReader, PipeWriter)> {
15+
anon_pipe().map(|(rx, tx)| (PipeReader(rx), PipeWriter(tx)))
16+
}
17+
18+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
19+
impl AsFd for PipeReader {
20+
fn as_fd(&self) -> BorrowedFd<'_> {
21+
self.0.as_fd()
22+
}
23+
}
24+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
25+
impl AsRawFd for PipeReader {
26+
fn as_raw_fd(&self) -> RawFd {
27+
self.0.as_raw_fd()
28+
}
29+
}
30+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
31+
impl From<PipeReader> for OwnedFd {
32+
fn from(pipe: PipeReader) -> Self {
33+
FileDesc::into_inner(AnonPipe::into_inner(pipe.0))
34+
}
35+
}
36+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
37+
impl FromRawFd for PipeReader {
38+
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
39+
Self(AnonPipe::from_raw_fd(raw_fd))
40+
}
41+
}
42+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
43+
impl IntoRawFd for PipeReader {
44+
fn into_raw_fd(self) -> RawFd {
45+
self.0.into_raw_fd()
46+
}
47+
}
48+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
49+
impl From<PipeReader> for Stdio {
50+
fn from(pipe: PipeReader) -> Self {
51+
Self::from(OwnedFd::from(pipe))
52+
}
53+
}
54+
55+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
56+
impl AsFd for PipeWriter {
57+
fn as_fd(&self) -> BorrowedFd<'_> {
58+
self.0.as_fd()
59+
}
60+
}
61+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
62+
impl AsRawFd for PipeWriter {
63+
fn as_raw_fd(&self) -> RawFd {
64+
self.0.as_raw_fd()
65+
}
66+
}
67+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
68+
impl From<PipeWriter> for OwnedFd {
69+
fn from(pipe: PipeWriter) -> Self {
70+
FileDesc::into_inner(AnonPipe::into_inner(pipe.0))
71+
}
72+
}
73+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
74+
impl FromRawFd for PipeWriter {
75+
unsafe fn from_raw_fd(raw_fd: RawFd) -> Self {
76+
Self(AnonPipe::from_raw_fd(raw_fd))
77+
}
78+
}
79+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
80+
impl IntoRawFd for PipeWriter {
81+
fn into_raw_fd(self) -> RawFd {
82+
self.0.into_raw_fd()
83+
}
84+
}
85+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
86+
impl From<PipeWriter> for Stdio {
87+
fn from(pipe: PipeWriter) -> Self {
88+
Self::from(OwnedFd::from(pipe))
89+
}
90+
}
91+
92+
fn convert_to_pipe(owned_fd: OwnedFd) -> AnonPipe {
93+
AnonPipe::from_inner(FileDesc::from_inner(OwnedFd::from(owned_fd)))
94+
}
95+
96+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
97+
impl From<OwnedFd> for PipeReader {
98+
fn from(owned_fd: OwnedFd) -> Self {
99+
Self(convert_to_pipe(owned_fd))
100+
}
101+
}
102+
103+
#[unstable(feature = "anonymous_pipe", issue = "127154")]
104+
impl From<OwnedFd> for PipeWriter {
105+
fn from(owned_fd: OwnedFd) -> Self {
106+
Self(convert_to_pipe(owned_fd))
107+
}
108+
}

0 commit comments

Comments
 (0)