@@ -194,64 +194,46 @@ fn fold_file_bytewise<T: Read, W: Write>(
194194 let mut line = Vec :: new ( ) ;
195195
196196 loop {
197- if file
198- . read_until ( NL , & mut line)
199- . map_err_context ( || translate ! ( "fold-error-readline" ) ) ?
200- == 0
201- {
202- break ;
197+ // Ensures that our line always has enough bytes to either
198+ // come across a newline, a whitespace or just wrap around.
199+ while width > line. len ( ) {
200+ let buf = file
201+ . fill_buf ( )
202+ . map_err_context ( || translate ! ( "fold-error-readline" ) ) ?;
203+ if buf. is_empty ( ) {
204+ break ;
205+ }
206+ line. extend_from_slice ( buf) ;
207+ let len = buf. len ( ) ;
208+ file. consume ( len) ;
203209 }
204210
205- if line == [ NL ] {
206- output. write_all ( & [ NL ] ) ?;
207- line. clear ( ) ;
208- continue ;
211+ // The width exceeds the line read so far if we have
212+ // reached EOF.
213+ if width > line. len ( ) {
214+ output. write_all ( & line) ?;
215+ break ;
209216 }
210217
211- let len = line. len ( ) ;
212- let mut i = 0 ;
213-
214- while i < len {
215- let width = if len - i >= width { width } else { len - i } ;
216- let slice = {
217- let slice = & line[ i..i + width] ;
218- if spaces && i + width < len {
219- match slice
220- . iter ( )
221- . enumerate ( )
222- . rev ( )
223- . find ( |( _, c) | c. is_ascii_whitespace ( ) && * * c != CR )
224- {
225- Some ( ( m, _) ) => & slice[ ..=m] ,
226- None => slice,
227- }
228- } else {
229- slice
230- }
231- } ;
232-
233- // Don't duplicate trailing newlines: if the slice is "\n", the
234- // previous iteration folded just before the end of the line and
235- // has already printed this newline.
236- if slice == [ NL ] {
237- break ;
238- }
218+ let chunk = & line[ ..width] ;
219+ let newline_end = chunk. iter ( ) . position ( |c| NL . eq ( c) ) . map ( |v| v + 1 ) ;
239220
240- i += slice. len ( ) ;
221+ let space_end = chunk
222+ . iter ( )
223+ . rposition ( |c| spaces && c. is_ascii_whitespace ( ) && !CR . eq ( c) )
224+ . map ( |v| v + 1 ) ;
241225
242- let at_eol = i >= len;
226+ let end = newline_end. or ( space_end) . unwrap_or ( width) ;
227+ let slice = & line[ ..end] ;
243228
244- if at_eol {
245- output. write_all ( slice) ?;
246- } else {
247- output. write_all ( slice) ?;
248- output. write_all ( & [ NL ] ) ?;
249- }
229+ output. write_all ( slice) ?;
230+ let slice_ends_without_newline = line[ end - 1 ] != NL ;
231+ let no_newline_follows_slice = line. get ( end) . is_some_and ( |c| * c != NL ) ;
232+ if slice_ends_without_newline && no_newline_follows_slice {
233+ output. write_all ( & [ NL ] ) ?;
250234 }
251-
252- line. clear ( ) ;
235+ line. drain ( ..end) ;
253236 }
254-
255237 Ok ( ( ) )
256238}
257239
0 commit comments