From aa08095461a1f6f09642f1849d2032dac4fd1de7 Mon Sep 17 00:00:00 2001 From: Alisdair Owens Date: Mon, 20 Jul 2015 18:29:45 +0100 Subject: [PATCH] Make File's specialisation of read_to_end use the size of the file --- src/libstd/fs.rs | 18 ++++++++++++++++-- src/libstd/sys/common/io.rs | 7 ++++++- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 2c78b2894311d..bffaac1c2dbca 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -22,10 +22,12 @@ use core::prelude::*; use fmt; use ffi::OsString; use io::{self, SeekFrom, Seek, Read, Write}; +use io::SeekFrom::Current; use path::{Path, PathBuf}; use sys::fs as fs_imp; use sys_common::{AsInnerMut, FromInner, AsInner}; -use sys_common::io::read_to_end_uninitialized; +use sys_common::io::read_to_end_uninitialized_hint; +use cmp::min; use vec::Vec; /// A reference to an open file on the filesystem. @@ -330,7 +332,19 @@ impl Read for File { self.inner.read(buf) } fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - unsafe { read_to_end_uninitialized(self, buf) } + let total_size = try!(self.metadata()).len(); + let cur_pos = try!(self.seek(Current(0))) as u64; + + // size isn't guaranteed to stay static, so we need to check + // we deal with the possibility that cur_pos > size! + let size = + if cur_pos > total_size { + 0usize + } else { + min((total_size - cur_pos) as usize, usize::max_value()) + }; + + unsafe { read_to_end_uninitialized_hint(self, buf, size) } } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd/sys/common/io.rs b/src/libstd/sys/common/io.rs index 151d853fc9f7e..97656463ec064 100644 --- a/src/libstd/sys/common/io.rs +++ b/src/libstd/sys/common/io.rs @@ -24,9 +24,14 @@ use slice::from_raw_parts_mut; // * The implementation of read never reads the buffer provided. // * The implementation of read correctly reports how many bytes were written. pub unsafe fn read_to_end_uninitialized(r: &mut Read, buf: &mut Vec) -> io::Result { + read_to_end_uninitialized_hint(r, buf, 16) +} + +pub unsafe fn read_to_end_uninitialized_hint(r: &mut Read, buf: &mut Vec, size_hint: usize) + -> io::Result { let start_len = buf.len(); - buf.reserve(16); + buf.reserve(size_hint); // Always try to read into the empty space of the vector (from the length to the capacity). // If the vector ever fills up then we reserve an extra byte which should trigger the normal