Skip to content

Specialize many implementations of Read::read_buf_exact #122393

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

Merged
merged 1 commit into from
Apr 10, 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
8 changes: 8 additions & 0 deletions library/std/src/io/buffered/bufreader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,14 @@ impl<R: ?Sized + Read> Read for BufReader<R> {
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<usize> {
let total_len = bufs.iter().map(|b| b.len()).sum::<usize>();
if self.buf.pos() == self.buf.filled() && total_len >= self.capacity() {
Expand Down
7 changes: 7 additions & 0 deletions library/std/src/io/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,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")]
Expand Down
24 changes: 24 additions & 0 deletions library/std/src/io/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ impl<R: Read + ?Sized> 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<W: Write + ?Sized> Write for &mut W {
Expand Down Expand Up @@ -154,6 +158,10 @@ impl<R: Read + ?Sized> Read for Box<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<W: Write + ?Sized> Write for Box<W> {
Expand Down Expand Up @@ -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<u8>) -> io::Result<usize> {
let len = self.len();
Expand Down
43 changes: 25 additions & 18 deletions library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,6 +582,29 @@ where
Ok(())
}

pub(crate) fn default_read_buf_exact<R: Read + ?Sized>(
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'.
Expand Down Expand Up @@ -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`.
Expand Down
10 changes: 10 additions & 0 deletions library/std/src/io/stdio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 = "CURRENT_RUSTC_VERSION")]
Expand All @@ -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
Expand Down Expand Up @@ -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<'_> {
Expand Down