about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-05-04 18:36:37 +0200
committerGitHub <noreply@github.com>2024-05-04 18:36:37 +0200
commit00bc2a425c98fe7067a862e3c822d4ca6c6be2ff (patch)
treee75879870e465eeff00acfb740c4e80e1585404c
parentd7ea27808deb5e10a0f7384e339e4e6165e33398 (diff)
parent2e3ee230220cc81b159d99d833cba46c667e3321 (diff)
downloadrust-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.rs21
-rw-r--r--library/std/src/io/impls.rs13
-rw-r--r--library/std/src/io/mod.rs5
-rw-r--r--library/std/src/process.rs4
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 {