@@ -266,6 +266,63 @@ mod if_std {
266266 -> Poll < Result < u64 > > ;
267267 }
268268
269+ /// Read bytes asynchronously.
270+ ///
271+ /// This trait is analogous to the `std::io::BufRead` trait, but integrates
272+ /// with the asynchronous task system. In particular, the `poll_fill_buf`
273+ /// method, unlike `BufRead::fill_buf`, will automatically queue the current task
274+ /// for wakeup and return if data is not yet available, rather than blocking
275+ /// the calling thread.
276+ pub trait AsyncBufRead : AsyncRead {
277+ /// Attempt to return the contents of the internal buffer, filling it with more data
278+ /// from the inner reader if it is empty.
279+ ///
280+ /// On success, returns `Poll::Ready(Ok(buf))`.
281+ ///
282+ /// If no data is available for reading, the method returns
283+ /// `Poll::Pending` and arranges for the current task (via
284+ /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes
285+ /// readable or is closed.
286+ ///
287+ /// This function is a lower-level call. It needs to be paired with the
288+ /// [`consume`] method to function properly. When calling this
289+ /// method, none of the contents will be "read" in the sense that later
290+ /// calling [`poll_read`] may return the same contents. As such, [`consume`] must
291+ /// be called with the number of bytes that are consumed from this buffer to
292+ /// ensure that the bytes are never returned twice.
293+ ///
294+ /// [`poll_read`]: AsyncRead::poll_read
295+ /// [`consume`]: AsyncBufRead::consume
296+ ///
297+ /// An empty buffer returned indicates that the stream has reached EOF.
298+ ///
299+ /// # Implementation
300+ ///
301+ /// This function may not return errors of kind `WouldBlock` or
302+ /// `Interrupted`. Implementations must convert `WouldBlock` into
303+ /// `Poll::Pending` and either internally retry or convert
304+ /// `Interrupted` into another error kind.
305+ fn poll_fill_buf < ' a > ( self : Pin < & ' a mut Self > , cx : & mut Context < ' _ > )
306+ -> Poll < Result < & ' a [ u8 ] > > ;
307+
308+ /// Tells this buffer that `amt` bytes have been consumed from the buffer,
309+ /// so they should no longer be returned in calls to [`poll_read`].
310+ ///
311+ /// This function is a lower-level call. It needs to be paired with the
312+ /// [`poll_fill_buf`] method to function properly. This function does
313+ /// not perform any I/O, it simply informs this object that some amount of
314+ /// its buffer, returned from [`poll_fill_buf`], has been consumed and should
315+ /// no longer be returned. As such, this function may do odd things if
316+ /// [`poll_fill_buf`] isn't called before calling it.
317+ ///
318+ /// The `amt` must be `<=` the number of bytes in the buffer returned by
319+ /// [`poll_fill_buf`].
320+ ///
321+ /// [`poll_read`]: AsyncRead::poll_read
322+ /// [`poll_fill_buf`]: AsyncBufRead::poll_fill_buf
323+ fn consume ( self : Pin < & mut Self > , amt : usize ) ;
324+ }
325+
269326 macro_rules! deref_async_read {
270327 ( ) => {
271328 unsafe fn initializer( & self ) -> Initializer {
@@ -340,6 +397,10 @@ mod if_std {
340397 unsafe_delegate_async_read_to_stdio ! ( ) ;
341398 }
342399
400+ impl AsyncRead for StdIo :: Empty {
401+ unsafe_delegate_async_read_to_stdio ! ( ) ;
402+ }
403+
343404 impl < T : AsRef < [ u8 ] > + Unpin > AsyncRead for StdIo :: Cursor < T > {
344405 unsafe_delegate_async_read_to_stdio ! ( ) ;
345406 }
@@ -499,6 +560,70 @@ mod if_std {
499560 impl < T : AsRef < [ u8 ] > + Unpin > AsyncSeek for StdIo :: Cursor < T > {
500561 delegate_async_seek_to_stdio ! ( ) ;
501562 }
563+
564+ macro_rules! deref_async_buf_read {
565+ ( ) => {
566+ fn poll_fill_buf<' a>( self : Pin <& ' a mut Self >, cx: & mut Context <' _>)
567+ -> Poll <Result <& ' a [ u8 ] >>
568+ {
569+ Pin :: new( & mut * * self . get_mut( ) ) . poll_fill_buf( cx)
570+ }
571+
572+ fn consume( self : Pin <& mut Self >, amt: usize ) {
573+ Pin :: new( & mut * * self . get_mut( ) ) . consume( amt)
574+ }
575+ }
576+ }
577+
578+ impl < T : ?Sized + AsyncBufRead + Unpin > AsyncBufRead for Box < T > {
579+ deref_async_buf_read ! ( ) ;
580+ }
581+
582+ impl < T : ?Sized + AsyncBufRead + Unpin > AsyncBufRead for & mut T {
583+ deref_async_buf_read ! ( ) ;
584+ }
585+
586+ impl < P > AsyncBufRead for Pin < P >
587+ where
588+ P : DerefMut + Unpin ,
589+ P :: Target : AsyncBufRead ,
590+ {
591+ fn poll_fill_buf < ' a > ( self : Pin < & ' a mut Self > , cx : & mut Context < ' _ > )
592+ -> Poll < Result < & ' a [ u8 ] > >
593+ {
594+ self . get_mut ( ) . as_mut ( ) . poll_fill_buf ( cx)
595+ }
596+
597+ fn consume ( self : Pin < & mut Self > , amt : usize ) {
598+ self . get_mut ( ) . as_mut ( ) . consume ( amt)
599+ }
600+ }
601+
602+ macro_rules! delegate_async_buf_read_to_stdio {
603+ ( ) => {
604+ fn poll_fill_buf<' a>( self : Pin <& ' a mut Self >, _: & mut Context <' _>)
605+ -> Poll <Result <& ' a [ u8 ] >>
606+ {
607+ Poll :: Ready ( StdIo :: BufRead :: fill_buf( self . get_mut( ) ) )
608+ }
609+
610+ fn consume( self : Pin <& mut Self >, amt: usize ) {
611+ StdIo :: BufRead :: consume( self . get_mut( ) , amt)
612+ }
613+ }
614+ }
615+
616+ impl AsyncBufRead for & [ u8 ] {
617+ delegate_async_buf_read_to_stdio ! ( ) ;
618+ }
619+
620+ impl AsyncBufRead for StdIo :: Empty {
621+ delegate_async_buf_read_to_stdio ! ( ) ;
622+ }
623+
624+ impl < T : AsRef < [ u8 ] > + Unpin > AsyncBufRead for StdIo :: Cursor < T > {
625+ delegate_async_buf_read_to_stdio ! ( ) ;
626+ }
502627}
503628
504629#[ cfg( feature = "std" ) ]
0 commit comments