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