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}