madsim_real_tokio/io/
stderr.rs

1use crate::io::blocking::Blocking;
2use crate::io::stdio_common::SplitByUtf8BoundaryIfWindows;
3use crate::io::AsyncWrite;
4
5use std::io;
6use std::pin::Pin;
7use std::task::Context;
8use std::task::Poll;
9
10cfg_io_std! {
11    /// A handle to the standard error stream of a process.
12    ///
13    /// Concurrent writes to stderr must be executed with care: Only individual
14    /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
15    /// you should be aware that writes using [`write_all`] are not guaranteed
16    /// to occur as a single write, so multiple threads writing data with
17    /// [`write_all`] may result in interleaved output.
18    ///
19    /// Created by the [`stderr`] function.
20    ///
21    /// [`stderr`]: stderr()
22    /// [`AsyncWrite`]: AsyncWrite
23    /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
24    ///
25    /// # Examples
26    ///
27    /// ```
28    /// use tokio::io::{self, AsyncWriteExt};
29    ///
30    /// #[tokio::main]
31    /// async fn main() -> io::Result<()> {
32    ///     let mut stderr = io::stdout();
33    ///     stderr.write_all(b"Print some error here.").await?;
34    ///     Ok(())
35    /// }
36    /// ```
37    #[derive(Debug)]
38    pub struct Stderr {
39        std: SplitByUtf8BoundaryIfWindows<Blocking<std::io::Stderr>>,
40    }
41
42    /// Constructs a new handle to the standard error of the current process.
43    ///
44    /// The returned handle allows writing to standard error from the within the
45    /// Tokio runtime.
46    ///
47    /// Concurrent writes to stderr must be executed with care: Only individual
48    /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
49    /// you should be aware that writes using [`write_all`] are not guaranteed
50    /// to occur as a single write, so multiple threads writing data with
51    /// [`write_all`] may result in interleaved output.
52    ///
53    /// [`AsyncWrite`]: AsyncWrite
54    /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
55    ///
56    /// # Examples
57    ///
58    /// ```
59    /// use tokio::io::{self, AsyncWriteExt};
60    ///
61    /// #[tokio::main]
62    /// async fn main() -> io::Result<()> {
63    ///     let mut stderr = io::stderr();
64    ///     stderr.write_all(b"Print some error here.").await?;
65    ///     Ok(())
66    /// }
67    /// ```
68    pub fn stderr() -> Stderr {
69        let std = io::stderr();
70        Stderr {
71            std: SplitByUtf8BoundaryIfWindows::new(Blocking::new(std)),
72        }
73    }
74}
75
76#[cfg(unix)]
77mod sys {
78    use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
79
80    use super::Stderr;
81
82    impl AsRawFd for Stderr {
83        fn as_raw_fd(&self) -> RawFd {
84            std::io::stderr().as_raw_fd()
85        }
86    }
87
88    impl AsFd for Stderr {
89        fn as_fd(&self) -> BorrowedFd<'_> {
90            unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
91        }
92    }
93}
94
95cfg_windows! {
96    use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle};
97
98    impl AsRawHandle for Stderr {
99        fn as_raw_handle(&self) -> RawHandle {
100            std::io::stderr().as_raw_handle()
101        }
102    }
103
104    impl AsHandle for Stderr {
105        fn as_handle(&self) -> BorrowedHandle<'_> {
106            unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
107        }
108    }
109}
110
111impl AsyncWrite for Stderr {
112    fn poll_write(
113        mut self: Pin<&mut Self>,
114        cx: &mut Context<'_>,
115        buf: &[u8],
116    ) -> Poll<io::Result<usize>> {
117        Pin::new(&mut self.std).poll_write(cx, buf)
118    }
119
120    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
121        Pin::new(&mut self.std).poll_flush(cx)
122    }
123
124    fn poll_shutdown(
125        mut self: Pin<&mut Self>,
126        cx: &mut Context<'_>,
127    ) -> Poll<Result<(), io::Error>> {
128        Pin::new(&mut self.std).poll_shutdown(cx)
129    }
130}