maybe_fut/api/io/
stdout.rs

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