@@ -266,6 +266,63 @@ mod if_std {
266
266
-> Poll < Result < u64 > > ;
267
267
}
268
268
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
+
269
326
macro_rules! deref_async_read {
270
327
( ) => {
271
328
unsafe fn initializer( & self ) -> Initializer {
@@ -340,6 +397,10 @@ mod if_std {
340
397
unsafe_delegate_async_read_to_stdio ! ( ) ;
341
398
}
342
399
400
+ impl AsyncRead for StdIo :: Empty {
401
+ unsafe_delegate_async_read_to_stdio ! ( ) ;
402
+ }
403
+
343
404
impl < T : AsRef < [ u8 ] > + Unpin > AsyncRead for StdIo :: Cursor < T > {
344
405
unsafe_delegate_async_read_to_stdio ! ( ) ;
345
406
}
@@ -499,6 +560,70 @@ mod if_std {
499
560
impl < T : AsRef < [ u8 ] > + Unpin > AsyncSeek for StdIo :: Cursor < T > {
500
561
delegate_async_seek_to_stdio ! ( ) ;
501
562
}
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
+ }
502
627
}
503
628
504
629
#[ cfg( feature = "std" ) ]
0 commit comments