@@ -27,7 +27,8 @@ pub fn render(source_code: &str, mut labels: Vec1<Label>) -> String {
2727 let span = label. span ;
2828 let start_ix = source_code. floor_char_boundary ( span. start ( ) . index ( ) ) ;
2929 let end_ix = source_code. ceil_char_boundary ( span. end ( ) . index ( ) ) ;
30- label. span = Span :: from_indices ( start_ix. into ( ) , end_ix. into ( ) ) ;
30+ // UNWRAP: since span is already ordered, we know that start_ix <= end_ix
31+ label. span = Span :: try_from_indices ( start_ix. into ( ) , end_ix. into ( ) ) . unwrap ( ) ;
3132 }
3233
3334 Highlighter :: new ( source_code) . render_spans ( labels. into ( ) )
@@ -108,8 +109,7 @@ impl Highlighter<'_> {
108109 . unwrap_or ( self . source_code . len ( ) )
109110 . into ( ) ;
110111
111- let line_span = Span :: from ( ( start_of_line, end_of_line) ) ;
112-
112+ let line_span = Span :: try_from ( ( start_of_line, end_of_line) ) . unwrap ( ) ;
113113 debug_assert ! (
114114 line_span. contains_offset( span. start( ) )
115115 || ( span. len( ) == Count :: ZERO && span. start( ) == line_span. end( ) )
@@ -421,8 +421,9 @@ impl LineHighlighter<'_> {
421421 // |← offset_to_space →|
422422 // [l.start]----
423423 // |← offset_from_start? →|
424- let offset_from_start =
425- self . source_code [ line_start. up_to ( l. start ( ) ) ] . width ( ) ;
424+ let offset_from_start = self . source_code
425+ [ line_start. up_to ( l. start ( ) ) . expect ( "l.start >= line_start" ) ]
426+ . width ( ) ;
426427
427428 if offset_from_start == offset_to_space {
428429 Some ( & l. style )
@@ -452,7 +453,10 @@ impl LineHighlighter<'_> {
452453 } ;
453454
454455 debug_assert ! ( line_start <= label. start( ) ) ;
455- let indent_width = self . source_code [ line_start. up_to ( label. start ( ) ) ] . width ( ) ;
456+ let indent_width = self . source_code [ line_start
457+ . up_to ( label. start ( ) )
458+ . expect ( "label.start >= line_start" ) ]
459+ . width ( ) ;
456460
457461 // 2 chars at start of messages: "└╴"
458462 const MSG_PREFIX_WIDTH : usize = 2 ;
@@ -484,7 +488,9 @@ impl LineHighlighter<'_> {
484488 // |← total_width →|← len? →|
485489 // [l.start]-------
486490 // |← offset_from_start →|
487- let offset_from_start = self . source_code [ line_start. up_to ( l. start ( ) ) ] . width ( ) ;
491+ let offset_from_start = self . source_code
492+ [ line_start. up_to ( l. start ( ) ) . expect ( "l.start >= line_start" ) ]
493+ . width ( ) ;
488494 if let Some ( len) = offset_from_start. checked_sub ( total_width) {
489495 if len > 0 {
490496 out. push ( no_style. style ( " " . repeat ( len) . into ( ) ) ) ;
@@ -517,7 +523,10 @@ impl LineHighlighter<'_> {
517523 let end = min ( wanted_end, label. start ( ) ) ;
518524
519525 // emit highlighted portion of line
520- let value = Span :: from_indices ( up_to, end) . str ( self . source_code ) ;
526+ // UNWRAP: since start is > up_to, end must be as well
527+ let value = Span :: try_from_indices ( up_to, end)
528+ . unwrap ( )
529+ . str ( self . source_code ) ;
521530 self . line . push ( outer_label. style . style ( value. into ( ) ) ) ;
522531
523532 // emit indicator line
@@ -543,14 +552,17 @@ impl LineHighlighter<'_> {
543552 // if we still didn’t get to the start of the next label
544553 // then there is an unhighlighted gap
545554 if label. start ( ) > up_to {
546- // emit unhighlighted characters
547- let value = & self . source_code [ up_to. up_to ( label. start ( ) ) ] ;
548- self . line . push ( no_style. style ( value. into ( ) ) ) ;
549- // space indicator line wide enough
550- self . indicator_line
551- . push ( no_style. style ( " " . repeat ( value. width ( ) ) . into ( ) ) ) ;
552-
553- up_to = label. start ( ) ;
555+ // the first check ensures that start > up_to, .up_to() will allow start >= up_to
556+ if let Some ( slice) = up_to. up_to ( label. start ( ) ) {
557+ // emit unhighlighted characters
558+ let value = & self . source_code [ slice] ;
559+ self . line . push ( no_style. style ( value. into ( ) ) ) ;
560+ // space indicator line wide enough
561+ self . indicator_line
562+ . push ( no_style. style ( " " . repeat ( value. width ( ) ) . into ( ) ) ) ;
563+
564+ up_to = label. start ( ) ;
565+ }
554566 }
555567 }
556568
@@ -560,10 +572,11 @@ impl LineHighlighter<'_> {
560572
561573 while let Some ( label) = stack. pop ( ) {
562574 let end = label. end ( ) ;
563- if up_to <= end {
575+
576+ if let Some ( slice) = up_to. up_to ( end) {
564577 // TODO: what are the effects of this check?
565578 // it prevents a crash found by fuzzing but might skip a message?
566- let value = & self . source_code [ up_to . up_to ( end ) ] ;
579+ let value = & self . source_code [ slice ] ;
567580 let continuing = label. start ( ) < up_to;
568581 self . fill_indicator ( continuing, false , value, & label. style ) ;
569582 self . line . push ( label. style . style ( value. into ( ) ) ) ;
@@ -574,10 +587,13 @@ impl LineHighlighter<'_> {
574587
575588 // if we didn't reach the end, we need to emit the rest
576589 if up_to < line_span. end ( ) {
577- // emit unhighlighted characters
578- let value = self . source_code [ up_to. up_to ( line_span. end ( ) ) ] . trim_ascii_end ( ) ;
579- self . line . push ( no_style. style ( value. into ( ) ) ) ;
580- // indicator line doesn't need spacing
590+ // note that .up_to() would allow <= line_span.end()
591+ if let Some ( slice) = up_to. up_to ( line_span. end ( ) ) {
592+ // emit unhighlighted characters
593+ let value = self . source_code [ slice] . trim_ascii_end ( ) ;
594+ self . line . push ( no_style. style ( value. into ( ) ) ) ;
595+ // indicator line doesn't need spacing
596+ }
581597 }
582598
583599 // emit all messages now that we know the full order
0 commit comments