@@ -353,20 +353,25 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
353353// Because we're extending the buffer with uninitialized data for trusted
354354// readers, we need to make sure to truncate that if any of this panics.
355355fn read_to_end < R : Read + ?Sized > ( r : & mut R , buf : & mut Vec < u8 > ) -> Result < usize > {
356- read_to_end_with_reservation ( r, buf, 32 )
356+ read_to_end_with_reservation ( r, buf, |_| 32 )
357357}
358358
359- fn read_to_end_with_reservation < R : Read + ?Sized > ( r : & mut R ,
360- buf : & mut Vec < u8 > ,
361- reservation_size : usize ) -> Result < usize >
359+ fn read_to_end_with_reservation < R , F > (
360+ r : & mut R ,
361+ buf : & mut Vec < u8 > ,
362+ mut reservation_size : F ,
363+ ) -> Result < usize >
364+ where
365+ R : Read + ?Sized ,
366+ F : FnMut ( & R ) -> usize ,
362367{
363368 let start_len = buf. len ( ) ;
364369 let mut g = Guard { len : buf. len ( ) , buf : buf } ;
365370 let ret;
366371 loop {
367372 if g. len == g. buf . len ( ) {
368373 unsafe {
369- g. buf . reserve ( reservation_size) ;
374+ g. buf . reserve ( reservation_size ( r ) ) ;
370375 let capacity = g. buf . capacity ( ) ;
371376 g. buf . set_len ( capacity) ;
372377 r. initializer ( ) . initialize ( & mut g. buf [ g. len ..] ) ;
@@ -2253,9 +2258,10 @@ impl<T: Read> Read for Take<T> {
22532258 }
22542259
22552260 fn read_to_end ( & mut self , buf : & mut Vec < u8 > ) -> Result < usize > {
2256- let reservation_size = cmp:: min ( self . limit , 32 ) as usize ;
2257-
2258- read_to_end_with_reservation ( self , buf, reservation_size)
2261+ // Pass in a reservation_size closure that respects the current value
2262+ // of limit for each read. If we hit the read limit, this prevents the
2263+ // final zero-byte read from allocating again.
2264+ read_to_end_with_reservation ( self , buf, |self_| cmp:: min ( self_. limit , 32 ) as usize )
22592265 }
22602266}
22612267
@@ -2378,6 +2384,7 @@ impl<B: BufRead> Iterator for Lines<B> {
23782384
23792385#[ cfg( test) ]
23802386mod tests {
2387+ use crate :: cmp;
23812388 use crate :: io:: prelude:: * ;
23822389 use super :: { Cursor , SeekFrom , repeat} ;
23832390 use crate :: io:: { self , IoSlice , IoSliceMut } ;
@@ -2651,6 +2658,49 @@ mod tests {
26512658 Ok ( ( ) )
26522659 }
26532660
2661+ // A simple example reader which uses the default implementation of
2662+ // read_to_end.
2663+ struct ExampleSliceReader < ' a > {
2664+ slice : & ' a [ u8 ] ,
2665+ }
2666+
2667+ impl < ' a > Read for ExampleSliceReader < ' a > {
2668+ fn read ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < usize > {
2669+ let len = cmp:: min ( self . slice . len ( ) , buf. len ( ) ) ;
2670+ buf[ ..len] . copy_from_slice ( & self . slice [ ..len] ) ;
2671+ self . slice = & self . slice [ len..] ;
2672+ Ok ( len)
2673+ }
2674+ }
2675+
2676+ #[ test]
2677+ fn test_read_to_end_capacity ( ) -> io:: Result < ( ) > {
2678+ let input = & b"foo" [ ..] ;
2679+
2680+ // read_to_end() generally needs to over-allocate, both for efficiency
2681+ // and so that it can distinguish EOF. Assert that this is the case
2682+ // with this simple ExampleSliceReader struct, which uses the default
2683+ // implementation of read_to_end. Even though vec1 is allocated with
2684+ // exactly enough capacity for the read, read_to_end will allocate more
2685+ // space here.
2686+ let mut vec1 = Vec :: with_capacity ( input. len ( ) ) ;
2687+ ExampleSliceReader { slice : input } . read_to_end ( & mut vec1) ?;
2688+ assert_eq ! ( vec1. len( ) , input. len( ) ) ;
2689+ assert ! ( vec1. capacity( ) > input. len( ) , "allocated more" ) ;
2690+
2691+ // However, std::io::Take includes an implementation of read_to_end
2692+ // that will not allocate when the limit has already been reached. In
2693+ // this case, vec2 never grows.
2694+ let mut vec2 = Vec :: with_capacity ( input. len ( ) ) ;
2695+ ExampleSliceReader { slice : input }
2696+ . take ( input. len ( ) as u64 )
2697+ . read_to_end ( & mut vec2) ?;
2698+ assert_eq ! ( vec2. len( ) , input. len( ) ) ;
2699+ assert_eq ! ( vec2. capacity( ) , input. len( ) , "did not allocate more" ) ;
2700+
2701+ Ok ( ( ) )
2702+ }
2703+
26542704 #[ test]
26552705 fn io_slice_mut_advance ( ) {
26562706 let mut buf1 = [ 1 ; 8 ] ;
0 commit comments