1use std::{
2 future::Future,
3 io,
4 os::{
5 fd::{AsRawFd, FromRawFd, IntoRawFd},
6 unix::prelude::RawFd,
7 },
8 process::Stdio,
9};
10
11use crate::{
12 buf::{IoBufMut, IoVecBufMut},
13 driver::{op::Op, shared_fd::SharedFd},
14 io::{
15 as_fd::{AsReadFd, AsWriteFd, SharedFdWrapper},
16 AsyncReadRent,
17 },
18 BufResult,
19};
20
21pub struct Pipe {
23 #[allow(dead_code)]
24 pub(crate) fd: SharedFd,
25}
26
27impl Pipe {
28 pub(crate) fn from_shared_fd(fd: SharedFd) -> Self {
29 Self { fd }
30 }
31
32 fn from_raw_fd(fd: RawFd) -> Self {
33 Self::from_shared_fd(SharedFd::new_without_register(fd))
34 }
35}
36
37pub fn new_pipe() -> io::Result<(Pipe, Pipe)> {
39 let mut pipes = [0 as libc::c_int; 2];
40 #[cfg(target_os = "linux")]
41 let flag = {
42 if crate::driver::op::is_legacy() {
43 libc::O_NONBLOCK
44 } else {
45 0
46 }
47 };
48 #[cfg(target_os = "linux")]
49 crate::syscall!(pipe2@RAW(pipes.as_mut_ptr() as _, flag))?;
50 #[cfg(not(target_os = "linux"))]
51 crate::syscall!(pipe@RAW(pipes.as_mut_ptr() as _))?;
52 Ok((Pipe::from_raw_fd(pipes[0]), Pipe::from_raw_fd(pipes[1])))
53}
54
55impl AsReadFd for Pipe {
56 #[inline]
57 fn as_reader_fd(&mut self) -> &SharedFdWrapper {
58 SharedFdWrapper::new(&self.fd)
59 }
60}
61
62impl AsWriteFd for Pipe {
63 #[inline]
64 fn as_writer_fd(&mut self) -> &SharedFdWrapper {
65 SharedFdWrapper::new(&self.fd)
66 }
67}
68
69impl IntoRawFd for Pipe {
70 #[inline]
71 fn into_raw_fd(self) -> RawFd {
72 self.fd
73 .try_unwrap()
74 .expect("unexpected multiple reference to rawfd")
75 }
76}
77
78impl AsRawFd for Pipe {
79 #[inline]
80 fn as_raw_fd(&self) -> RawFd {
81 self.fd.raw_fd()
82 }
83}
84
85impl From<Pipe> for Stdio {
86 #[inline]
87 fn from(pipe: Pipe) -> Self {
88 let rawfd = pipe.fd.try_unwrap().unwrap();
89 unsafe { Stdio::from_raw_fd(rawfd) }
90 }
91}
92
93impl AsyncReadRent for Pipe {
94 #[inline]
95 fn read<T: IoBufMut>(&mut self, buf: T) -> impl Future<Output = BufResult<usize, T>> {
96 let op = Op::read(self.fd.clone(), buf).unwrap();
98 op.result()
99 }
100
101 #[inline]
102 fn readv<T: IoVecBufMut>(&mut self, buf: T) -> impl Future<Output = BufResult<usize, T>> {
103 let op = Op::readv(self.fd.clone(), buf).unwrap();
105 op.result()
106 }
107}