@@ -13,12 +13,12 @@ use syntax_pos::{self, BytePos, CharPos, Pos, Span, NO_EXPANSION};
1313use source_map:: { SourceMap , FilePathMapping } ;
1414use errors:: { Applicability , FatalError , Diagnostic , DiagnosticBuilder } ;
1515use parse:: { token, ParseSess } ;
16- use str:: char_at;
1716use symbol:: { Symbol , keywords} ;
1817use core:: unicode:: property:: Pattern_White_Space ;
1918
2019use std:: borrow:: Cow ;
2120use std:: char;
21+ use std:: iter;
2222use std:: mem:: replace;
2323use rustc_data_structures:: sync:: Lrc ;
2424
@@ -459,45 +459,42 @@ impl<'a> StringReader<'a> {
459459
460460 /// Converts CRLF to LF in the given string, raising an error on bare CR.
461461 fn translate_crlf < ' b > ( & self , start : BytePos , s : & ' b str , errmsg : & ' b str ) -> Cow < ' b , str > {
462- let mut i = 0 ;
463- while i < s. len ( ) {
464- let ch = char_at ( s, i) ;
465- let next = i + ch. len_utf8 ( ) ;
462+ let mut chars = s. char_indices ( ) . peekable ( ) ;
463+ while let Some ( ( i, ch) ) = chars. next ( ) {
466464 if ch == '\r' {
467- if next < s . len ( ) && char_at ( s , next ) == '\n' {
468- return translate_crlf_ ( self , start, s, errmsg , i ) . into ( ) ;
465+ if let Some ( ( lf_idx , '\n' ) ) = chars . peek ( ) {
466+ return translate_crlf_ ( self , start, s, * lf_idx , chars , errmsg ) . into ( ) ;
469467 }
470468 let pos = start + BytePos ( i as u32 ) ;
471- let end_pos = start + BytePos ( next as u32 ) ;
469+ let end_pos = start + BytePos ( ( i + ch . len_utf8 ( ) ) as u32 ) ;
472470 self . err_span_ ( pos, end_pos, errmsg) ;
473471 }
474- i = next;
475472 }
476473 return s. into ( ) ;
477474
478475 fn translate_crlf_ ( rdr : & StringReader ,
479476 start : BytePos ,
480477 s : & str ,
481- errmsg : & str ,
482- mut i : usize )
478+ mut j : usize ,
479+ mut chars : iter:: Peekable < impl Iterator < Item = ( usize , char ) > > ,
480+ errmsg : & str )
483481 -> String {
484482 let mut buf = String :: with_capacity ( s. len ( ) ) ;
485- let mut j = 0 ;
486- while i < s. len ( ) {
487- let ch = char_at ( s, i) ;
488- let next = i + ch. len_utf8 ( ) ;
483+ // Skip first CR
484+ buf. push_str ( & s[ .. j - 1 ] ) ;
485+ while let Some ( ( i, ch) ) = chars. next ( ) {
489486 if ch == '\r' {
490487 if j < i {
491488 buf. push_str ( & s[ j..i] ) ;
492489 }
490+ let next = i + ch. len_utf8 ( ) ;
493491 j = next;
494- if next >= s . len ( ) || char_at ( s , next ) != '\n' {
492+ if chars . peek ( ) . map ( | ( _ , ch ) | * ch ) != Some ( '\n' ) {
495493 let pos = start + BytePos ( i as u32 ) ;
496494 let end_pos = start + BytePos ( next as u32 ) ;
497495 rdr. err_span_ ( pos, end_pos, errmsg) ;
498496 }
499497 }
500- i = next;
501498 }
502499 if j < s. len ( ) {
503500 buf. push_str ( & s[ j..] ) ;
@@ -1858,6 +1855,11 @@ fn ident_continue(c: Option<char>) -> bool {
18581855 ( c > '\x7f' && c. is_xid_continue ( ) )
18591856}
18601857
1858+ #[ inline]
1859+ fn char_at ( s : & str , byte : usize ) -> char {
1860+ s[ byte..] . chars ( ) . next ( ) . unwrap ( )
1861+ }
1862+
18611863#[ cfg( test) ]
18621864mod tests {
18631865 use super :: * ;
0 commit comments