1use crate::io::blocking::Blocking;
2use crate::io::stdio_common::SplitByUtf8BoundaryIfWindows;
3use crate::io::AsyncWrite;
4use std::io;
5use std::pin::Pin;
6use std::task::Context;
7use std::task::Poll;
8
9cfg_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 #[derive(Debug)]
37 pub struct Stdout {
38 std: SplitByUtf8BoundaryIfWindows<Blocking<std::io::Stdout>>,
39 }
40
41 /// Constructs a new handle to the standard output of the current process.
42 ///
43 /// The returned handle allows writing to standard out from the within the
44 /// Tokio runtime.
45 ///
46 /// Concurrent writes to stdout must be executed with care: Only individual
47 /// writes to this [`AsyncWrite`] are guaranteed to be intact. In particular
48 /// you should be aware that writes using [`write_all`] are not guaranteed
49 /// to occur as a single write, so multiple threads writing data with
50 /// [`write_all`] may result in interleaved output.
51 ///
52 /// [`AsyncWrite`]: AsyncWrite
53 /// [`write_all`]: crate::io::AsyncWriteExt::write_all()
54 ///
55 /// # Examples
56 ///
57 /// ```
58 /// use tokio::io::{self, AsyncWriteExt};
59 ///
60 /// #[tokio::main]
61 /// async fn main() -> io::Result<()> {
62 /// let mut stdout = io::stdout();
63 /// stdout.write_all(b"Hello world!").await?;
64 /// Ok(())
65 /// }
66 /// ```
67 pub fn stdout() -> Stdout {
68 let std = io::stdout();
69 Stdout {
70 std: SplitByUtf8BoundaryIfWindows::new(Blocking::new(std)),
71 }
72 }
73}
74
75#[cfg(unix)]
76mod sys {
77 use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
78
79 use super::Stdout;
80
81 impl AsRawFd for Stdout {
82 fn as_raw_fd(&self) -> RawFd {
83 std::io::stdout().as_raw_fd()
84 }
85 }
86
87 impl AsFd for Stdout {
88 fn as_fd(&self) -> BorrowedFd<'_> {
89 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
90 }
91 }
92}
93
94cfg_windows! {
95 use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle};
96
97 impl AsRawHandle for Stdout {
98 fn as_raw_handle(&self) -> RawHandle {
99 std::io::stdout().as_raw_handle()
100 }
101 }
102
103 impl AsHandle for Stdout {
104 fn as_handle(&self) -> BorrowedHandle<'_> {
105 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
106 }
107 }
108}
109
110impl AsyncWrite for Stdout {
111 fn poll_write(
112 mut self: Pin<&mut Self>,
113 cx: &mut Context<'_>,
114 buf: &[u8],
115 ) -> Poll<io::Result<usize>> {
116 Pin::new(&mut self.std).poll_write(cx, buf)
117 }
118
119 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
120 Pin::new(&mut self.std).poll_flush(cx)
121 }
122
123 fn poll_shutdown(
124 mut self: Pin<&mut Self>,
125 cx: &mut Context<'_>,
126 ) -> Poll<Result<(), io::Error>> {
127 Pin::new(&mut self.std).poll_shutdown(cx)
128 }
129}
130