Skip to content

Commit

Permalink
Rollup merge of #122441 - a1phyr:improve_read_impls, r=ChrisDenton
Browse files Browse the repository at this point in the history
Improve several `Read` implementations

- `read_to_end` and `read_to_string` for `Cursor`
- Error on OOM in `read_to_string` of `&[u8]` and `VecDeque<u8>`
- Avoid making the slices contiguous in `VecDeque::read_to_string`
- ~`read_exact` and (unstable) `read_buf_exact` for `Take`~
- ~`read_buf` for `UnixStream` and `&UnixStream`~ (moved to #123084)
- `read_to_end` for `ChildStdErr`
  • Loading branch information
matthiaskrgr committed May 4, 2024
2 parents d7ea278 + 2e3ee23 commit 00bc2a4
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 10 deletions.
21 changes: 21 additions & 0 deletions library/std/src/io/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -364,6 +364,27 @@ where
self.pos += n as u64;
Ok(())
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
let content = self.remaining_slice();
let len = content.len();
buf.try_reserve(len)?;
buf.extend_from_slice(content);
self.pos += len as u64;

Ok(len)
}

fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
let content =
crate::str::from_utf8(self.remaining_slice()).map_err(|_| io::Error::INVALID_UTF8)?;
let len = content.len();
buf.try_reserve(len)?;
buf.push_str(content);
self.pos += len as u64;

Ok(len)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
13 changes: 4 additions & 9 deletions library/std/src/io/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,9 @@ impl Read for &[u8] {
#[inline]
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
let content = str::from_utf8(self).map_err(|_| io::Error::INVALID_UTF8)?;
buf.push_str(content);
let len = self.len();
buf.try_reserve(len)?;
buf.push_str(content);
*self = &self[len..];
Ok(len)
}
Expand Down Expand Up @@ -473,14 +474,8 @@ impl<A: Allocator> Read for VecDeque<u8, A> {

#[inline]
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
// We have to use a single contiguous slice because the `VecDequeue` might be split in the
// middle of an UTF-8 character.
let len = self.len();
let content = self.make_contiguous();
let string = str::from_utf8(content).map_err(|_| io::Error::INVALID_UTF8)?;
buf.push_str(string);
self.clear();
Ok(len)
// SAFETY: We only append to the buffer
unsafe { io::append_to_string(buf, |buf| self.read_to_end(buf)) }
}
}

Expand Down
5 changes: 4 additions & 1 deletion library/std/src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,10 @@ where
{
let mut g = Guard { len: buf.len(), buf: buf.as_mut_vec() };
let ret = f(g.buf);
if str::from_utf8(&g.buf[g.len..]).is_err() {

// SAFETY: the caller promises to only append data to `buf`
let appended = g.buf.get_unchecked(g.len..);
if str::from_utf8(appended).is_err() {
ret.and_then(|_| Err(Error::INVALID_UTF8))
} else {
g.len = g.buf.len();
Expand Down
4 changes: 4 additions & 0 deletions library/std/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,10 @@ impl Read for ChildStderr {
fn is_read_vectored(&self) -> bool {
self.inner.is_read_vectored()
}

fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
self.inner.read_to_end(buf)
}
}

impl AsInner<AnonPipe> for ChildStderr {
Expand Down

0 comments on commit 00bc2a4

Please sign in to comment.