@@ -358,11 +358,9 @@ where
358
358
// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
359
359
// time is 4,500 times (!) slower than a default reservation size of 32 if the
360
360
// reader has a very small amount of data to return.
361
- //
362
- // Because we're extending the buffer with uninitialized data for trusted
363
- // readers, we need to make sure to truncate that if any of this panics.
364
361
pub ( crate ) fn default_read_to_end < R : Read + ?Sized > ( r : & mut R , buf : & mut Vec < u8 > ) -> Result < usize > {
365
- let initial_len = buf. len ( ) ; // need to know so we can return how many bytes we read
362
+ let start_len = buf. len ( ) ;
363
+ let start_cap = buf. capacity ( ) ;
366
364
367
365
let mut initialized = 0 ; // Extra initalized bytes from previous loop iteration
368
366
loop {
@@ -384,7 +382,7 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>
384
382
}
385
383
386
384
if read_buf. filled_len ( ) == 0 {
387
- break ;
385
+ return Ok ( buf . len ( ) - start_len )
388
386
}
389
387
390
388
// store how much was initialized but not filled
@@ -395,9 +393,27 @@ pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>
395
393
unsafe {
396
394
buf. set_len ( new_len) ;
397
395
}
398
- }
399
396
400
- Ok ( buf. len ( ) - initial_len)
397
+ if buf. len ( ) == buf. capacity ( ) && buf. capacity ( ) == start_cap {
398
+ // The buffer might be an exact fit. Let's read into a probe buffer
399
+ // and see if it returns `Ok(0)`. If so, we've avoided an
400
+ // unnecessary doubling of the capacity. But if not, append the
401
+ // probe buffer to the primary buffer and let its capacity grow.
402
+ let mut probe = [ 0u8 ; 32 ] ;
403
+
404
+ loop {
405
+ match r. read ( & mut probe) {
406
+ Ok ( 0 ) => return Ok ( buf. len ( ) - start_len) ,
407
+ Ok ( n) => {
408
+ buf. extend_from_slice ( & probe[ ..n] ) ;
409
+ break ;
410
+ }
411
+ Err ( ref e) if e. kind ( ) == ErrorKind :: Interrupted => continue ,
412
+ Err ( e) => return Err ( e) ,
413
+ }
414
+ }
415
+ }
416
+ }
401
417
}
402
418
403
419
pub ( crate ) fn default_read_to_string < R : Read + ?Sized > (
0 commit comments