monoio/net/unix/
pipe.rs

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
21/// Unix pipe.
22pub 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
37/// Create a new pair of pipe.
38pub 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        // Submit the read operation
97        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        // Submit the read operation
104        let op = Op::readv(self.fd.clone(), buf).unwrap();
105        op.result()
106    }
107}