@@ -313,12 +313,52 @@ fn unexpand_line(
313313 lastcol : usize ,
314314 ts : & [ usize ] ,
315315) -> UResult < ( ) > {
316+ // Fast path: if we're not converting all spaces (-a flag not set)
317+ // and the line doesn't start with spaces, just write it directly
318+ if !options. aflag && !buf. is_empty ( ) && buf[ 0 ] != b' ' && buf[ 0 ] != b'\t' {
319+ output. write_all ( buf) ?;
320+ buf. truncate ( 0 ) ;
321+ return Ok ( ( ) ) ;
322+ }
323+
316324 let mut byte = 0 ; // offset into the buffer
317325 let mut col = 0 ; // the current column
318326 let mut scol = 0 ; // the start col for the current span, i.e., the already-printed width
319327 let mut init = true ; // are we at the start of the line?
320328 let mut pctype = CharType :: Other ;
321329
330+ // Fast path for leading spaces in non-UTF8 mode: count consecutive spaces/tabs at start
331+ if !options. uflag && init && !options. aflag {
332+ // In default mode (not -a), we only convert leading spaces
333+ // So we can batch process them and then copy the rest
334+ while byte < buf. len ( ) {
335+ match buf[ byte] {
336+ b' ' => {
337+ col += 1 ;
338+ byte += 1 ;
339+ }
340+ b'\t' => {
341+ col += next_tabstop ( ts, col) . unwrap_or ( 1 ) ;
342+ byte += 1 ;
343+ pctype = CharType :: Tab ;
344+ }
345+ _ => break ,
346+ }
347+ }
348+
349+ // If we found spaces/tabs, write them as tabs
350+ if byte > 0 {
351+ write_tabs ( output, ts, 0 , col, pctype == CharType :: Tab , true , true ) ?;
352+ }
353+
354+ // Write the rest of the line directly (no more tab conversion needed)
355+ if byte < buf. len ( ) {
356+ output. write_all ( & buf[ byte..] ) ?;
357+ }
358+ buf. truncate ( 0 ) ;
359+ return Ok ( ( ) ) ;
360+ }
361+
322362 while byte < buf. len ( ) {
323363 // when we have a finite number of columns, never convert past the last column
324364 if lastcol > 0 && col >= lastcol {
@@ -379,7 +419,6 @@ fn unexpand_line(
379419
380420 // write out anything remaining
381421 write_tabs ( output, ts, scol, col, pctype == CharType :: Tab , init, true ) ?;
382- output. flush ( ) ?;
383422 buf. truncate ( 0 ) ; // clear out the buffer
384423
385424 Ok ( ( ) )
@@ -407,6 +446,7 @@ fn unexpand(options: &Options) -> UResult<()> {
407446 unexpand_line ( & mut buf, & mut output, options, lastcol, ts) ?;
408447 }
409448 }
449+ output. flush ( ) ?;
410450 Ok ( ( ) )
411451}
412452
0 commit comments