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}
131