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