@@ -353,20 +353,25 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
353
353
// Because we're extending the buffer with uninitialized data for trusted
354
354
// readers, we need to make sure to truncate that if any of this panics.
355
355
fn 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 )
357
357
}
358
358
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 ,
362
367
{
363
368
let start_len = buf. len ( ) ;
364
369
let mut g = Guard { len : buf. len ( ) , buf : buf } ;
365
370
let ret;
366
371
loop {
367
372
if g. len == g. buf . len ( ) {
368
373
unsafe {
369
- g. buf . reserve ( reservation_size) ;
374
+ g. buf . reserve ( reservation_size ( r ) ) ;
370
375
let capacity = g. buf . capacity ( ) ;
371
376
g. buf . set_len ( capacity) ;
372
377
r. initializer ( ) . initialize ( & mut g. buf [ g. len ..] ) ;
@@ -2253,9 +2258,10 @@ impl<T: Read> Read for Take<T> {
2253
2258
}
2254
2259
2255
2260
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 )
2259
2265
}
2260
2266
}
2261
2267
@@ -2378,6 +2384,7 @@ impl<B: BufRead> Iterator for Lines<B> {
2378
2384
2379
2385
#[ cfg( test) ]
2380
2386
mod tests {
2387
+ use crate :: cmp;
2381
2388
use crate :: io:: prelude:: * ;
2382
2389
use super :: { Cursor , SeekFrom , repeat} ;
2383
2390
use crate :: io:: { self , IoSlice , IoSliceMut } ;
@@ -2651,6 +2658,49 @@ mod tests {
2651
2658
Ok ( ( ) )
2652
2659
}
2653
2660
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
+
2654
2704
#[ test]
2655
2705
fn io_slice_mut_advance ( ) {
2656
2706
let mut buf1 = [ 1 ; 8 ] ;
0 commit comments