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