@@ -520,25 +520,36 @@ impl Input<'_> {
520520 /// Fills a given buffer.
521521 /// Reads in increments of 'self.ibs'.
522522 /// The start of each ibs-sized read follows the previous one.
523- fn fill_consecutive ( & mut self , buf : & mut Vec < u8 > ) -> io:: Result < ReadStat > {
523+ fn fill_consecutive ( & mut self , buf : & mut Vec < u8 > , bsize : usize ) -> io:: Result < ReadStat > {
524524 let mut reads_complete = 0 ;
525525 let mut reads_partial = 0 ;
526526 let mut bytes_total = 0 ;
527-
528- for chunk in buf. chunks_mut ( self . settings . ibs ) {
529- match self . read ( chunk) ? {
527+ buf. clear ( ) ;
528+ let spare = buf. spare_capacity_mut ( ) ;
529+ let spare_len = spare. len ( ) ;
530+ let target_area = & mut spare[ ..bsize. min ( spare_len) ] ;
531+
532+ for chunk in target_area. chunks_mut ( self . settings . ibs ) {
533+ // std cannot fix https://github.com/uutils/coreutils/issues/11544 without unsafe yet
534+ // caution: restrict usage of this to write-only
535+ let slice = unsafe {
536+ std:: slice:: from_raw_parts_mut ( chunk. as_mut_ptr ( ) . cast :: < u8 > ( ) , chunk. len ( ) )
537+ } ;
538+ match self . read ( slice) ? {
530539 rlen if rlen == self . settings . ibs => {
531540 bytes_total += rlen;
532541 reads_complete += 1 ;
533542 }
534543 rlen if rlen > 0 => {
535544 bytes_total += rlen;
536545 reads_partial += 1 ;
546+ break ;
537547 }
538- _ => break ,
548+ _ => break , // end of file
539549 }
540550 }
541- buf. truncate ( bytes_total) ;
551+ // todo: use wrapper to extend buf with read at same time without unsafe
552+ unsafe { buf. set_len ( bytes_total) } ;
542553 Ok ( ReadStat {
543554 reads_complete,
544555 reads_partial,
@@ -551,7 +562,10 @@ impl Input<'_> {
551562 /// Fills a given buffer.
552563 /// Reads in increments of 'self.ibs'.
553564 /// The start of each ibs-sized read is aligned to multiples of ibs; remaining space is filled with the 'pad' byte.
554- fn fill_blocks ( & mut self , buf : & mut Vec < u8 > , pad : u8 ) -> io:: Result < ReadStat > {
565+ fn fill_blocks ( & mut self , buf : & mut Vec < u8 > , bsize : usize , pad : u8 ) -> io:: Result < ReadStat > {
566+ // Resize the buffer to the bsize. Any garbage data in the buffer is overwritten or truncated, so there is no need to fill with BUF_INIT_BYTE first.
567+ // resizing buf cause serious performance drop https://github.com/uutils/coreutils/issues/11544
568+ buf. resize ( bsize, BUF_INIT_BYTE ) ;
555569 let mut reads_complete = 0 ;
556570 let mut reads_partial = 0 ;
557571 let mut base_idx = 0 ;
@@ -1366,13 +1380,10 @@ fn read_helper(i: &mut Input, buf: &mut Vec<u8>, bsize: usize) -> io::Result<Rea
13661380 }
13671381 // ------------------------------------------------------------------
13681382 // Read
1369- // Resize the buffer to the bsize. Any garbage data in the buffer is overwritten or truncated, so there is no need to fill with BUF_INIT_BYTE first.
1370- // resizing buf cause serious performance drop https://github.com/uutils/coreutils/issues/11544
1371- buf. resize ( bsize, BUF_INIT_BYTE ) ;
13721383
13731384 let mut rstat = match i. settings . iconv . sync {
1374- Some ( ch) => i. fill_blocks ( buf, ch) ?,
1375- _ => i. fill_consecutive ( buf) ?,
1385+ Some ( ch) => i. fill_blocks ( buf, bsize , ch) ?,
1386+ _ => i. fill_consecutive ( buf, bsize ) ?,
13761387 } ;
13771388 // Return early if no data
13781389 if rstat. reads_complete == 0 && rstat. reads_partial == 0 {
0 commit comments