about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2018-08-01 21:46:36 +0200
committerGitHub <noreply@github.com>2018-08-01 21:46:36 +0200
commiteeb7b6ae093c666084bb0f35e73151dcbe7a93af (patch)
tree7fcc3c4c0f66c3d4d26965b8c7ae2f9c599213fd /src/libstd
parent2893bd0e0c752af8c2238bf18181a4b6991bfd78 (diff)
parentb5ed39ff10f0e46be6e97b577477e0f60234fa0b (diff)
downloadrust-eeb7b6ae093c666084bb0f35e73151dcbe7a93af.tar.gz
rust-eeb7b6ae093c666084bb0f35e73151dcbe7a93af.zip
Rollup merge of #52939 - ljedrz:fix_51746, r=kennytm
Make io::Read::read_to_end consider io::Take::limit

Add a custom implementation of `io::Read::read_to_end` for `io::Take` that doesn't reserve the default 32 bytes but rather `Take::limit` if `Take::limit < 32`.

It's a conservative adjustment that preserves the default behavior for `Take::limit >= 32`.

Fixes #51746.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/io/mod.rs19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 5e89ad45f81..b83f3fbe7a5 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -354,19 +354,26 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
 // avoid paying to allocate and zero a huge chunk of memory if the reader only
 // has 4 bytes while still making large reads if the reader does have a ton
 // of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
-// time is 4,500 times (!) slower than this if the reader has a very small
-// amount of data to return.
+// time is 4,500 times (!) slower than a default reservation size of 32 if the
+// reader has a very small amount of data to return.
 //
 // Because we're extending the buffer with uninitialized data for trusted
 // readers, we need to make sure to truncate that if any of this panics.
 fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
+    read_to_end_with_reservation(r, buf, 32)
+}
+
+fn read_to_end_with_reservation<R: Read + ?Sized>(r: &mut R,
+                                                  buf: &mut Vec<u8>,
+                                                  reservation_size: usize) -> Result<usize>
+{
     let start_len = buf.len();
     let mut g = Guard { len: buf.len(), buf: buf };
     let ret;
     loop {
         if g.len == g.buf.len() {
             unsafe {
-                g.buf.reserve(32);
+                g.buf.reserve(reservation_size);
                 let capacity = g.buf.capacity();
                 g.buf.set_len(capacity);
                 r.initializer().initialize(&mut g.buf[g.len..]);
@@ -1899,6 +1906,12 @@ impl<T: Read> Read for Take<T> {
     unsafe fn initializer(&self) -> Initializer {
         self.inner.initializer()
     }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
+        let reservation_size = cmp::min(self.limit, 32) as usize;
+
+        read_to_end_with_reservation(self, buf, reservation_size)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]