@@ -241,6 +241,63 @@ mod if_std {
241
241
fn poll_close ( self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Result < ( ) > > ;
242
242
}
243
243
244
+ /// Read bytes asynchronously.
245
+ ///
246
+ /// This trait is analogous to the `std::io::BufRead` trait, but integrates
247
+ /// with the asynchronous task system. In particular, the `poll_fill_buf`
248
+ /// method, unlike `BufRead::fill_buf`, will automatically queue the current task
249
+ /// for wakeup and return if data is not yet available, rather than blocking
250
+ /// the calling thread.
251
+ pub trait AsyncBufRead : AsyncRead {
252
+ /// Attempt to return the contents of the internal buffer, filling it with more data
253
+ /// from the inner reader if it is empty.
254
+ ///
255
+ /// On success, returns `Poll::Ready(Ok(buf))`.
256
+ ///
257
+ /// If no data is available for reading, the method returns
258
+ /// `Poll::Pending` and arranges for the current task (via
259
+ /// `cx.waker().wake_by_ref()`) to receive a notification when the object becomes
260
+ /// readable or is closed.
261
+ ///
262
+ /// This function is a lower-level call. It needs to be paired with the
263
+ /// [`consume`] method to function properly. When calling this
264
+ /// method, none of the contents will be "read" in the sense that later
265
+ /// calling [`poll_read`] may return the same contents. As such, [`consume`] must
266
+ /// be called with the number of bytes that are consumed from this buffer to
267
+ /// ensure that the bytes are never returned twice.
268
+ ///
269
+ /// [`poll_read`]: AsyncRead::poll_read
270
+ /// [`consume`]: AsyncBufRead::consume
271
+ ///
272
+ /// An empty buffer returned indicates that the stream has reached EOF.
273
+ ///
274
+ /// # Implementation
275
+ ///
276
+ /// This function may not return errors of kind `WouldBlock` or
277
+ /// `Interrupted`. Implementations must convert `WouldBlock` into
278
+ /// `Poll::Pending` and either internally retry or convert
279
+ /// `Interrupted` into another error kind.
280
+ fn poll_fill_buf < ' a > ( self : Pin < & ' a mut Self > , cx : & mut Context < ' _ > )
281
+ -> Poll < Result < & ' a [ u8 ] > > ;
282
+
283
+ /// Tells this buffer that `amt` bytes have been consumed from the buffer,
284
+ /// so they should no longer be returned in calls to [`poll_read`].
285
+ ///
286
+ /// This function is a lower-level call. It needs to be paired with the
287
+ /// [`poll_fill_buf`] method to function properly. This function does
288
+ /// not perform any I/O, it simply informs this object that some amount of
289
+ /// its buffer, returned from [`poll_fill_buf`], has been consumed and should
290
+ /// no longer be returned. As such, this function may do odd things if
291
+ /// [`poll_fill_buf`] isn't called before calling it.
292
+ ///
293
+ /// The `amt` must be `<=` the number of bytes in the buffer returned by
294
+ /// [`poll_fill_buf`].
295
+ ///
296
+ /// [`poll_read`]: AsyncRead::poll_read
297
+ /// [`poll_fill_buf`]: AsyncBufRead::poll_fill_buf
298
+ fn consume ( & mut self , amt : usize ) ;
299
+ }
300
+
244
301
macro_rules! deref_async_read {
245
302
( ) => {
246
303
unsafe fn initializer( & self ) -> Initializer {
@@ -315,6 +372,10 @@ mod if_std {
315
372
unsafe_delegate_async_read_to_stdio ! ( ) ;
316
373
}
317
374
375
+ impl AsyncRead for StdIo :: Empty {
376
+ unsafe_delegate_async_read_to_stdio ! ( ) ;
377
+ }
378
+
318
379
impl < T : AsRef < [ u8 ] > + Unpin > AsyncRead for StdIo :: Cursor < T > {
319
380
unsafe_delegate_async_read_to_stdio ! ( ) ;
320
381
}
@@ -429,6 +490,70 @@ mod if_std {
429
490
impl AsyncWrite for StdIo :: Sink {
430
491
delegate_async_write_to_stdio ! ( ) ;
431
492
}
493
+
494
+ macro_rules! deref_async_buf_read {
495
+ ( ) => {
496
+ fn poll_fill_buf<' a>( self : Pin <& ' a mut Self >, cx: & mut Context <' _>)
497
+ -> Poll <Result <& ' a [ u8 ] >>
498
+ {
499
+ Pin :: new( & mut * * self . get_mut( ) ) . poll_fill_buf( cx)
500
+ }
501
+
502
+ fn consume( & mut self , amt: usize ) {
503
+ T :: consume( & mut * * self , amt)
504
+ }
505
+ }
506
+ }
507
+
508
+ impl < T : ?Sized + AsyncBufRead + Unpin > AsyncBufRead for Box < T > {
509
+ deref_async_buf_read ! ( ) ;
510
+ }
511
+
512
+ impl < T : ?Sized + AsyncBufRead + Unpin > AsyncBufRead for & mut T {
513
+ deref_async_buf_read ! ( ) ;
514
+ }
515
+
516
+ impl < P > AsyncBufRead for Pin < P >
517
+ where
518
+ P : DerefMut + Unpin ,
519
+ P :: Target : AsyncBufRead + Unpin ,
520
+ {
521
+ fn poll_fill_buf < ' a > ( self : Pin < & ' a mut Self > , cx : & mut Context < ' _ > )
522
+ -> Poll < Result < & ' a [ u8 ] > >
523
+ {
524
+ self . get_mut ( ) . as_mut ( ) . poll_fill_buf ( cx)
525
+ }
526
+
527
+ fn consume ( & mut self , amt : usize ) {
528
+ <P :: Target as AsyncBufRead >:: consume ( self . as_mut ( ) . get_mut ( ) , amt)
529
+ }
530
+ }
531
+
532
+ macro_rules! delegate_async_buf_read_to_stdio {
533
+ ( ) => {
534
+ fn poll_fill_buf<' a>( self : Pin <& ' a mut Self >, _: & mut Context <' _>)
535
+ -> Poll <Result <& ' a [ u8 ] >>
536
+ {
537
+ Poll :: Ready ( StdIo :: BufRead :: fill_buf( self . get_mut( ) ) )
538
+ }
539
+
540
+ fn consume( & mut self , amt: usize ) {
541
+ StdIo :: BufRead :: consume( self , amt)
542
+ }
543
+ }
544
+ }
545
+
546
+ impl AsyncBufRead for & [ u8 ] {
547
+ delegate_async_buf_read_to_stdio ! ( ) ;
548
+ }
549
+
550
+ impl AsyncBufRead for StdIo :: Empty {
551
+ delegate_async_buf_read_to_stdio ! ( ) ;
552
+ }
553
+
554
+ impl < T : AsRef < [ u8 ] > + Unpin > AsyncBufRead for StdIo :: Cursor < T > {
555
+ delegate_async_buf_read_to_stdio ! ( ) ;
556
+ }
432
557
}
433
558
434
559
#[ cfg( feature = "std" ) ]
0 commit comments