1 //! Asynchronous I/O 2 //! 3 //! This crate contains the `AsyncRead`, `AsyncWrite`, `AsyncSeek`, and 4 //! `AsyncBufRead` traits, the asynchronous analogs to 5 //! `std::io::{Read, Write, Seek, BufRead}`. The primary difference is 6 //! that these traits integrate with the asynchronous task system. 7 //! 8 //! All items of this library are only available when the `std` feature of this 9 //! library is activated, and it is activated by default. 10 11 #![cfg_attr(all(feature = "read-initializer", feature = "std"), feature(read_initializer))] 12 13 #![cfg_attr(not(feature = "std"), no_std)] 14 15 #![warn(missing_docs, missing_debug_implementations, rust_2018_idioms, unreachable_pub)] 16 // It cannot be included in the published code because this lints have false positives in the minimum required version. 17 #![cfg_attr(test, warn(single_use_lifetimes))] 18 #![warn(clippy::all)] 19 #![doc(test(attr(deny(warnings), allow(dead_code, unused_assignments, unused_variables))))] 20 21 #![cfg_attr(docsrs, feature(doc_cfg))] 22 23 #[cfg(all(feature = "read-initializer", not(feature = "unstable")))] 24 compile_error!("The `read-initializer` feature requires the `unstable` feature as an explicit opt-in to unstable features"); 25 26 #[cfg(feature = "std")] 27 mod if_std { 28 use std::io; 29 use std::ops::DerefMut; 30 use std::pin::Pin; 31 use std::task::{Context, Poll}; 32 33 // Re-export some types from `std::io` so that users don't have to deal 34 // with conflicts when `use`ing `futures::io` and `std::io`. 35 #[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 36 #[doc(no_inline)] 37 pub use io::{Error, ErrorKind, Result, IoSlice, IoSliceMut, SeekFrom}; 38 #[cfg(feature = "read-initializer")] 39 #[cfg_attr(docsrs, doc(cfg(feature = "read-initializer")))] 40 #[doc(no_inline)] 41 #[allow(unreachable_pub)] // https://github.com/rust-lang/rust/issues/57411 42 pub use io::Initializer; 43 44 /// Read bytes asynchronously. 45 /// 46 /// This trait is analogous to the `std::io::Read` trait, but integrates 47 /// with the asynchronous task system. In particular, the `poll_read` 48 /// method, unlike `Read::read`, will automatically queue the current task 49 /// for wakeup and return if data is not yet available, rather than blocking 50 /// the calling thread. 51 pub trait AsyncRead { 52 /// Determines if this `AsyncRead`er can work with buffers of 53 /// uninitialized memory. 54 /// 55 /// The default implementation returns an initializer which will zero 56 /// buffers. 57 /// 58 /// This method is only available when the `read-initializer` feature of this 59 /// library is activated. 60 /// 61 /// # Safety 62 /// 63 /// This method is `unsafe` because an `AsyncRead`er could otherwise 64 /// return a non-zeroing `Initializer` from another `AsyncRead` type 65 /// without an `unsafe` block. 66 #[cfg(feature = "read-initializer")] 67 #[cfg_attr(docsrs, doc(cfg(feature = "read-initializer")))] 68 #[inline] initializer(&self) -> Initializer69 unsafe fn initializer(&self) -> Initializer { 70 Initializer::zeroing() 71 } 72 73 /// Attempt to read from the `AsyncRead` into `buf`. 74 /// 75 /// On success, returns `Poll::Ready(Ok(num_bytes_read))`. 76 /// 77 /// If no data is available for reading, the method returns 78 /// `Poll::Pending` and arranges for the current task (via 79 /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes 80 /// readable or is closed. 81 /// 82 /// # Implementation 83 /// 84 /// This function may not return errors of kind `WouldBlock` or 85 /// `Interrupted`. Implementations must convert `WouldBlock` into 86 /// `Poll::Pending` and either internally retry or convert 87 /// `Interrupted` into another error kind. poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>>88 fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) 89 -> Poll<Result<usize>>; 90 91 /// Attempt to read from the `AsyncRead` into `bufs` using vectored 92 /// IO operations. 93 /// 94 /// This method is similar to `poll_read`, but allows data to be read 95 /// into multiple buffers using a single operation. 96 /// 97 /// On success, returns `Poll::Ready(Ok(num_bytes_read))`. 98 /// 99 /// If no data is available for reading, the method returns 100 /// `Poll::Pending` and arranges for the current task (via 101 /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes 102 /// readable or is closed. 103 /// By default, this method delegates to using `poll_read` on the first 104 /// nonempty buffer in `bufs`, or an empty one if none exists. Objects which 105 /// support vectored IO should override this method. 106 /// 107 /// # Implementation 108 /// 109 /// This function may not return errors of kind `WouldBlock` or 110 /// `Interrupted`. Implementations must convert `WouldBlock` into 111 /// `Poll::Pending` and either internally retry or convert 112 /// `Interrupted` into another error kind. poll_read_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>]) -> Poll<Result<usize>>113 fn poll_read_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>]) 114 -> Poll<Result<usize>> 115 { 116 for b in bufs { 117 if !b.is_empty() { 118 return self.poll_read(cx, b); 119 } 120 } 121 122 self.poll_read(cx, &mut []) 123 } 124 } 125 126 /// Write bytes asynchronously. 127 /// 128 /// This trait is analogous to the `std::io::Write` trait, but integrates 129 /// with the asynchronous task system. In particular, the `poll_write` 130 /// method, unlike `Write::write`, will automatically queue the current task 131 /// for wakeup and return if the writer cannot take more data, rather than blocking 132 /// the calling thread. 133 pub trait AsyncWrite { 134 /// Attempt to write bytes from `buf` into the object. 135 /// 136 /// On success, returns `Poll::Ready(Ok(num_bytes_written))`. 137 /// 138 /// If the object is not ready for writing, the method returns 139 /// `Poll::Pending` and arranges for the current task (via 140 /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes 141 /// writable or is closed. 142 /// 143 /// # Implementation 144 /// 145 /// This function may not return errors of kind `WouldBlock` or 146 /// `Interrupted`. Implementations must convert `WouldBlock` into 147 /// `Poll::Pending` and either internally retry or convert 148 /// `Interrupted` into another error kind. 149 /// 150 /// `poll_write` must try to make progress by flushing the underlying object if 151 /// that is the only way the underlying object can become writable again. poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>>152 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) 153 -> Poll<Result<usize>>; 154 155 /// Attempt to write bytes from `bufs` into the object using vectored 156 /// IO operations. 157 /// 158 /// This method is similar to `poll_write`, but allows data from multiple buffers to be written 159 /// using a single operation. 160 /// 161 /// On success, returns `Poll::Ready(Ok(num_bytes_written))`. 162 /// 163 /// If the object is not ready for writing, the method returns 164 /// `Poll::Pending` and arranges for the current task (via 165 /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes 166 /// writable or is closed. 167 /// 168 /// By default, this method delegates to using `poll_write` on the first 169 /// nonempty buffer in `bufs`, or an empty one if none exists. Objects which 170 /// support vectored IO should override this method. 171 /// 172 /// # Implementation 173 /// 174 /// This function may not return errors of kind `WouldBlock` or 175 /// `Interrupted`. Implementations must convert `WouldBlock` into 176 /// `Poll::Pending` and either internally retry or convert 177 /// `Interrupted` into another error kind. poll_write_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>]) -> Poll<Result<usize>>178 fn poll_write_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>]) 179 -> Poll<Result<usize>> 180 { 181 for b in bufs { 182 if !b.is_empty() { 183 return self.poll_write(cx, b); 184 } 185 } 186 187 self.poll_write(cx, &[]) 188 } 189 190 /// Attempt to flush the object, ensuring that any buffered data reach 191 /// their destination. 192 /// 193 /// On success, returns `Poll::Ready(Ok(()))`. 194 /// 195 /// If flushing cannot immediately complete, this method returns 196 /// `Poll::Pending` and arranges for the current task (via 197 /// `cx.waker().wake_by_ref()`) to receive a notification when the object can make 198 /// progress towards flushing. 199 /// 200 /// # Implementation 201 /// 202 /// This function may not return errors of kind `WouldBlock` or 203 /// `Interrupted`. Implementations must convert `WouldBlock` into 204 /// `Poll::Pending` and either internally retry or convert 205 /// `Interrupted` into another error kind. 206 /// 207 /// It only makes sense to do anything here if you actually buffer data. poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>208 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>; 209 210 /// Attempt to close the object. 211 /// 212 /// On success, returns `Poll::Ready(Ok(()))`. 213 /// 214 /// If closing cannot immediately complete, this function returns 215 /// `Poll::Pending` and arranges for the current task (via 216 /// `cx.waker().wake_by_ref()`) to receive a notification when the object can make 217 /// progress towards closing. 218 /// 219 /// # Implementation 220 /// 221 /// This function may not return errors of kind `WouldBlock` or 222 /// `Interrupted`. Implementations must convert `WouldBlock` into 223 /// `Poll::Pending` and either internally retry or convert 224 /// `Interrupted` into another error kind. poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>225 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>; 226 } 227 228 /// Seek bytes asynchronously. 229 /// 230 /// This trait is analogous to the `std::io::Seek` trait, but integrates 231 /// with the asynchronous task system. In particular, the `poll_seek` 232 /// method, unlike `Seek::seek`, will automatically queue the current task 233 /// for wakeup and return if data is not yet available, rather than blocking 234 /// the calling thread. 235 pub trait AsyncSeek { 236 /// Attempt to seek to an offset, in bytes, in a stream. 237 /// 238 /// A seek beyond the end of a stream is allowed, but behavior is defined 239 /// by the implementation. 240 /// 241 /// If the seek operation completed successfully, 242 /// this method returns the new position from the start of the stream. 243 /// That position can be used later with [`SeekFrom::Start`]. 244 /// 245 /// # Errors 246 /// 247 /// Seeking to a negative offset is considered an error. 248 /// 249 /// # Implementation 250 /// 251 /// This function may not return errors of kind `WouldBlock` or 252 /// `Interrupted`. Implementations must convert `WouldBlock` into 253 /// `Poll::Pending` and either internally retry or convert 254 /// `Interrupted` into another error kind. poll_seek(self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom) -> Poll<Result<u64>>255 fn poll_seek(self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom) 256 -> Poll<Result<u64>>; 257 } 258 259 /// Read bytes asynchronously. 260 /// 261 /// This trait is analogous to the `std::io::BufRead` trait, but integrates 262 /// with the asynchronous task system. In particular, the `poll_fill_buf` 263 /// method, unlike `BufRead::fill_buf`, will automatically queue the current task 264 /// for wakeup and return if data is not yet available, rather than blocking 265 /// the calling thread. 266 pub trait AsyncBufRead: AsyncRead { 267 /// Attempt to return the contents of the internal buffer, filling it with more data 268 /// from the inner reader if it is empty. 269 /// 270 /// On success, returns `Poll::Ready(Ok(buf))`. 271 /// 272 /// If no data is available for reading, the method returns 273 /// `Poll::Pending` and arranges for the current task (via 274 /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes 275 /// readable or is closed. 276 /// 277 /// This function is a lower-level call. It needs to be paired with the 278 /// [`consume`] method to function properly. When calling this 279 /// method, none of the contents will be "read" in the sense that later 280 /// calling [`poll_read`] may return the same contents. As such, [`consume`] must 281 /// be called with the number of bytes that are consumed from this buffer to 282 /// ensure that the bytes are never returned twice. 283 /// 284 /// [`poll_read`]: AsyncRead::poll_read 285 /// [`consume`]: AsyncBufRead::consume 286 /// 287 /// An empty buffer returned indicates that the stream has reached EOF. 288 /// 289 /// # Implementation 290 /// 291 /// This function may not return errors of kind `WouldBlock` or 292 /// `Interrupted`. Implementations must convert `WouldBlock` into 293 /// `Poll::Pending` and either internally retry or convert 294 /// `Interrupted` into another error kind. poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>>295 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) 296 -> Poll<Result<&[u8]>>; 297 298 /// Tells this buffer that `amt` bytes have been consumed from the buffer, 299 /// so they should no longer be returned in calls to [`poll_read`]. 300 /// 301 /// This function is a lower-level call. It needs to be paired with the 302 /// [`poll_fill_buf`] method to function properly. This function does 303 /// not perform any I/O, it simply informs this object that some amount of 304 /// its buffer, returned from [`poll_fill_buf`], has been consumed and should 305 /// no longer be returned. As such, this function may do odd things if 306 /// [`poll_fill_buf`] isn't called before calling it. 307 /// 308 /// The `amt` must be `<=` the number of bytes in the buffer returned by 309 /// [`poll_fill_buf`]. 310 /// 311 /// [`poll_read`]: AsyncRead::poll_read 312 /// [`poll_fill_buf`]: AsyncBufRead::poll_fill_buf consume(self: Pin<&mut Self>, amt: usize)313 fn consume(self: Pin<&mut Self>, amt: usize); 314 } 315 316 macro_rules! deref_async_read { 317 () => { 318 #[cfg(feature = "read-initializer")] 319 unsafe fn initializer(&self) -> Initializer { 320 (**self).initializer() 321 } 322 323 fn poll_read(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) 324 -> Poll<Result<usize>> 325 { 326 Pin::new(&mut **self).poll_read(cx, buf) 327 } 328 329 fn poll_read_vectored(mut self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>]) 330 -> Poll<Result<usize>> 331 { 332 Pin::new(&mut **self).poll_read_vectored(cx, bufs) 333 } 334 } 335 } 336 337 impl<T: ?Sized + AsyncRead + Unpin> AsyncRead for Box<T> { 338 deref_async_read!(); 339 } 340 341 impl<T: ?Sized + AsyncRead + Unpin> AsyncRead for &mut T { 342 deref_async_read!(); 343 } 344 345 impl<P> AsyncRead for Pin<P> 346 where 347 P: DerefMut + Unpin, 348 P::Target: AsyncRead, 349 { 350 #[cfg(feature = "read-initializer")] initializer(&self) -> Initializer351 unsafe fn initializer(&self) -> Initializer { 352 (**self).initializer() 353 } 354 poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<Result<usize>>355 fn poll_read(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &mut [u8]) 356 -> Poll<Result<usize>> 357 { 358 self.get_mut().as_mut().poll_read(cx, buf) 359 } 360 poll_read_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>]) -> Poll<Result<usize>>361 fn poll_read_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>]) 362 -> Poll<Result<usize>> 363 { 364 self.get_mut().as_mut().poll_read_vectored(cx, bufs) 365 } 366 } 367 368 macro_rules! delegate_async_read_to_stdio { 369 () => { 370 #[cfg(feature = "read-initializer")] 371 unsafe fn initializer(&self) -> Initializer { 372 io::Read::initializer(self) 373 } 374 375 fn poll_read(mut self: Pin<&mut Self>, _: &mut Context<'_>, buf: &mut [u8]) 376 -> Poll<Result<usize>> 377 { 378 Poll::Ready(io::Read::read(&mut *self, buf)) 379 } 380 381 fn poll_read_vectored(mut self: Pin<&mut Self>, _: &mut Context<'_>, bufs: &mut [IoSliceMut<'_>]) 382 -> Poll<Result<usize>> 383 { 384 Poll::Ready(io::Read::read_vectored(&mut *self, bufs)) 385 } 386 } 387 } 388 389 impl AsyncRead for &[u8] { 390 delegate_async_read_to_stdio!(); 391 } 392 393 macro_rules! deref_async_write { 394 () => { 395 fn poll_write(mut self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) 396 -> Poll<Result<usize>> 397 { 398 Pin::new(&mut **self).poll_write(cx, buf) 399 } 400 401 fn poll_write_vectored(mut self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>]) 402 -> Poll<Result<usize>> 403 { 404 Pin::new(&mut **self).poll_write_vectored(cx, bufs) 405 } 406 407 fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { 408 Pin::new(&mut **self).poll_flush(cx) 409 } 410 411 fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { 412 Pin::new(&mut **self).poll_close(cx) 413 } 414 } 415 } 416 417 impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for Box<T> { 418 deref_async_write!(); 419 } 420 421 impl<T: ?Sized + AsyncWrite + Unpin> AsyncWrite for &mut T { 422 deref_async_write!(); 423 } 424 425 impl<P> AsyncWrite for Pin<P> 426 where 427 P: DerefMut + Unpin, 428 P::Target: AsyncWrite, 429 { poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>>430 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) 431 -> Poll<Result<usize>> 432 { 433 self.get_mut().as_mut().poll_write(cx, buf) 434 } 435 poll_write_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>]) -> Poll<Result<usize>>436 fn poll_write_vectored(self: Pin<&mut Self>, cx: &mut Context<'_>, bufs: &[IoSlice<'_>]) 437 -> Poll<Result<usize>> 438 { 439 self.get_mut().as_mut().poll_write_vectored(cx, bufs) 440 } 441 poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>442 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { 443 self.get_mut().as_mut().poll_flush(cx) 444 } 445 poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>>446 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { 447 self.get_mut().as_mut().poll_close(cx) 448 } 449 } 450 451 macro_rules! delegate_async_write_to_stdio { 452 () => { 453 fn poll_write(mut self: Pin<&mut Self>, _: &mut Context<'_>, buf: &[u8]) 454 -> Poll<Result<usize>> 455 { 456 Poll::Ready(io::Write::write(&mut *self, buf)) 457 } 458 459 fn poll_write_vectored(mut self: Pin<&mut Self>, _: &mut Context<'_>, bufs: &[IoSlice<'_>]) 460 -> Poll<Result<usize>> 461 { 462 Poll::Ready(io::Write::write_vectored(&mut *self, bufs)) 463 } 464 465 fn poll_flush(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Result<()>> { 466 Poll::Ready(io::Write::flush(&mut *self)) 467 } 468 469 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> { 470 self.poll_flush(cx) 471 } 472 } 473 } 474 475 impl AsyncWrite for Vec<u8> { 476 delegate_async_write_to_stdio!(); 477 } 478 479 macro_rules! deref_async_seek { 480 () => { 481 fn poll_seek(mut self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom) 482 -> Poll<Result<u64>> 483 { 484 Pin::new(&mut **self).poll_seek(cx, pos) 485 } 486 } 487 } 488 489 impl<T: ?Sized + AsyncSeek + Unpin> AsyncSeek for Box<T> { 490 deref_async_seek!(); 491 } 492 493 impl<T: ?Sized + AsyncSeek + Unpin> AsyncSeek for &mut T { 494 deref_async_seek!(); 495 } 496 497 impl<P> AsyncSeek for Pin<P> 498 where 499 P: DerefMut + Unpin, 500 P::Target: AsyncSeek, 501 { poll_seek(self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom) -> Poll<Result<u64>>502 fn poll_seek(self: Pin<&mut Self>, cx: &mut Context<'_>, pos: SeekFrom) 503 -> Poll<Result<u64>> 504 { 505 self.get_mut().as_mut().poll_seek(cx, pos) 506 } 507 } 508 509 macro_rules! deref_async_buf_read { 510 () => { 511 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) 512 -> Poll<Result<&[u8]>> 513 { 514 Pin::new(&mut **self.get_mut()).poll_fill_buf(cx) 515 } 516 517 fn consume(mut self: Pin<&mut Self>, amt: usize) { 518 Pin::new(&mut **self).consume(amt) 519 } 520 } 521 } 522 523 impl<T: ?Sized + AsyncBufRead + Unpin> AsyncBufRead for Box<T> { 524 deref_async_buf_read!(); 525 } 526 527 impl<T: ?Sized + AsyncBufRead + Unpin> AsyncBufRead for &mut T { 528 deref_async_buf_read!(); 529 } 530 531 impl<P> AsyncBufRead for Pin<P> 532 where 533 P: DerefMut + Unpin, 534 P::Target: AsyncBufRead, 535 { poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<&[u8]>>536 fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) 537 -> Poll<Result<&[u8]>> 538 { 539 self.get_mut().as_mut().poll_fill_buf(cx) 540 } 541 consume(self: Pin<&mut Self>, amt: usize)542 fn consume(self: Pin<&mut Self>, amt: usize) { 543 self.get_mut().as_mut().consume(amt) 544 } 545 } 546 547 macro_rules! delegate_async_buf_read_to_stdio { 548 () => { 549 fn poll_fill_buf(self: Pin<&mut Self>, _: &mut Context<'_>) 550 -> Poll<Result<&[u8]>> 551 { 552 Poll::Ready(io::BufRead::fill_buf(self.get_mut())) 553 } 554 555 fn consume(self: Pin<&mut Self>, amt: usize) { 556 io::BufRead::consume(self.get_mut(), amt) 557 } 558 } 559 } 560 561 impl AsyncBufRead for &[u8] { 562 delegate_async_buf_read_to_stdio!(); 563 } 564 } 565 566 #[cfg(feature = "std")] 567 pub use self::if_std::*; 568