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