use crate::io::blocking::Blocking; use crate::io::{AsyncRead, ReadBuf}; use std::io; use std::pin::Pin; use std::task::Context; use std::task::Poll; cfg_io_std! { /// A handle to the standard input stream of a process. /// /// The handle implements the [`AsyncRead`] trait, but beware that concurrent /// reads of `Stdin` must be executed with care. /// /// This handle is best used for non-interactive uses, such as when a file /// is piped into the application. For technical reasons, `stdin` is /// implemented by using an ordinary blocking read on a separate thread, and /// it is impossible to cancel that read. This can make shutdown of the /// runtime hang until the user presses enter. /// /// For interactive uses, it is recommended to spawn a thread dedicated to /// user input and use blocking IO directly in that thread. /// /// Created by the [`stdin`] function. /// /// [`stdin`]: fn@stdin /// [`AsyncRead`]: trait@AsyncRead #[derive(Debug)] pub struct Stdin { std: Blocking, } /// Constructs a new handle to the standard input of the current process. /// /// This handle is best used for non-interactive uses, such as when a file /// is piped into the application. For technical reasons, `stdin` is /// implemented by using an ordinary blocking read on a separate thread, and /// it is impossible to cancel that read. This can make shutdown of the /// runtime hang until the user presses enter. /// /// For interactive uses, it is recommended to spawn a thread dedicated to /// user input and use blocking IO directly in that thread. pub fn stdin() -> Stdin { let std = io::stdin(); Stdin { std: Blocking::new(std), } } } #[cfg(unix)] mod sys { #[cfg(not(tokio_no_as_fd))] use std::os::unix::io::{AsFd, BorrowedFd}; use std::os::unix::io::{AsRawFd, RawFd}; use super::Stdin; impl AsRawFd for Stdin { fn as_raw_fd(&self) -> RawFd { std::io::stdin().as_raw_fd() } } #[cfg(not(tokio_no_as_fd))] impl AsFd for Stdin { fn as_fd(&self) -> BorrowedFd<'_> { unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) } } } } cfg_windows! { #[cfg(not(tokio_no_as_fd))] use crate::os::windows::io::{AsHandle, BorrowedHandle}; use crate::os::windows::io::{AsRawHandle, RawHandle}; impl AsRawHandle for Stdin { fn as_raw_handle(&self) -> RawHandle { std::io::stdin().as_raw_handle() } } #[cfg(not(tokio_no_as_fd))] impl AsHandle for Stdin { fn as_handle(&self) -> BorrowedHandle<'_> { unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) } } } } impl AsyncRead for Stdin { fn poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll> { Pin::new(&mut self.std).poll_read(cx, buf) } }