diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-05-04 18:36:37 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-04 18:36:37 +0200 |
| commit | 00bc2a425c98fe7067a862e3c822d4ca6c6be2ff (patch) | |
| tree | e75879870e465eeff00acfb740c4e80e1585404c | |
| parent | d7ea27808deb5e10a0f7384e339e4e6165e33398 (diff) | |
| parent | 2e3ee230220cc81b159d99d833cba46c667e3321 (diff) | |
| download | rust-00bc2a425c98fe7067a862e3c822d4ca6c6be2ff.tar.gz rust-00bc2a425c98fe7067a862e3c822d4ca6c6be2ff.zip | |
Rollup merge of #122441 - a1phyr:improve_read_impls, r=ChrisDenton
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`
| -rw-r--r-- | library/std/src/io/cursor.rs | 21 | ||||
| -rw-r--r-- | library/std/src/io/impls.rs | 13 | ||||
| -rw-r--r-- | library/std/src/io/mod.rs | 5 | ||||
| -rw-r--r-- | library/std/src/process.rs | 4 |
4 files changed, 33 insertions, 10 deletions
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index f6680b211c7..37492e9efab 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -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")] diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index dd7e0725176..46f04c7cd39 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -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) } @@ -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)) } } } diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index a3fdcdc2d07..af055152cbe 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -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(); diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 4a73a9be88b..d1848224251 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -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 { |
