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