diff --git a/library/std/src/io/buffered/bufreader.rs b/library/std/src/io/buffered/bufreader.rs index acaa7e9228ecc..250cd58369614 100644 --- a/library/std/src/io/buffered/bufreader.rs +++ b/library/std/src/io/buffered/bufreader.rs @@ -322,6 +322,14 @@ impl Read for BufReader { crate::io::default_read_exact(self, buf) } + fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { + if self.buf.consume_with(cursor.capacity(), |claimed| cursor.append(claimed)) { + return Ok(()); + } + + crate::io::default_read_buf_exact(self, cursor) + } + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { let total_len = bufs.iter().map(|b| b.len()).sum::(); if self.buf.pos() == self.buf.filled() && total_len >= self.capacity() { diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 4ef1f1b695e60..49dde828c1fc4 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -357,6 +357,13 @@ where self.pos += n as u64; Ok(()) } + + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + let n = cursor.capacity(); + Read::read_buf_exact(&mut self.remaining_slice(), cursor)?; + self.pos += n as u64; + Ok(()) + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index cb972abd2b821..ee7ed4bcc9ab5 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -50,6 +50,10 @@ impl Read for &mut R { fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { (**self).read_exact(buf) } + #[inline] + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + (**self).read_buf_exact(cursor) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for &mut W { @@ -154,6 +158,10 @@ impl Read for Box { fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { (**self).read_exact(buf) } + #[inline] + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + (**self).read_buf_exact(cursor) + } } #[stable(feature = "rust1", since = "1.0.0")] impl Write for Box { @@ -301,6 +309,22 @@ impl Read for &[u8] { Ok(()) } + #[inline] + fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> io::Result<()> { + if cursor.capacity() > self.len() { + return Err(io::const_io_error!( + ErrorKind::UnexpectedEof, + "failed to fill whole buffer" + )); + } + let (a, b) = self.split_at(cursor.capacity()); + + cursor.append(a); + + *self = b; + Ok(()) + } + #[inline] fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { let len = self.len(); diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 10bf9c51d16aa..980b3e7aa48d0 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -582,6 +582,29 @@ where Ok(()) } +pub(crate) fn default_read_buf_exact( + this: &mut R, + mut cursor: BorrowedCursor<'_>, +) -> Result<()> { + while cursor.capacity() > 0 { + let prev_written = cursor.written(); + match this.read_buf(cursor.reborrow()) { + Ok(()) => {} + Err(e) if e.is_interrupted() => continue, + Err(e) => return Err(e), + } + + if cursor.written() == prev_written { + return Err(error::const_io_error!( + ErrorKind::UnexpectedEof, + "failed to fill whole buffer" + )); + } + } + + Ok(()) +} + /// The `Read` trait allows for reading bytes from a source. /// /// Implementors of the `Read` trait are called 'readers'. @@ -978,24 +1001,8 @@ pub trait Read { /// /// If this function returns an error, all bytes read will be appended to `cursor`. #[unstable(feature = "read_buf", issue = "78485")] - fn read_buf_exact(&mut self, mut cursor: BorrowedCursor<'_>) -> Result<()> { - while cursor.capacity() > 0 { - let prev_written = cursor.written(); - match self.read_buf(cursor.reborrow()) { - Ok(()) => {} - Err(e) if e.is_interrupted() => continue, - Err(e) => return Err(e), - } - - if cursor.written() == prev_written { - return Err(error::const_io_error!( - ErrorKind::UnexpectedEof, - "failed to fill whole buffer" - )); - } - } - - Ok(()) + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> Result<()> { + default_read_buf_exact(self, cursor) } /// Creates a "by reference" adaptor for this instance of `Read`. diff --git a/library/std/src/io/stdio.rs b/library/std/src/io/stdio.rs index 8f60b3b15356f..73fa7cbc3fead 100644 --- a/library/std/src/io/stdio.rs +++ b/library/std/src/io/stdio.rs @@ -451,6 +451,9 @@ impl Read for Stdin { fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { self.lock().read_exact(buf) } + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + self.lock().read_buf_exact(cursor) + } } #[stable(feature = "read_shared_stdin", since = "1.78.0")] @@ -477,6 +480,9 @@ impl Read for &Stdin { fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { self.lock().read_exact(buf) } + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + self.lock().read_buf_exact(cursor) + } } // only used by platform-dependent io::copy specializations, i.e. unused on some platforms @@ -517,6 +523,10 @@ impl Read for StdinLock<'_> { fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { self.inner.read_exact(buf) } + + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + self.inner.read_buf_exact(cursor) + } } impl SpecReadByte for StdinLock<'_> {