maybe_fut/api/io/
stdin.rs

1/// A handle to the standard input stream of a process.
2#[derive(Debug, Read, Unwrap)]
3#[io(feature("tokio"))]
4#[unwrap_types(std(std::io::Stdin), tokio(tokio::io::Stdin), tokio_gated("tokio"))]
5pub struct Stdin(StdinInner);
6
7#[derive(Debug)]
8enum StdinInner {
9    Std(std::io::Stdin),
10    #[cfg(tokio)]
11    Tokio(tokio::io::Stdin),
12}
13
14impl From<std::io::Stdin> for Stdin {
15    fn from(stdin: std::io::Stdin) -> Self {
16        Self(StdinInner::Std(stdin))
17    }
18}
19
20#[cfg(tokio)]
21#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
22impl From<tokio::io::Stdin> for Stdin {
23    fn from(stdin: tokio::io::Stdin) -> Self {
24        Self(StdinInner::Tokio(stdin))
25    }
26}
27
28/// Constructs a new handle to the standard input of the current process.
29pub fn stdin() -> Stdin {
30    #[cfg(tokio)]
31    {
32        if crate::is_async_context() {
33            tokio::io::stdin().into()
34        } else {
35            std::io::stdin().into()
36        }
37    }
38    #[cfg(not(tokio))]
39    {
40        std::io::stdin().into()
41    }
42}
43
44#[cfg(unix)]
45impl std::os::fd::AsFd for Stdin {
46    fn as_fd(&self) -> std::os::fd::BorrowedFd<'_> {
47        match &self.0 {
48            StdinInner::Std(file) => file.as_fd(),
49            #[cfg(tokio)]
50            StdinInner::Tokio(file) => file.as_fd(),
51        }
52    }
53}
54
55#[cfg(windows)]
56impl std::os::windows::io::AsHandle for Stdin {
57    fn as_handle(&self) -> std::os::windows::io::BorrowedHandle<'_> {
58        match &self.0 {
59            StdinInner::Std(file) => file.as_handle(),
60            #[cfg(tokio)]
61            StdinInner::Tokio(file) => file.as_handle(),
62        }
63    }
64}
65
66#[cfg(unix)]
67impl std::os::fd::AsRawFd for Stdin {
68    fn as_raw_fd(&self) -> std::os::fd::RawFd {
69        match &self.0 {
70            StdinInner::Std(file) => file.as_raw_fd(),
71            #[cfg(tokio)]
72            StdinInner::Tokio(file) => file.as_raw_fd(),
73        }
74    }
75}
76
77#[cfg(windows)]
78impl std::os::windows::io::AsRawHandle for Stdin {
79    fn as_raw_handle(&self) -> std::os::windows::io::RawHandle {
80        match &self.0 {
81            StdinInner::Std(file) => file.as_raw_handle(),
82            #[cfg(tokio)]
83            StdinInner::Tokio(file) => file.as_raw_handle(),
84        }
85    }
86}
87
88#[cfg(test)]
89mod test {
90
91    use super::*;
92
93    #[test]
94    fn test_should_stdin_sync() {
95        let stdin = stdin();
96        assert!(matches!(stdin.0, StdinInner::Std(_)));
97    }
98
99    #[cfg(tokio)]
100    #[tokio::test]
101    async fn test_should_stdin_async() {
102        let stdin = stdin();
103        assert!(matches!(stdin.0, StdinInner::Tokio(_)));
104    }
105}