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    fn poll_write(
255        self: Pin<&mut Self>,
256        _cx: &mut Context<'_>,
257        buf: &[u8],
258    ) -> Poll<io::Result<usize>> {
259        self.get_mut().extend_from_slice(buf);
260        Poll::Ready(Ok(buf.len()))
261    }
262
263    fn poll_write_vectored(
264        mut self: Pin<&mut Self>,
265        _: &mut Context<'_>,
266        bufs: &[IoSlice<'_>],
267    ) -> Poll<io::Result<usize>> {
268        Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
269    }
270
271    fn is_write_vectored(&self) -> bool {
272        true
273    }
274
275    fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
276        Poll::Ready(Ok(()))
277    }
278
279    fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<io::Result<()>> {
280        Poll::Ready(Ok(()))
281    }
282}
283
284impl AsyncWrite for io::Cursor<&mut [u8]> {
285    fn poll_write(
286        mut self: Pin<&mut Self>,
287        _: &mut Context<'_>,
288        buf: &[u8],
289    ) -> Poll<io::Result<usize>> {
290        Poll::Ready(io::Write::write(&mut *self, buf))
291    }
292
293    fn poll_write_vectored(
294        mut self: Pin<&mut Self>,
295        _: &mut Context<'_>,
296        bufs: &[IoSlice<'_>],
297    ) -> Poll<io::Result<usize>> {
298        Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
299    }
300
301    fn is_write_vectored(&self) -> bool {
302        true
303    }
304
305    fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
306        Poll::Ready(io::Write::flush(&mut *self))
307    }
308
309    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
310        self.poll_flush(cx)
311    }
312}
313
314impl AsyncWrite for io::Cursor<&mut Vec<u8>> {
315    fn poll_write(
316        mut self: Pin<&mut Self>,
317        _: &mut Context<'_>,
318        buf: &[u8],
319    ) -> Poll<io::Result<usize>> {
320        Poll::Ready(io::Write::write(&mut *self, buf))
321    }
322
323    fn poll_write_vectored(
324        mut self: Pin<&mut Self>,
325        _: &mut Context<'_>,
326        bufs: &[IoSlice<'_>],
327    ) -> Poll<io::Result<usize>> {
328        Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
329    }
330
331    fn is_write_vectored(&self) -> bool {
332        true
333    }
334
335    fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
336        Poll::Ready(io::Write::flush(&mut *self))
337    }
338
339    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
340        self.poll_flush(cx)
341    }
342}
343
344impl AsyncWrite for io::Cursor<Vec<u8>> {
345    fn poll_write(
346        mut self: Pin<&mut Self>,
347        _: &mut Context<'_>,
348        buf: &[u8],
349    ) -> Poll<io::Result<usize>> {
350        Poll::Ready(io::Write::write(&mut *self, buf))
351    }
352
353    fn poll_write_vectored(
354        mut self: Pin<&mut Self>,
355        _: &mut Context<'_>,
356        bufs: &[IoSlice<'_>],
357    ) -> Poll<io::Result<usize>> {
358        Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
359    }
360
361    fn is_write_vectored(&self) -> bool {
362        true
363    }
364
365    fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
366        Poll::Ready(io::Write::flush(&mut *self))
367    }
368
369    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
370        self.poll_flush(cx)
371    }
372}
373
374impl AsyncWrite for io::Cursor<Box<[u8]>> {
375    fn poll_write(
376        mut self: Pin<&mut Self>,
377        _: &mut Context<'_>,
378        buf: &[u8],
379    ) -> Poll<io::Result<usize>> {
380        Poll::Ready(io::Write::write(&mut *self, buf))
381    }
382
383    fn poll_write_vectored(
384        mut self: Pin<&mut Self>,
385        _: &mut Context<'_>,
386        bufs: &[IoSlice<'_>],
387    ) -> Poll<io::Result<usize>> {
388        Poll::Ready(io::Write::write_vectored(&mut *self, bufs))
389    }
390
391    fn is_write_vectored(&self) -> bool {
392        true
393    }
394
395    fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<io::Result<()>> {
396        Poll::Ready(io::Write::flush(&mut *self))
397    }
398
399    fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<()>> {
400        self.poll_flush(cx)
401    }
402}