diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index 0be5590440702..f7fbaa9c27649 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -290,9 +290,7 @@ impl Read for BufReader { // generation for the common path where the buffer has enough bytes to fill the passed-in // buffer. fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { - if let Some(claimed) = self.buffer().get(..buf.len()) { - buf.copy_from_slice(claimed); - self.consume(claimed.len()); + if self.buf.consume_with(buf.len(), |claimed| buf.copy_from_slice(claimed)) { return Ok(()); } diff --git a/library/std/src/io/buffered/bufreader/buffer.rs b/library/std/src/io/buffered/bufreader/buffer.rs index bf3462bf00cb8..8ae01f3b0ad8a 100644 --- a/library/std/src/io/buffered/bufreader/buffer.rs +++ b/library/std/src/io/buffered/bufreader/buffer.rs @@ -62,6 +62,23 @@ impl Buffer { self.pos = cmp::min(self.pos + amt, self.filled); } + /// If there are `amt` bytes available in the buffer, pass a slice containing those bytes to + /// `visitor` and return true. If there are not enough bytes available, return false. + #[inline] + pub fn consume_with(&mut self, amt: usize, mut visitor: V) -> bool + where + V: FnMut(&[u8]), + { + if let Some(claimed) = self.buffer().get(..amt) { + visitor(claimed); + // If the indexing into self.buffer() succeeds, amt must be a valid increment. + self.pos += amt; + true + } else { + false + } + } + #[inline] pub fn unconsume(&mut self, amt: usize) { self.pos = self.pos.saturating_sub(amt);