1use crate::io::blocking::Blocking;
2use crate::io::{AsyncRead, ReadBuf};
3
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 input stream of a process.
11 ///
12 /// The handle implements the [`AsyncRead`] trait, but beware that concurrent
13 /// reads of `Stdin` must be executed with care.
14 ///
15 /// This handle is best used for non-interactive uses, such as when a file
16 /// is piped into the application. For technical reasons, `stdin` is
17 /// implemented by using an ordinary blocking read on a separate thread, and
18 /// it is impossible to cancel that read. This can make shutdown of the
19 /// runtime hang until the user presses enter.
20 ///
21 /// For interactive uses, it is recommended to spawn a thread dedicated to
22 /// user input and use blocking IO directly in that thread.
23 ///
24 /// Created by the [`stdin`] function.
25 ///
26 /// [`stdin`]: fn@stdin
27 /// [`AsyncRead`]: trait@AsyncRead
28 #[derive(Debug)]
29 pub struct Stdin {
30 std: Blocking<std::io::Stdin>,
31 }
32
33 /// Constructs a new handle to the standard input of the current process.
34 ///
35 /// This handle is best used for non-interactive uses, such as when a file
36 /// is piped into the application. For technical reasons, `stdin` is
37 /// implemented by using an ordinary blocking read on a separate thread, and
38 /// it is impossible to cancel that read. This can make shutdown of the
39 /// runtime hang until the user presses enter.
40 ///
41 /// For interactive uses, it is recommended to spawn a thread dedicated to
42 /// user input and use blocking IO directly in that thread.
43 pub fn stdin() -> Stdin {
44 let std = io::stdin();
45 Stdin {
46 std: Blocking::new(std),
47 }
48 }
49}
50
51#[cfg(unix)]
52mod sys {
53 use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
54
55 use super::Stdin;
56
57 impl AsRawFd for Stdin {
58 fn as_raw_fd(&self) -> RawFd {
59 std::io::stdin().as_raw_fd()
60 }
61 }
62
63 impl AsFd for Stdin {
64 fn as_fd(&self) -> BorrowedFd<'_> {
65 unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
66 }
67 }
68}
69
70cfg_windows! {
71 use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle};
72
73 impl AsRawHandle for Stdin {
74 fn as_raw_handle(&self) -> RawHandle {
75 std::io::stdin().as_raw_handle()
76 }
77 }
78
79 impl AsHandle for Stdin {
80 fn as_handle(&self) -> BorrowedHandle<'_> {
81 unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
82 }
83 }
84}
85
86impl AsyncRead for Stdin {
87 fn poll_read(
88 mut self: Pin<&mut Self>,
89 cx: &mut Context<'_>,
90 buf: &mut ReadBuf<'_>,
91 ) -> Poll<io::Result<()>> {
92 Pin::new(&mut self.std).poll_read(cx, buf)
93 }
94}
95