Skip to main content

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}