Coverage Report

Created: 2025-12-31 06:49

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/stdout.rs
Line
Count
Source
1
use crate::io::blocking::Blocking;
2
use crate::io::stdio_common::SplitByUtf8BoundaryIfWindows;
3
use crate::io::AsyncWrite;
4
use std::io;
5
use std::pin::Pin;
6
use std::task::Context;
7
use std::task::Poll;
8
9
cfg_io_std! {
10
    /// A handle to the standard output stream of a process.
11
    ///
12
    /// Concurrent writes to stdout must be executed with care: Only individual
13
    /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
14
    /// you should be aware that writes using [`write_all`] are not guaranteed
15
    /// to occur as a single write, so multiple threads writing data with
16
    /// [`write_all`] may result in interleaved output.
17
    ///
18
    /// Created by the [`stdout`] function.
19
    ///
20
    /// [`stdout`]: stdout()
21
    /// [`AsyncWrite`]: AsyncWrite
22
    /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
23
    ///
24
    /// # Examples
25
    ///
26
    /// ```
27
    /// use tokio::io::{self, AsyncWriteExt};
28
    ///
29
    /// #[tokio::main]
30
    /// async fn main() -> io::Result<()> {
31
    ///     let mut stdout = io::stdout();
32
    ///     stdout.write_all(b"Hello world!").await?;
33
    ///     Ok(())
34
    /// }
35
    /// ```
36
    ///
37
    /// The following is an example of using `stdio` with loop.
38
    ///
39
    /// ```
40
    /// use tokio::io::{self, AsyncWriteExt};
41
    ///
42
    /// #[tokio::main]
43
    /// async fn main() {
44
    ///     let messages = vec!["hello", " world\n"];
45
    ///
46
    ///     // When you use `stdio` in a loop, it is recommended to create
47
    ///     // a single `stdio` instance outside the loop and call a write
48
    ///     // operation against that instance on each loop.
49
    ///     //
50
    ///     // Repeatedly creating `stdout` instances inside the loop and
51
    ///     // writing to that handle could result in mangled output since
52
    ///     // each write operation is handled by a different blocking thread.
53
    ///     let mut stdout = io::stdout();
54
    ///
55
    ///     for message in &messages {
56
    ///         stdout.write_all(message.as_bytes()).await.unwrap();
57
    ///         stdout.flush().await.unwrap();
58
    ///     }
59
    /// }
60
    /// ```
61
    #[derive(Debug)]
62
    pub struct Stdout {
63
        std: SplitByUtf8BoundaryIfWindows<Blocking<std::io::Stdout>>,
64
    }
65
66
    /// Constructs a new handle to the standard output of the current process.
67
    ///
68
    /// The returned handle allows writing to standard out from the within the
69
    /// Tokio runtime.
70
    ///
71
    /// Concurrent writes to stdout must be executed with care: Only individual
72
    /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
73
    /// you should be aware that writes using [`write_all`] are not guaranteed
74
    /// to occur as a single write, so multiple threads writing data with
75
    /// [`write_all`] may result in interleaved output.
76
    ///
77
    /// [`AsyncWrite`]: AsyncWrite
78
    /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
79
    ///
80
    /// # Examples
81
    ///
82
    /// ```
83
    /// use tokio::io::{self, AsyncWriteExt};
84
    ///
85
    /// #[tokio::main]
86
    /// async fn main() -> io::Result<()> {
87
    ///     let mut stdout = io::stdout();
88
    ///     stdout.write_all(b"Hello world!").await?;
89
    ///     Ok(())
90
    /// }
91
    /// ```
92
    ///
93
    /// The following is an example of using `stdio` with loop.
94
    ///
95
    /// ```
96
    /// use tokio::io::{self, AsyncWriteExt};
97
    ///
98
    /// #[tokio::main]
99
    /// async fn main() {
100
    ///     let messages = vec!["hello", " world\n"];
101
    ///
102
    ///     // When you use `stdio` in a loop, it is recommended to create
103
    ///     // a single `stdio` instance outside the loop and call a write
104
    ///     // operation against that instance on each loop.
105
    ///     //
106
    ///     // Repeatedly creating `stdout` instances inside the loop and
107
    ///     // writing to that handle could result in mangled output since
108
    ///     // each write operation is handled by a different blocking thread.
109
    ///     let mut stdout = io::stdout();
110
    ///
111
    ///     for message in &messages {
112
    ///         stdout.write_all(message.as_bytes()).await.unwrap();
113
    ///         stdout.flush().await.unwrap();
114
    ///     }
115
    /// }
116
    /// ```
117
0
    pub fn stdout() -> Stdout {
118
0
        let std = io::stdout();
119
        // SAFETY: The `Read` implementation of `std` does not read from the
120
        // buffer it is borrowing and correctly reports the length of the data
121
        // written into the buffer.
122
0
        let blocking = unsafe { Blocking::new(std) };
123
0
        Stdout {
124
0
            std: SplitByUtf8BoundaryIfWindows::new(blocking),
125
0
        }
126
0
    }
127
}
128
129
#[cfg(unix)]
130
mod sys {
131
    use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
132
133
    use super::Stdout;
134
135
    impl AsRawFd for Stdout {
136
0
        fn as_raw_fd(&self) -> RawFd {
137
0
            std::io::stdout().as_raw_fd()
138
0
        }
139
    }
140
141
    impl AsFd for Stdout {
142
0
        fn as_fd(&self) -> BorrowedFd<'_> {
143
0
            unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
144
0
        }
145
    }
146
}
147
148
cfg_windows! {
149
    use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle};
150
151
    impl AsRawHandle for Stdout {
152
        fn as_raw_handle(&self) -> RawHandle {
153
            std::io::stdout().as_raw_handle()
154
        }
155
    }
156
157
    impl AsHandle for Stdout {
158
        fn as_handle(&self) -> BorrowedHandle<'_> {
159
            unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
160
        }
161
    }
162
}
163
164
impl AsyncWrite for Stdout {
165
0
    fn poll_write(
166
0
        mut self: Pin<&mut Self>,
167
0
        cx: &mut Context<'_>,
168
0
        buf: &[u8],
169
0
    ) -> Poll<io::Result<usize>> {
170
0
        Pin::new(&mut self.std).poll_write(cx, buf)
171
0
    }
172
173
0
    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
174
0
        Pin::new(&mut self.std).poll_flush(cx)
175
0
    }
176
177
0
    fn poll_shutdown(
178
0
        mut self: Pin<&mut Self>,
179
0
        cx: &mut Context<'_>,
180
0
    ) -> Poll<Result<(), io::Error>> {
181
0
        Pin::new(&mut self.std).poll_shutdown(cx)
182
0
    }
183
}