1 use crate::io::blocking::Blocking;
2 use crate::io::{AsyncRead, ReadBuf};
3 
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 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)]
52 mod sys {
53     use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
54 
55     use super::Stdin;
56 
57     impl AsRawFd for Stdin {
as_raw_fd(&self) -> RawFd58         fn as_raw_fd(&self) -> RawFd {
59             std::io::stdin().as_raw_fd()
60         }
61     }
62 
63     impl AsFd for Stdin {
as_fd(&self) -> BorrowedFd<'_>64         fn as_fd(&self) -> BorrowedFd<'_> {
65             unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
66         }
67     }
68 }
69 
70 cfg_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 
86 impl AsyncRead for Stdin {
poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll<io::Result<()>>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