1 | use std::io::{self, IoSlice}; |
2 | use std::ops::DerefMut; |
3 | use std::pin::Pin; |
4 | use std::task::{Context, Poll}; |
5 | |
6 | /// Writes bytes asynchronously. |
7 | /// |
8 | /// The trait inherits from [`std::io::Write`] and indicates that an I/O object is |
9 | /// **nonblocking**. All non-blocking I/O objects must return an error when |
10 | /// bytes cannot be written instead of blocking the current thread. |
11 | /// |
12 | /// Specifically, this means that the [`poll_write`] function will return one of |
13 | /// the following: |
14 | /// |
15 | /// * `Poll::Ready(Ok(n))` means that `n` bytes of data was immediately |
16 | /// written. |
17 | /// |
18 | /// * `Poll::Pending` means that no data was written from the buffer |
19 | /// provided. The I/O object is not currently writable but may become writable |
20 | /// in the future. Most importantly, **the current future's task is scheduled |
21 | /// to get unparked when the object is writable**. This means that like |
22 | /// `Future::poll` you'll receive a notification when the I/O object is |
23 | /// writable again. |
24 | /// |
25 | /// * `Poll::Ready(Err(e))` for other errors are standard I/O errors coming from the |
26 | /// underlying object. |
27 | /// |
28 | /// This trait importantly means that the [`write`][stdwrite] method only works in |
29 | /// the context of a future's task. The object may panic if used outside of a task. |
30 | /// |
31 | /// Note that this trait also represents that the [`Write::flush`][stdflush] method |
32 | /// works very similarly to the `write` method, notably that `Ok(())` means that the |
33 | /// writer has successfully been flushed, a "would block" error means that the |
34 | /// current task is ready to receive a notification when flushing can make more |
35 | /// progress, and otherwise normal errors can happen as well. |
36 | /// |
37 | /// Utilities for working with `AsyncWrite` values are provided by |
38 | /// [`AsyncWriteExt`]. |
39 | /// |
40 | /// [`std::io::Write`]: std::io::Write |
41 | /// [`poll_write`]: AsyncWrite::poll_write() |
42 | /// [stdwrite]: std::io::Write::write() |
43 | /// [stdflush]: std::io::Write::flush() |
44 | /// [`AsyncWriteExt`]: crate::io::AsyncWriteExt |
45 | pub trait AsyncWrite { |
46 | /// Attempt to write bytes from `buf` into the object. |
47 | /// |
48 | /// On success, returns `Poll::Ready(Ok(num_bytes_written))`. If successful, |
49 | /// then it must be guaranteed that `n <= buf.len()`. A return value of `0` |
50 | /// typically means that the underlying object is no longer able to accept |
51 | /// bytes and will likely not be able to in the future as well, or that the |
52 | /// buffer provided is empty. |
53 | /// |
54 | /// If the object is not ready for writing, the method returns |
55 | /// `Poll::Pending` and arranges for the current task (via |
56 | /// `cx.waker()`) to receive a notification when the object becomes |
57 | /// writable or is closed. |
58 | fn poll_write( |
59 | self: Pin<&mut Self>, |
60 | cx: &mut Context<'_>, |
61 | buf: &[u8], |
62 | ) -> Poll<Result<usize, io::Error>>; |
63 | |
64 | /// Attempts to flush the object, ensuring that any buffered data reach |
65 | /// their destination. |
66 | /// |
67 | /// On success, returns `Poll::Ready(Ok(()))`. |
68 | /// |
69 | /// If flushing cannot immediately complete, this method returns |
70 | /// `Poll::Pending` and arranges for the current task (via |
71 | /// `cx.waker()`) to receive a notification when the object can make |
72 | /// progress towards flushing. |
73 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>; |
74 | |
75 | /// Initiates or attempts to shut down this writer, returning success when |
76 | /// the I/O connection has completely shut down. |
77 | /// |
78 | /// This method is intended to be used for asynchronous shutdown of I/O |
79 | /// connections. For example this is suitable for implementing shutdown of a |
80 | /// TLS connection or calling `TcpStream::shutdown` on a proxied connection. |
81 | /// Protocols sometimes need to flush out final pieces of data or otherwise |
82 | /// perform a graceful shutdown handshake, reading/writing more data as |
83 | /// appropriate. This method is the hook for such protocols to implement the |
84 | /// graceful shutdown logic. |
85 | /// |
86 | /// This `shutdown` method is required by implementers of the |
87 | /// `AsyncWrite` trait. Wrappers typically just want to proxy this call |
88 | /// through to the wrapped type, and base types will typically implement |
89 | /// shutdown logic here or just return `Ok(().into())`. Note that if you're |
90 | /// wrapping an underlying `AsyncWrite` a call to `shutdown` implies that |
91 | /// transitively the entire stream has been shut down. After your wrapper's |
92 | /// shutdown logic has been executed you should shut down the underlying |
93 | /// stream. |
94 | /// |
95 | /// Invocation of a `shutdown` implies an invocation of `flush`. Once this |
96 | /// method returns `Ready` it implies that a flush successfully happened |
97 | /// before the shutdown happened. That is, callers don't need to call |
98 | /// `flush` before calling `shutdown`. They can rely that by calling |
99 | /// `shutdown` any pending buffered data will be written out. |
100 | /// |
101 | /// # Return value |
102 | /// |
103 | /// This function returns a `Poll<io::Result<()>>` classified as such: |
104 | /// |
105 | /// * `Poll::Ready(Ok(()))` - indicates that the connection was |
106 | /// successfully shut down and is now safe to deallocate/drop/close |
107 | /// resources associated with it. This method means that the current task |
108 | /// will no longer receive any notifications due to this method and the |
109 | /// I/O object itself is likely no longer usable. |
110 | /// |
111 | /// * `Poll::Pending` - indicates that shutdown is initiated but could |
112 | /// not complete just yet. This may mean that more I/O needs to happen to |
113 | /// continue this shutdown operation. The current task is scheduled to |
114 | /// receive a notification when it's otherwise ready to continue the |
115 | /// shutdown operation. When woken up this method should be called again. |
116 | /// |
117 | /// * `Poll::Ready(Err(e))` - indicates a fatal error has happened with shutdown, |
118 | /// indicating that the shutdown operation did not complete successfully. |
119 | /// This typically means that the I/O object is no longer usable. |
120 | /// |
121 | /// # Errors |
122 | /// |
123 | /// This function can return normal I/O errors through `Err`, described |
124 | /// above. Additionally this method may also render the underlying |
125 | /// `Write::write` method no longer usable (e.g. will return errors in the |
126 | /// future). It's recommended that once `shutdown` is called the |
127 | /// `write` method is no longer called. |
128 | /// |
129 | /// # Panics |
130 | /// |
131 | /// This function will panic if not called within the context of a future's |
132 | /// task. |
133 | fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>>; |
134 | |
135 | /// Like [`poll_write`], except that it writes from a slice of buffers. |
136 | /// |
137 | /// Data is copied from each buffer in order, with the final buffer |
138 | /// read from possibly being only partially consumed. This method must |
139 | /// behave as a call to [`write`] with the buffers concatenated would. |
140 | /// |
141 | /// The default implementation calls [`poll_write`] with either the first nonempty |
142 | /// buffer provided, or an empty one if none exists. |
143 | /// |
144 | /// On success, returns `Poll::Ready(Ok(num_bytes_written))`. |
145 | /// |
146 | /// If the object is not ready for writing, the method returns |
147 | /// `Poll::Pending` and arranges for the current task (via |
148 | /// `cx.waker()`) to receive a notification when the object becomes |
149 | /// writable or is closed. |
150 | /// |
151 | /// # Note |
152 | /// |
153 | /// This should be implemented as a single "atomic" write action. If any |
154 | /// data has been partially written, it is wrong to return an error or |
155 | /// pending. |
156 | /// |
157 | /// [`poll_write`]: AsyncWrite::poll_write |
158 | fn poll_write_vectored( |
159 | self: Pin<&mut Self>, |
160 | cx: &mut Context<'_>, |
161 | bufs: &[IoSlice<'_>], |
162 | ) -> Poll<Result<usize, io::Error>> { |
163 | let buf = bufs |
164 | .iter() |
165 | .find(|b| !b.is_empty()) |
166 | .map_or(&[][..], |b| &**b); |
167 | self.poll_write(cx, buf) |
168 | } |
169 | |
170 | /// Determines if this writer has an efficient [`poll_write_vectored`] |
171 | /// implementation. |
172 | /// |
173 | /// If a writer does not override the default [`poll_write_vectored`] |
174 | /// implementation, code using it may want to avoid the method all together |
175 | /// and coalesce writes into a single buffer for higher performance. |
176 | /// |
177 | /// The default implementation returns `false`. |
178 | /// |
179 | /// [`poll_write_vectored`]: AsyncWrite::poll_write_vectored |
180 | fn is_write_vectored(&self) -> bool { |
181 | false |
182 | } |
183 | } |
184 | |
185 | macro_rules! deref_async_write { |
186 | () => { |
187 | fn poll_write( |
188 | mut self: Pin<&mut Self>, |
189 | cx: &mut Context<'_>, |
190 | buf: &[u8], |
191 | ) -> Poll<io::Result<usize>> { |
192 | Pin::new(&mut **self).poll_write(cx, buf) |
193 | } |
194 | |
195 | fn poll_write_vectored( |
196 | mut self: Pin<&mut Self>, |
197 | cx: &mut Context<'_>, |
198 | bufs: &[IoSlice<'_>], |
199 | ) -> Poll<io::Result<usize>> { |
200 | Pin::new(&mut **self).poll_write_vectored(cx, bufs) |
201 | } |
202 | |
203 | fn is_write_vectored(&self) -> bool { |
204 | (**self).is_write_vectored() |
205 | } |
206 | |
207 | fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
208 | Pin::new(&mut **self).poll_flush(cx) |
209 | } |
210 | |
211 | fn poll_shutdown(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
212 | Pin::new(&mut **self).poll_shutdown(cx) |
213 | } |
214 | }; |
215 | } |
216 | |
217 | impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for Box<T> { |
218 | deref_async_write!(); |
219 | } |
220 | |
221 | impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for &mut T { |
222 | deref_async_write!(); |
223 | } |
224 | |
225 | impl<P> AsyncWrite for Pin<P> |
226 | where |
227 | P: DerefMut + Unpin, |
228 | P::Target: AsyncWrite, |
229 | { |
230 | fn poll_write( |
231 | self: Pin<&mut Self>, |
232 | cx: &mut Context<'_>, |
233 | buf: &[u8], |
234 | ) -> Poll<io::Result<usize>> { |
235 | self.get_mut().as_mut().poll_write(cx, buf) |
236 | } |
237 | |
238 | fn poll_write_vectored( |
239 | self: Pin<&mut Self>, |
240 | cx: &mut Context<'_>, |
241 | bufs: &[IoSlice<'_>], |
242 | ) -> Poll<io::Result<usize>> { |
243 | self.get_mut().as_mut().poll_write_vectored(cx, bufs) |
244 | } |
245 | |
246 | fn is_write_vectored(&self) -> bool { |
247 | (**self).is_write_vectored() |
248 | } |
249 | |
250 | fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
251 | self.get_mut().as_mut().poll_flush(cx) |
252 | } |
253 | |
254 | fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
255 | self.get_mut().as_mut().poll_shutdown(cx) |
256 | } |
257 | } |
258 | |
259 | impl AsyncWrite for Vec<u8> { |
260 | fn poll_write( |
261 | self: Pin<&mut Self>, |
262 | _cx: &mut Context<'_>, |
263 | buf: &[u8], |
264 | ) -> Poll<io::Result<usize>> { |
265 | self.get_mut().extend_from_slice(buf); |
266 | Poll::Ready(Ok(buf.len())) |
267 | } |
268 | |
269 | fn poll_write_vectored( |
270 | mut self: Pin<&mut Self>, |
271 | _: &mut Context<'_>, |
272 | bufs: &[IoSlice<'_>], |
273 | ) -> Poll<io::Result<usize>> { |
274 | Poll::Ready(io::Write::write_vectored(&mut *self, bufs)) |
275 | } |
276 | |
277 | fn is_write_vectored(&self) -> bool { |
278 | true |
279 | } |
280 | |
281 | fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
282 | Poll::Ready(Ok(())) |
283 | } |
284 | |
285 | fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
286 | Poll::Ready(Ok(())) |
287 | } |
288 | } |
289 | |
290 | impl AsyncWrite for io::Cursor<&mut [u8]> { |
291 | fn poll_write( |
292 | mut self: Pin<&mut Self>, |
293 | _: &mut Context<'_>, |
294 | buf: &[u8], |
295 | ) -> Poll<io::Result<usize>> { |
296 | Poll::Ready(io::Write::write(&mut *self, buf)) |
297 | } |
298 | |
299 | fn poll_write_vectored( |
300 | mut self: Pin<&mut Self>, |
301 | _: &mut Context<'_>, |
302 | bufs: &[IoSlice<'_>], |
303 | ) -> Poll<io::Result<usize>> { |
304 | Poll::Ready(io::Write::write_vectored(&mut *self, bufs)) |
305 | } |
306 | |
307 | fn is_write_vectored(&self) -> bool { |
308 | true |
309 | } |
310 | |
311 | fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> { |
312 | Poll::Ready(io::Write::flush(&mut *self)) |
313 | } |
314 | |
315 | fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
316 | self.poll_flush(cx) |
317 | } |
318 | } |
319 | |
320 | impl AsyncWrite for io::Cursor<&mut Vec<u8>> { |
321 | fn poll_write( |
322 | mut self: Pin<&mut Self>, |
323 | _: &mut Context<'_>, |
324 | buf: &[u8], |
325 | ) -> Poll<io::Result<usize>> { |
326 | Poll::Ready(io::Write::write(&mut *self, buf)) |
327 | } |
328 | |
329 | fn poll_write_vectored( |
330 | mut self: Pin<&mut Self>, |
331 | _: &mut Context<'_>, |
332 | bufs: &[IoSlice<'_>], |
333 | ) -> Poll<io::Result<usize>> { |
334 | Poll::Ready(io::Write::write_vectored(&mut *self, bufs)) |
335 | } |
336 | |
337 | fn is_write_vectored(&self) -> bool { |
338 | true |
339 | } |
340 | |
341 | fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> { |
342 | Poll::Ready(io::Write::flush(&mut *self)) |
343 | } |
344 | |
345 | fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
346 | self.poll_flush(cx) |
347 | } |
348 | } |
349 | |
350 | impl AsyncWrite for io::Cursor<Vec<u8>> { |
351 | fn poll_write( |
352 | mut self: Pin<&mut Self>, |
353 | _: &mut Context<'_>, |
354 | buf: &[u8], |
355 | ) -> Poll<io::Result<usize>> { |
356 | Poll::Ready(io::Write::write(&mut *self, buf)) |
357 | } |
358 | |
359 | fn poll_write_vectored( |
360 | mut self: Pin<&mut Self>, |
361 | _: &mut Context<'_>, |
362 | bufs: &[IoSlice<'_>], |
363 | ) -> Poll<io::Result<usize>> { |
364 | Poll::Ready(io::Write::write_vectored(&mut *self, bufs)) |
365 | } |
366 | |
367 | fn is_write_vectored(&self) -> bool { |
368 | true |
369 | } |
370 | |
371 | fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> { |
372 | Poll::Ready(io::Write::flush(&mut *self)) |
373 | } |
374 | |
375 | fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
376 | self.poll_flush(cx) |
377 | } |
378 | } |
379 | |
380 | impl AsyncWrite for io::Cursor<Box<[u8]>> { |
381 | fn poll_write( |
382 | mut self: Pin<&mut Self>, |
383 | _: &mut Context<'_>, |
384 | buf: &[u8], |
385 | ) -> Poll<io::Result<usize>> { |
386 | Poll::Ready(io::Write::write(&mut *self, buf)) |
387 | } |
388 | |
389 | fn poll_write_vectored( |
390 | mut self: Pin<&mut Self>, |
391 | _: &mut Context<'_>, |
392 | bufs: &[IoSlice<'_>], |
393 | ) -> Poll<io::Result<usize>> { |
394 | Poll::Ready(io::Write::write_vectored(&mut *self, bufs)) |
395 | } |
396 | |
397 | fn is_write_vectored(&self) -> bool { |
398 | true |
399 | } |
400 | |
401 | fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> { |
402 | Poll::Ready(io::Write::flush(&mut *self)) |
403 | } |
404 | |
405 | fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> { |
406 | self.poll_flush(cx) |
407 | } |
408 | } |
409 | |