Skip to content

Commit 06f2569

Browse files
tirr-cStjepan Glavina
authored and
Stjepan Glavina
committed
Add BufRead::fill_buf (#176)
* Add BufRead::fill_buf * Make FillBufFuture constructor pub(crate) * Give more information about the transmutation source type
1 parent 568f6a6 commit 06f2569

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

Diff for: src/io/buf_read/fill_buf.rs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use std::pin::Pin;
2+
3+
use futures_io::AsyncBufRead;
4+
5+
use crate::future::Future;
6+
use crate::io;
7+
use crate::task::{Context, Poll};
8+
9+
#[doc(hidden)]
10+
#[allow(missing_debug_implementations)]
11+
pub struct FillBufFuture<'a, R: ?Sized> {
12+
reader: &'a mut R,
13+
}
14+
15+
impl<'a, R: ?Sized> FillBufFuture<'a, R> {
16+
pub(crate) fn new(reader: &'a mut R) -> Self {
17+
Self { reader }
18+
}
19+
}
20+
21+
impl<'a, R: AsyncBufRead + Unpin + ?Sized> Future for FillBufFuture<'a, R> {
22+
type Output = io::Result<&'a [u8]>;
23+
24+
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&'a [u8]>> {
25+
let Self { reader } = &mut *self;
26+
let result = Pin::new(reader).poll_fill_buf(cx);
27+
// This is safe because:
28+
// 1. The buffer is valid for the lifetime of the reader.
29+
// 2. Output is unrelated to the wrapper (Self).
30+
result.map_ok(|buf| unsafe { std::mem::transmute::<&'_ [u8], &'a [u8]>(buf) })
31+
}
32+
}

Diff for: src/io/buf_read/mod.rs

+22
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1+
mod fill_buf;
12
mod lines;
23
mod read_line;
34
mod read_until;
45

6+
use fill_buf::FillBufFuture;
57
pub use lines::Lines;
68
use read_line::ReadLineFuture;
79
use read_until::ReadUntilFuture;
@@ -41,6 +43,26 @@ cfg_if! {
4143
/// [`futures::io::AsyncBufRead`]:
4244
/// https://docs.rs/futures-preview/0.3.0-alpha.17/futures/io/trait.AsyncBufRead.html
4345
pub trait BufRead {
46+
/// Returns the contents of the internal buffer, filling it with more data from the inner
47+
/// reader if it is empty.
48+
///
49+
/// This function is a lower-level call. It needs to be paired with the [`consume`] method to
50+
/// function properly. When calling this method, none of the contents will be "read" in the
51+
/// sense that later calling `read` may return the same contents. As such, [`consume`] must be
52+
/// called with the number of bytes that are consumed from this buffer to ensure that the bytes
53+
/// are never returned twice.
54+
///
55+
/// [`consume`]: #tymethod.consume
56+
///
57+
/// An empty buffer returned indicates that the stream has reached EOF.
58+
// TODO: write a proper doctest with `consume`
59+
fn fill_buf<'a>(&'a mut self) -> ret!('a, FillBufFuture, io::Result<&'a [u8]>)
60+
where
61+
Self: Unpin,
62+
{
63+
FillBufFuture::new(self)
64+
}
65+
4466
/// Reads all bytes into `buf` until the delimiter `byte` or EOF is reached.
4567
///
4668
/// This function will read bytes from the underlying stream until the delimiter or EOF is

0 commit comments

Comments
 (0)