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