Coverage Report

Created: 2026-08-31 06:59

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.53.1/src/io/stderr.rs
Line
Count
Source
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::stderr();
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
    /// Note that unlike [`std::io::stderr`], each call to this `stderr()`
54
    /// produces a new writer, so for example, this program does **not** flush stderr:
55
    ///
56
    /// ```no_run
57
    /// # use tokio::io::AsyncWriteExt;
58
    /// # #[tokio::main]
59
    /// # async fn main() -> std::io::Result<()> {
60
    /// tokio::io::stderr().write_all(b"aa").await?;
61
    /// tokio::io::stderr().flush().await?;
62
    /// # Ok(())
63
    /// # }
64
    /// ```
65
    ///
66
    /// [`std::io::stderr`]: std::io::stderr
67
    /// [`AsyncWrite`]: AsyncWrite
68
    /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
69
    ///
70
    /// # Examples
71
    ///
72
    /// ```
73
    /// use tokio::io::{self, AsyncWriteExt};
74
    ///
75
    /// #[tokio::main]
76
    /// async fn main() -> io::Result<()> {
77
    ///     let mut stderr = io::stderr();
78
    ///     stderr.write_all(b"Print some error here.").await?;
79
    ///     Ok(())
80
    /// }
81
    /// ```
82
0
    pub fn stderr() -> Stderr {
83
0
        let std = io::stderr();
84
        // SAFETY: The `Read` implementation of `std` does not read from the
85
        // buffer it is borrowing and correctly reports the length of the data
86
        // written into the buffer.
87
0
        let blocking = unsafe { Blocking::new(std) };
88
0
        Stderr {
89
0
            std: SplitByUtf8BoundaryIfWindows::new(blocking),
90
0
        }
91
0
    }
92
}
93
94
#[cfg(unix)]
95
mod sys {
96
    use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
97
98
    use super::Stderr;
99
100
    impl AsRawFd for Stderr {
101
0
        fn as_raw_fd(&self) -> RawFd {
102
0
            std::io::stderr().as_raw_fd()
103
0
        }
104
    }
105
106
    impl AsFd for Stderr {
107
0
        fn as_fd(&self) -> BorrowedFd<'_> {
108
0
            unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
109
0
        }
110
    }
111
}
112
113
cfg_windows! {
114
    use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle};
115
116
    impl AsRawHandle for Stderr {
117
        fn as_raw_handle(&self) -> RawHandle {
118
            std::io::stderr().as_raw_handle()
119
        }
120
    }
121
122
    impl AsHandle for Stderr {
123
        fn as_handle(&self) -> BorrowedHandle<'_> {
124
            unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
125
        }
126
    }
127
}
128
129
impl AsyncWrite for Stderr {
130
0
    fn poll_write(
131
0
        mut self: Pin<&mut Self>,
132
0
        cx: &mut Context<'_>,
133
0
        buf: &[u8],
134
0
    ) -> Poll<io::Result<usize>> {
135
0
        Pin::new(&mut self.std).poll_write(cx, buf)
136
0
    }
137
138
0
    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
139
0
        Pin::new(&mut self.std).poll_flush(cx)
140
0
    }
141
142
0
    fn poll_shutdown(
143
0
        mut self: Pin<&mut Self>,
144
0
        cx: &mut Context<'_>,
145
0
    ) -> Poll<Result<(), io::Error>> {
146
0
        Pin::new(&mut self.std).poll_shutdown(cx)
147
0
    }
148
}