Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

implement BufReader::peek #128406

Merged
merged 1 commit into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions library/std/src/io/buffered/bufreader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,40 @@ impl<R: Read> BufReader<R> {
pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
BufReader { inner, buf: Buffer::with_capacity(capacity) }
}

/// Attempt to look ahead `n` bytes.
///
/// `n` must be less than `capacity`.
///
/// ## Examples
///
/// ```rust
/// #![feature(bufreader_peek)]
/// use std::io::{Read, BufReader};
///
/// let mut bytes = &b"oh, hello"[..];
/// let mut rdr = BufReader::with_capacity(6, &mut bytes);
/// assert_eq!(rdr.peek(2).unwrap(), b"oh");
/// let mut buf = [0; 4];
/// rdr.read(&mut buf[..]).unwrap();
/// assert_eq!(&buf, b"oh, ");
/// assert_eq!(rdr.peek(2).unwrap(), b"he");
/// let mut s = String::new();
/// rdr.read_to_string(&mut s).unwrap();
/// assert_eq!(&s, "hello");
/// ```
#[unstable(feature = "bufreader_peek", issue = "128405")]
pub fn peek(&mut self, n: usize) -> io::Result<&[u8]> {
assert!(n <= self.capacity());
while n > self.buf.buffer().len() {
if self.buf.pos() > 0 {
self.buf.backshift();
}
self.buf.read_more(&mut self.inner)?;
debug_assert_eq!(self.buf.pos(), 0);
}
Ok(&self.buf.buffer()[..n])
}
}

impl<R: ?Sized> BufReader<R> {
Expand Down
21 changes: 21 additions & 0 deletions library/std/src/io/buffered/bufreader/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,27 @@ impl Buffer {
self.pos = self.pos.saturating_sub(amt);
}

/// Read more bytes into the buffer without discarding any of its contents
pub fn read_more(&mut self, mut reader: impl Read) -> io::Result<()> {
let mut buf = BorrowedBuf::from(&mut self.buf[self.pos..]);
let old_init = self.initialized - self.pos;
unsafe {
buf.set_init(old_init);
}
reader.read_buf(buf.unfilled())?;
self.filled += buf.len();
self.initialized += buf.init_len() - old_init;
Ok(())
}

/// Remove bytes that have already been read from the buffer.
pub fn backshift(&mut self) {
Mark-Simulacrum marked this conversation as resolved.
Show resolved Hide resolved
self.buf.copy_within(self.pos.., 0);
self.initialized -= self.pos;
self.filled -= self.pos;
self.pos = 0;
}

#[inline]
pub fn fill_buf(&mut self, mut reader: impl Read) -> io::Result<&[u8]> {
// If we've reached the end of our internal buffer then we need to fetch
Expand Down
Loading