Skip to content

Commit 1bd5338

Browse files
authored
Rollup merge of rust-lang#128406 - lolbinarycat:bufreader_peek, r=Mark-Simulacrum
implement BufReader::peek Part of rust-lang#128405
2 parents e20aa64 + 51ec2bb commit 1bd5338

File tree

2 files changed

+55
-0
lines changed

2 files changed

+55
-0
lines changed

Diff for: std/src/io/buffered/bufreader.rs

+34
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,40 @@ impl<R: Read> BufReader<R> {
9494
pub fn with_capacity(capacity: usize, inner: R) -> BufReader<R> {
9595
BufReader { inner, buf: Buffer::with_capacity(capacity) }
9696
}
97+
98+
/// Attempt to look ahead `n` bytes.
99+
///
100+
/// `n` must be less than `capacity`.
101+
///
102+
/// ## Examples
103+
///
104+
/// ```rust
105+
/// #![feature(bufreader_peek)]
106+
/// use std::io::{Read, BufReader};
107+
///
108+
/// let mut bytes = &b"oh, hello"[..];
109+
/// let mut rdr = BufReader::with_capacity(6, &mut bytes);
110+
/// assert_eq!(rdr.peek(2).unwrap(), b"oh");
111+
/// let mut buf = [0; 4];
112+
/// rdr.read(&mut buf[..]).unwrap();
113+
/// assert_eq!(&buf, b"oh, ");
114+
/// assert_eq!(rdr.peek(2).unwrap(), b"he");
115+
/// let mut s = String::new();
116+
/// rdr.read_to_string(&mut s).unwrap();
117+
/// assert_eq!(&s, "hello");
118+
/// ```
119+
#[unstable(feature = "bufreader_peek", issue = "128405")]
120+
pub fn peek(&mut self, n: usize) -> io::Result<&[u8]> {
121+
assert!(n <= self.capacity());
122+
while n > self.buf.buffer().len() {
123+
if self.buf.pos() > 0 {
124+
self.buf.backshift();
125+
}
126+
self.buf.read_more(&mut self.inner)?;
127+
debug_assert_eq!(self.buf.pos(), 0);
128+
}
129+
Ok(&self.buf.buffer()[..n])
130+
}
97131
}
98132

99133
impl<R: ?Sized> BufReader<R> {

Diff for: std/src/io/buffered/bufreader/buffer.rs

+21
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,27 @@ impl Buffer {
9797
self.pos = self.pos.saturating_sub(amt);
9898
}
9999

100+
/// Read more bytes into the buffer without discarding any of its contents
101+
pub fn read_more(&mut self, mut reader: impl Read) -> io::Result<()> {
102+
let mut buf = BorrowedBuf::from(&mut self.buf[self.pos..]);
103+
let old_init = self.initialized - self.pos;
104+
unsafe {
105+
buf.set_init(old_init);
106+
}
107+
reader.read_buf(buf.unfilled())?;
108+
self.filled += buf.len();
109+
self.initialized += buf.init_len() - old_init;
110+
Ok(())
111+
}
112+
113+
/// Remove bytes that have already been read from the buffer.
114+
pub fn backshift(&mut self) {
115+
self.buf.copy_within(self.pos.., 0);
116+
self.initialized -= self.pos;
117+
self.filled -= self.pos;
118+
self.pos = 0;
119+
}
120+
100121
#[inline]
101122
pub fn fill_buf(&mut self, mut reader: impl Read) -> io::Result<&[u8]> {
102123
// If we've reached the end of our internal buffer then we need to fetch

0 commit comments

Comments
 (0)