1 // Copyright (c) 2023 Huawei Device Co., Ltd.
2 // Licensed under the Apache License, Version 2.0 (the "License");
3 // you may not use this file except in compliance with the License.
4 // You may obtain a copy of the License at
5 //
6 //     http://www.apache.org/licenses/LICENSE-2.0
7 //
8 // Unless required by applicable law or agreed to in writing, software
9 // distributed under the License is distributed on an "AS IS" BASIS,
10 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 // See the License for the specific language governing permissions and
12 // limitations under the License.
13 
14 use std::future::Future;
15 use std::io;
16 use std::pin::Pin;
17 use std::task::{Context, Poll};
18 
19 use crate::io::{AsyncRead, ReadBuf, State};
20 use crate::spawn_blocking;
21 
22 /// A handle to the standard input stream of a process.
23 ///
24 /// `Stdin` implements the [`AsyncRead`] trait.
25 pub struct Stdin {
26     std: Option<io::Stdin>,
27     state: State<io::Stdin>,
28 }
29 
30 /// Constructs a new handle to the standard input of the current process.
31 ///
32 /// # Example
33 /// ```
34 /// use ylong_runtime::io::stdin;
35 /// let _stdin = stdin();
36 /// ```
stdin() -> Stdin37 pub fn stdin() -> Stdin {
38     let stdin = io::stdin();
39     Stdin {
40         std: Some(stdin),
41         state: State::init(),
42     }
43 }
44 
45 impl AsyncRead for Stdin {
poll_read( mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut ReadBuf<'_>, ) -> Poll<io::Result<()>>46     fn poll_read(
47         mut self: Pin<&mut Self>,
48         cx: &mut Context<'_>,
49         buf: &mut ReadBuf<'_>,
50     ) -> Poll<io::Result<()>> {
51         loop {
52             match self.state {
53                 State::Idle(ref mut buf_op) => {
54                     // before each take, BufInner is set to some
55                     let mut buf_inner = buf_op.take().unwrap();
56 
57                     if !buf_inner.is_empty() {
58                         buf_inner.clone_into(buf);
59                         *buf_op = Some(buf_inner);
60                         return Poll::Ready(Ok(()));
61                     }
62 
63                     buf_inner.set_len(buf);
64                     // before each take, std is set to some
65                     let mut std = self.std.take().unwrap();
66                     let handle = spawn_blocking(move || {
67                         let res = buf_inner.read_from(&mut std);
68                         (res, buf_inner, std)
69                     });
70 
71                     self.state = State::Poll(handle);
72                 }
73                 State::Poll(ref mut join_handle) => {
74                     let (res, mut buf_inner, std) = match Pin::new(join_handle).poll(cx)? {
75                         Poll::Ready(t) => t,
76                         Poll::Pending => return Poll::Pending,
77                     };
78                     self.std = Some(std);
79 
80                     return match res {
81                         Ok(_) => {
82                             buf_inner.clone_into(buf);
83                             self.state = State::Idle(Some(buf_inner));
84                             Poll::Ready(Ok(()))
85                         }
86                         Err(e) => {
87                             self.state = State::Idle(Some(buf_inner));
88                             Poll::Ready(Err(e))
89                         }
90                     };
91                 }
92             }
93         }
94     }
95 }
96 
97 #[cfg(unix)]
98 use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
99 
100 #[cfg(unix)]
101 impl AsRawFd for Stdin {
as_raw_fd(&self) -> RawFd102     fn as_raw_fd(&self) -> RawFd {
103         io::stdin().as_raw_fd()
104     }
105 }
106 
107 #[cfg(unix)]
108 impl AsFd for Stdin {
as_fd(&self) -> BorrowedFd<'_>109     fn as_fd(&self) -> BorrowedFd<'_> {
110         unsafe { BorrowedFd::borrow_raw(self.as_raw_fd()) }
111     }
112 }
113 
114 #[cfg(windows)]
115 use std::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, RawHandle};
116 
117 #[cfg(windows)]
118 impl AsRawHandle for Stdin {
as_raw_handle(&self) -> RawHandle119     fn as_raw_handle(&self) -> RawHandle {
120         io::stdin().as_raw_handle()
121     }
122 }
123 
124 #[cfg(windows)]
125 impl AsHandle for Stdin {
as_handle(&self) -> BorrowedHandle<'_>126     fn as_handle(&self) -> BorrowedHandle<'_> {
127         unsafe { BorrowedHandle::borrow_raw(self.as_raw_handle()) }
128     }
129 }
130