1 use crate::io::blocking::Blocking;
2 use crate::io::stdio_common::SplitByUtf8BoundaryIfWindows;
3 use crate::io::AsyncWrite;
4 
5 use std::io;
6 use std::pin::Pin;
7 use std::task::Context;
8 use std::task::Poll;
9 
10 cfg_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)]
77 mod sys {
78     use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
79 
80     use super::Stderr;
81 
82     impl AsRawFd for Stderr {
as_raw_fd(&self) -> RawFd83         fn as_raw_fd(&self) -> RawFd {
84             std::io::stderr().as_raw_fd()
85         }
86     }
87 
88     impl AsFd for Stderr {
as_fd(&self) -> BorrowedFd<'_>89         fn as_fd(&self) -> BorrowedFd<'_> {
90             unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
91         }
92     }
93 }
94 
95 cfg_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 
111 impl AsyncWrite for Stderr {
poll_write( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8], ) -> Poll<io::Result<usize>>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 
poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>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 
poll_shutdown( mut self: Pin<&mut Self>, cx: &mut Context<'_>, ) -> Poll<Result<(), io::Error>>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