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