Coverage Report

Created: 2025-07-18 06:42

/rust/registry/src/index.crates.io-6f17d22bba15001f/tokio-1.46.1/src/io/stdin.rs
Line
Count
Source (jump to first uncovered line)
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
0
    pub fn stdin() -> Stdin {
44
0
        let std = io::stdin();
45
0
        // SAFETY: The `Read` implementation of `std` does not read from the
46
0
        // buffer it is borrowing and correctly reports the length of the data
47
0
        // written into the buffer.
48
0
        let std = unsafe { Blocking::new(std) };
49
0
        Stdin {
50
0
            std,
51
0
        }
52
0
    }
53
}
54
55
#[cfg(unix)]
56
mod sys {
57
    use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
58
59
    use super::Stdin;
60
61
    impl AsRawFd for Stdin {
62
0
        fn as_raw_fd(&self) -> RawFd {
63
0
            std::io::stdin().as_raw_fd()
64
0
        }
65
    }
66
67
    impl AsFd for Stdin {
68
0
        fn as_fd(&self) -> BorrowedFd<'_> {
69
0
            unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
70
0
        }
71
    }
72
}
73
74
cfg_windows! {
75
    use crate::os::windows::io::{AsHandle, BorrowedHandle, AsRawHandle, RawHandle};
76
77
    impl AsRawHandle for Stdin {
78
        fn as_raw_handle(&self) -> RawHandle {
79
            std::io::stdin().as_raw_handle()
80
        }
81
    }
82
83
    impl AsHandle for Stdin {
84
        fn as_handle(&self) -> BorrowedHandle<'_> {
85
            unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
86
        }
87
    }
88
}
89
90
impl AsyncRead for Stdin {
91
0
    fn poll_read(
92
0
        mut self: Pin<&mut Self>,
93
0
        cx: &mut Context<'_>,
94
0
        buf: &mut ReadBuf<'_>,
95
0
    ) -> Poll<io::Result<()>> {
96
0
        Pin::new(&mut self.std).poll_read(cx, buf)
97
0
    }
98
}