Skip to main content

compio_fs/stdio/
unix.rs

1use std::io;
2
3use compio_buf::{BufResult, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
4use compio_driver::{AsFd, AsRawFd, BorrowedFd, BufferRef, RawFd};
5use compio_io::{AsyncRead, AsyncReadManaged, AsyncReadMulti, AsyncWrite};
6use compio_runtime::fd::AsyncFd;
7use futures_util::Stream;
8use rustix::stdio::{raw_stderr, raw_stdin, raw_stdout};
9
10#[cfg(doc)]
11use super::{stderr, stdin, stdout};
12
13#[derive(Debug)]
14struct StaticFd(RawFd);
15
16impl StaticFd {
17    const STDERR: Self = Self(raw_stderr());
18    const STDIN: Self = Self(raw_stdin());
19    const STDOUT: Self = Self(raw_stdout());
20}
21
22impl AsFd for StaticFd {
23    fn as_fd(&self) -> BorrowedFd<'_> {
24        unsafe { BorrowedFd::borrow_raw(self.0) }
25    }
26}
27
28impl AsRawFd for StaticFd {
29    fn as_raw_fd(&self) -> RawFd {
30        self.0 as _
31    }
32}
33
34/// A handle to the standard input stream of a process.
35///
36/// See [`stdin`].
37#[derive(Debug, Clone)]
38pub struct Stdin(AsyncFd<StaticFd>);
39
40impl Stdin {
41    pub(crate) fn new() -> Self {
42        // SAFETY: no need to attach on unix
43        Self(unsafe { AsyncFd::new_unchecked(StaticFd::STDIN) })
44    }
45}
46
47impl AsyncRead for Stdin {
48    async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B> {
49        (&*self).read(buf).await
50    }
51
52    async fn read_vectored<V: IoVectoredBufMut>(&mut self, buf: V) -> BufResult<usize, V> {
53        (&*self).read_vectored(buf).await
54    }
55}
56
57impl AsyncRead for &Stdin {
58    async fn read<B: IoBufMut>(&mut self, buf: B) -> BufResult<usize, B> {
59        (&self.0).read(buf).await
60    }
61
62    async fn read_vectored<V: IoVectoredBufMut>(&mut self, buf: V) -> BufResult<usize, V> {
63        (&self.0).read_vectored(buf).await
64    }
65}
66
67impl AsyncReadManaged for Stdin {
68    type Buffer = BufferRef;
69
70    async fn read_managed(&mut self, len: usize) -> io::Result<Option<Self::Buffer>> {
71        (&*self).read_managed(len).await
72    }
73}
74
75impl AsyncReadManaged for &Stdin {
76    type Buffer = BufferRef;
77
78    async fn read_managed(&mut self, len: usize) -> io::Result<Option<Self::Buffer>> {
79        (&self.0).read_managed(len).await
80    }
81}
82
83impl AsyncReadMulti for Stdin {
84    fn read_multi(&mut self, len: usize) -> impl Stream<Item = io::Result<Self::Buffer>> {
85        self.0.read_multi(len)
86    }
87}
88
89impl AsyncReadMulti for &Stdin {
90    fn read_multi(&mut self, len: usize) -> impl Stream<Item = io::Result<Self::Buffer>> {
91        self.0.read_multi_shared(len)
92    }
93}
94
95impl AsRawFd for Stdin {
96    fn as_raw_fd(&self) -> RawFd {
97        self.0.as_raw_fd()
98    }
99}
100
101/// A handle to the standard output stream of a process.
102///
103/// See [`stdout`].
104#[derive(Debug, Clone)]
105pub struct Stdout(AsyncFd<StaticFd>);
106
107impl Stdout {
108    pub(crate) fn new() -> Self {
109        // SAFETY: no need to attach on unix
110        Self(unsafe { AsyncFd::new_unchecked(StaticFd::STDOUT) })
111    }
112}
113
114impl AsyncWrite for Stdout {
115    async fn write<T: IoBuf>(&mut self, buf: T) -> BufResult<usize, T> {
116        self.0.write(buf).await
117    }
118
119    async fn write_vectored<T: IoVectoredBuf>(&mut self, buf: T) -> BufResult<usize, T> {
120        self.0.write_vectored(buf).await
121    }
122
123    async fn flush(&mut self) -> io::Result<()> {
124        self.0.flush().await
125    }
126
127    async fn shutdown(&mut self) -> io::Result<()> {
128        self.0.shutdown().await
129    }
130}
131
132impl AsRawFd for Stdout {
133    fn as_raw_fd(&self) -> RawFd {
134        self.0.as_raw_fd()
135    }
136}
137
138/// A handle to the standard output stream of a process.
139///
140/// See [`stderr`].
141#[derive(Debug, Clone)]
142pub struct Stderr(AsyncFd<StaticFd>);
143
144impl Stderr {
145    pub(crate) fn new() -> Self {
146        // SAFETY: no need to attach on unix
147        Self(unsafe { AsyncFd::new_unchecked(StaticFd::STDERR) })
148    }
149}
150
151impl AsyncWrite for Stderr {
152    async fn write<T: IoBuf>(&mut self, buf: T) -> BufResult<usize, T> {
153        self.0.write(buf).await
154    }
155
156    async fn write_vectored<T: IoVectoredBuf>(&mut self, buf: T) -> BufResult<usize, T> {
157        self.0.write_vectored(buf).await
158    }
159
160    async fn flush(&mut self) -> io::Result<()> {
161        self.0.flush().await
162    }
163
164    async fn shutdown(&mut self) -> io::Result<()> {
165        self.0.shutdown().await
166    }
167}
168
169impl AsRawFd for Stderr {
170    fn as_raw_fd(&self) -> RawFd {
171        self.0.as_raw_fd()
172    }
173}