From c3e6c983363af7f7a88e52d50d57404defb1bf49 Mon Sep 17 00:00:00 2001 From: Andrew Hickman Date: Tue, 2 Aug 2022 22:38:22 +0100 Subject: [PATCH] fix(utils): Fix off-by-one error in SourceOffset::from_location (#190) --- src/protocol.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/src/protocol.rs b/src/protocol.rs index d5cd1fa..d94011a 100644 --- a/src/protocol.rs +++ b/src/protocol.rs @@ -446,7 +446,7 @@ impl SourceOffset { self.0 } - /// Little utility to help convert line/column locations into + /// Little utility to help convert 1-based line/column locations into /// miette-compatible Spans /// /// This function is infallible: Giving an out-of-range line/column pair @@ -456,15 +456,15 @@ impl SourceOffset { let mut col = 0usize; let mut offset = 0usize; for char in source.as_ref().chars() { + if line + 1 >= loc_line && col + 1 >= loc_col { + break; + } if char == '\n' { col = 0; line += 1; } else { col += 1; } - if line + 1 >= loc_line && col + 1 >= loc_col { - break; - } offset += char.len_utf8(); } @@ -498,3 +498,26 @@ impl From for SourceOffset { SourceOffset(bytes) } } + +#[test] +fn test_source_offset_from_location() { + let source = "f\n\noo\r\nbar"; + + assert_eq!(SourceOffset::from_location(source, 1, 1).offset(), 0); + assert_eq!(SourceOffset::from_location(source, 1, 2).offset(), 1); + assert_eq!(SourceOffset::from_location(source, 2, 1).offset(), 2); + assert_eq!(SourceOffset::from_location(source, 3, 1).offset(), 3); + assert_eq!(SourceOffset::from_location(source, 3, 2).offset(), 4); + assert_eq!(SourceOffset::from_location(source, 3, 3).offset(), 5); + assert_eq!(SourceOffset::from_location(source, 3, 4).offset(), 6); + assert_eq!(SourceOffset::from_location(source, 4, 1).offset(), 7); + assert_eq!(SourceOffset::from_location(source, 4, 2).offset(), 8); + assert_eq!(SourceOffset::from_location(source, 4, 3).offset(), 9); + assert_eq!(SourceOffset::from_location(source, 4, 4).offset(), 10); + + // Out-of-range + assert_eq!( + SourceOffset::from_location(source, 5, 1).offset(), + source.len() + ); +}