Coverage Report

Created: 2025-11-16 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/tokio-1.48.0/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::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
0
    pub fn stderr() -> Stderr {
69
0
        let std = io::stderr();
70
        // SAFETY: The `Read` implementation of `std` does not read from the
71
        // buffer it is borrowing and correctly reports the length of the data
72
        // written into the buffer.
73
0
        let blocking = unsafe { Blocking::new(std) };
74
0
        Stderr {
75
0
            std: SplitByUtf8BoundaryIfWindows::new(blocking),
76
0
        }
77
0
    }
78
}
79
80
#[cfg(unix)]
81
mod sys {
82
    use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
83
84
    use super::Stderr;
85
86
    impl AsRawFd for Stderr {
87
0
        fn as_raw_fd(&self) -> RawFd {
88
0
            std::io::stderr().as_raw_fd()
89
0
        }
90
    }
91
92
    impl AsFd for Stderr {
93
0
        fn as_fd(&self) -> BorrowedFd<'_> {
94
0
            unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
95
0
        }
96
    }
97
}
98
99
cfg_windows! {
100
    use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle};
101
102
    impl AsRawHandle for Stderr {
103
        fn as_raw_handle(&self) -> RawHandle {
104
            std::io::stderr().as_raw_handle()
105
        }
106
    }
107
108
    impl AsHandle for Stderr {
109
        fn as_handle(&self) -> BorrowedHandle<'_> {
110
            unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
111
        }
112
    }
113
}
114
115
impl AsyncWrite for Stderr {
116
0
    fn poll_write(
117
0
        mut self: Pin<&mut Self>,
118
0
        cx: &mut Context<'_>,
119
0
        buf: &[u8],
120
0
    ) -> Poll<io::Result<usize>> {
121
0
        Pin::new(&mut self.std).poll_write(cx, buf)
122
0
    }
123
124
0
    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
125
0
        Pin::new(&mut self.std).poll_flush(cx)
126
0
    }
127
128
0
    fn poll_shutdown(
129
0
        mut self: Pin<&mut Self>,
130
0
        cx: &mut Context<'_>,
131
0
    ) -> Poll<Result<(), io::Error>> {
132
0
        Pin::new(&mut self.std).poll_shutdown(cx)
133
0
    }
134
}