@@ -4,6 +4,8 @@ use crate::parse::{self, Cursor};
44use crate :: rcvec:: { RcVec , RcVecBuilder , RcVecIntoIter , RcVecMut } ;
55use crate :: { Delimiter , Spacing , TokenTree } ;
66#[ cfg( all( span_locations, not( fuzzing) ) ) ]
7+ use alloc:: collections:: BTreeMap ;
8+ #[ cfg( all( span_locations, not( fuzzing) ) ) ]
79use core:: cell:: RefCell ;
810#[ cfg( span_locations) ]
911use core:: cmp;
@@ -327,6 +329,7 @@ thread_local! {
327329 source_text: String :: new( ) ,
328330 span: Span { lo: 0 , hi: 0 } ,
329331 lines: vec![ 0 ] ,
332+ char_index_to_byte_offset: BTreeMap :: new( ) ,
330333 } ] ,
331334 } ) ;
332335}
@@ -336,6 +339,7 @@ struct FileInfo {
336339 source_text : String ,
337340 span : Span ,
338341 lines : Vec < usize > ,
342+ char_index_to_byte_offset : BTreeMap < usize , usize > ,
339343}
340344
341345#[ cfg( all( span_locations, not( fuzzing) ) ) ]
@@ -363,11 +367,27 @@ impl FileInfo {
363367 }
364368
365369 fn source_text ( & mut self , span : Span ) -> String {
366- let lo = ( span. lo - self . span . lo ) as usize ;
367- let trunc_lo = match self . source_text . char_indices ( ) . nth ( lo) {
368- Some ( ( offset, _ch) ) => & self . source_text [ offset..] ,
369- None => return String :: new ( ) ,
370+ let lo_char = ( span. lo - self . span . lo ) as usize ;
371+ let ( & last_char_index, & last_byte_offset) = self
372+ . char_index_to_byte_offset
373+ . range ( ..=lo_char)
374+ . next_back ( )
375+ . unwrap_or ( ( & 0 , & 0 ) ) ;
376+ let lo_byte = if last_char_index == lo_char {
377+ last_byte_offset
378+ } else {
379+ let total_byte_offset = match self . source_text [ last_byte_offset..]
380+ . char_indices ( )
381+ . nth ( lo_char - last_char_index)
382+ {
383+ Some ( ( additional_offset, _ch) ) => last_byte_offset + additional_offset,
384+ None => self . source_text . len ( ) ,
385+ } ;
386+ self . char_index_to_byte_offset
387+ . insert ( lo_char, total_byte_offset) ;
388+ total_byte_offset
370389 } ;
390+ let trunc_lo = & self . source_text [ lo_byte..] ;
371391 let char_len = ( span. hi - span. lo ) as usize ;
372392 let source_text = match trunc_lo. char_indices ( ) . nth ( char_len) {
373393 Some ( ( offset, _ch) ) => & trunc_lo[ ..offset] ,
@@ -421,6 +441,7 @@ impl SourceMap {
421441 source_text : src. to_owned ( ) ,
422442 span,
423443 lines,
444+ char_index_to_byte_offset : BTreeMap :: new ( ) ,
424445 } ) ;
425446
426447 span
0 commit comments