Skip to content

Commit d9e13af

Browse files
authored
Rollup 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 627a13b + 72f5999 commit d9e13af

File tree

10 files changed

+414
-2
lines changed

10 files changed

+414
-2
lines changed

library/std/src/lib.rs

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

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

0 commit comments

Comments
 (0)