Skip to content

Commit

Permalink
Add BufRead::fill_buf (#176)
Browse files Browse the repository at this point in the history
* Add BufRead::fill_buf

* Make FillBufFuture constructor pub(crate)

* Give more information about the transmutation source type
  • Loading branch information
tirr-c authored and Stjepan Glavina committed Sep 11, 2019
1 parent 568f6a6 commit 06f2569
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/io/buf_read/fill_buf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
use std::pin::Pin;

use futures_io::AsyncBufRead;

use crate::future::Future;
use crate::io;
use crate::task::{Context, Poll};

#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct FillBufFuture<'a, R: ?Sized> {
reader: &'a mut R,
}

impl<'a, R: ?Sized> FillBufFuture<'a, R> {
pub(crate) fn new(reader: &'a mut R) -> Self {
Self { reader }
}
}

impl<'a, R: AsyncBufRead + Unpin + ?Sized> Future for FillBufFuture<'a, R> {
type Output = io::Result<&'a [u8]>;

fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&'a [u8]>> {
let Self { reader } = &mut *self;
let result = Pin::new(reader).poll_fill_buf(cx);
// This is safe because:
// 1. The buffer is valid for the lifetime of the reader.
// 2. Output is unrelated to the wrapper (Self).
result.map_ok(|buf| unsafe { std::mem::transmute::<&'_ [u8], &'a [u8]>(buf) })
}
}
22 changes: 22 additions & 0 deletions src/io/buf_read/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
mod fill_buf;
mod lines;
mod read_line;
mod read_until;

use fill_buf::FillBufFuture;
pub use lines::Lines;
use read_line::ReadLineFuture;
use read_until::ReadUntilFuture;
Expand Down Expand Up @@ -41,6 +43,26 @@ cfg_if! {
/// [`futures::io::AsyncBufRead`]:
/// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncBufRead.html
pub trait BufRead {
/// Returns the contents of the internal buffer, filling it with more data from the inner
/// reader if it is empty.
///
/// This function is a lower-level call. It needs to be paired with the [`consume`] method to
/// function properly. When calling this method, none of the contents will be "read" in the
/// sense that later calling `read` may return the same contents. As such, [`consume`] must be
/// called with the number of bytes that are consumed from this buffer to ensure that the bytes
/// are never returned twice.
///
/// [`consume`]: #tymethod.consume
///
/// An empty buffer returned indicates that the stream has reached EOF.
// TODO: write a proper doctest with `consume`
fn fill_buf<'a>(&'a mut self) -> ret!('a, FillBufFuture, io::Result<&'a [u8]>)
where
Self: Unpin,
{
FillBufFuture::new(self)
}

/// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
///
/// This function will read bytes from the underlying stream until the delimiter or EOF is
Expand Down

0 comments on commit 06f2569

Please sign in to comment.