1use crate::SerialIo;
7use futures::io::AsyncRead;
8use futures::io::AsyncWrite;
9use inspect::InspectMut;
10use parking_lot::Mutex;
11use std::fmt::Debug;
12use std::io;
13use std::io::IoSliceMut;
14use std::pin::Pin;
15use std::sync::Arc;
16use std::task::Context;
17use std::task::Poll;
18
19pub struct Connected<T>(T);
22
23impl<T> InspectMut for Connected<T> {
24 fn inspect_mut(&mut self, req: inspect::Request<'_>) {
25 req.respond();
26 }
27}
28
29impl<T: AsyncRead + AsyncWrite + Send> Connected<T> {
30 pub fn new(t: T) -> Self {
32 Self(t)
33 }
34
35 pub fn into_inner(self) -> T {
37 self.0
38 }
39}
40
41impl<T: AsyncRead + AsyncWrite + Send + Unpin> SerialIo for Connected<T> {
42 fn is_connected(&self) -> bool {
43 true
44 }
45
46 fn poll_connect(&mut self, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
47 Poll::Ready(Ok(()))
48 }
49
50 fn poll_disconnect(&mut self, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
51 Poll::Pending
52 }
53}
54
55impl<T: AsyncRead + Unpin> AsyncRead for Connected<T> {
56 fn poll_read(
57 self: Pin<&mut Self>,
58 cx: &mut Context<'_>,
59 buf: &mut [u8],
60 ) -> Poll<io::Result<usize>> {
61 let r = Pin::new(&mut self.get_mut().0).poll_read(cx, buf);
62 if matches!(r, Poll::Ready(Ok(0))) {
63 Poll::Pending
64 } else {
65 r
66 }
67 }
68
69 fn poll_read_vectored(
70 self: Pin<&mut Self>,
71 cx: &mut Context<'_>,
72 bufs: &mut [IoSliceMut<'_>],
73 ) -> Poll<io::Result<usize>> {
74 let r = Pin::new(&mut self.get_mut().0).poll_read_vectored(cx, bufs);
75 if matches!(r, Poll::Ready(Ok(0))) {
76 Poll::Pending
77 } else {
78 r
79 }
80 }
81}
82
83impl<T: AsyncWrite + Unpin> AsyncWrite for Connected<T> {
84 fn poll_write(
85 self: Pin<&mut Self>,
86 cx: &mut Context<'_>,
87 buf: &[u8],
88 ) -> Poll<io::Result<usize>> {
89 Pin::new(&mut self.get_mut().0).poll_write(cx, buf)
90 }
91
92 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
93 Pin::new(&mut self.get_mut().0).poll_flush(cx)
94 }
95
96 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
97 Pin::new(&mut self.get_mut().0).poll_close(cx)
98 }
99
100 fn poll_write_vectored(
101 self: Pin<&mut Self>,
102 cx: &mut Context<'_>,
103 bufs: &[io::IoSlice<'_>],
104 ) -> Poll<io::Result<usize>> {
105 Pin::new(&mut self.get_mut().0).poll_write_vectored(cx, bufs)
106 }
107}
108
109pub fn detachable<T: SerialIo + Unpin>(t: T) -> (DetachableIo<T>, IoDetacher<T>) {
112 let inner = Arc::new(Mutex::new(Some(t)));
113 (
114 DetachableIo {
115 inner: inner.clone(),
116 },
117 IoDetacher { inner },
118 )
119}
120
121#[derive(Debug)]
128pub struct DetachableIo<T> {
129 inner: Arc<Mutex<Option<T>>>,
130}
131
132impl<T: InspectMut> InspectMut for DetachableIo<T> {
133 fn inspect_mut(&mut self, req: inspect::Request<'_>) {
134 self.inner.lock().inspect_mut(req)
135 }
136}
137
138impl<T> DetachableIo<T> {
139 pub fn detached() -> Self {
141 Self {
142 inner: Arc::new(Mutex::new(None)),
143 }
144 }
145}
146
147pub struct IoDetacher<T> {
149 inner: Arc<Mutex<Option<T>>>,
150}
151
152impl<T: SerialIo + Unpin> IoDetacher<T> {
153 pub fn detach(self) -> T {
155 self.inner.lock().take().unwrap()
156 }
157}
158
159impl<T: SerialIo + Unpin> SerialIo for DetachableIo<T> {
160 fn is_connected(&self) -> bool {
161 self.inner.lock().as_ref().is_some_and(|s| s.is_connected())
162 }
163
164 fn poll_connect(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
165 let mut inner = self.inner.lock();
166 if let Some(serial) = &mut *inner {
167 serial.poll_connect(cx)
168 } else {
169 Poll::Pending
170 }
171 }
172
173 fn poll_disconnect(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
174 let mut inner = self.inner.lock();
175 if let Some(serial) = &mut *inner {
176 serial.poll_disconnect(cx)
177 } else {
178 Poll::Ready(Ok(()))
179 }
180 }
181}
182
183impl<T: AsyncRead + Unpin> AsyncRead for DetachableIo<T> {
184 fn poll_read(
185 self: Pin<&mut Self>,
186 cx: &mut Context<'_>,
187 buf: &mut [u8],
188 ) -> Poll<io::Result<usize>> {
189 let mut inner = self.inner.lock();
190 if let Some(inner) = &mut *inner {
191 Pin::new(inner).poll_read(cx, buf)
192 } else {
193 Poll::Ready(Ok(0))
194 }
195 }
196
197 fn poll_read_vectored(
198 self: Pin<&mut Self>,
199 cx: &mut Context<'_>,
200 bufs: &mut [IoSliceMut<'_>],
201 ) -> Poll<io::Result<usize>> {
202 let mut inner = self.inner.lock();
203 if let Some(inner) = &mut *inner {
204 Pin::new(inner).poll_read_vectored(cx, bufs)
205 } else {
206 Poll::Ready(Ok(0))
207 }
208 }
209}
210
211impl<T: AsyncWrite + Unpin> AsyncWrite for DetachableIo<T> {
212 fn poll_write(
213 self: Pin<&mut Self>,
214 cx: &mut Context<'_>,
215 buf: &[u8],
216 ) -> Poll<io::Result<usize>> {
217 let mut inner = self.inner.lock();
218 if let Some(inner) = &mut *inner {
219 Pin::new(inner).poll_write(cx, buf)
220 } else {
221 Poll::Ready(Err(io::ErrorKind::BrokenPipe.into()))
222 }
223 }
224
225 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
226 let mut inner = self.inner.lock();
227 if let Some(inner) = &mut *inner {
228 Pin::new(inner).poll_flush(cx)
229 } else {
230 Poll::Ready(Err(io::ErrorKind::BrokenPipe.into()))
231 }
232 }
233
234 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
235 let mut inner = self.inner.lock();
236 if let Some(inner) = &mut *inner {
237 Pin::new(inner).poll_close(cx)
238 } else {
239 Poll::Ready(Err(io::ErrorKind::BrokenPipe.into()))
240 }
241 }
242
243 fn poll_write_vectored(
244 self: Pin<&mut Self>,
245 cx: &mut Context<'_>,
246 bufs: &[io::IoSlice<'_>],
247 ) -> Poll<io::Result<usize>> {
248 let mut inner = self.inner.lock();
249 if let Some(inner) = &mut *inner {
250 Pin::new(inner).poll_write_vectored(cx, bufs)
251 } else {
252 Poll::Ready(Err(io::ErrorKind::BrokenPipe.into()))
253 }
254 }
255}