@@ -29,15 +29,28 @@ impl<'a, T: Text + ?Sized> Parser<'a, T> {
2929 self . lines . peek ( )
3030 }
3131
32+ fn offset ( & self ) -> usize {
33+ self . offset
34+ }
35+
3236 fn next ( & mut self ) -> Result < & ' a T > {
3337 let line = self
3438 . lines
3539 . next ( )
36- . ok_or ( ParsePatchErrorKind :: UnexpectedEof ) ?;
40+ . ok_or_else ( || self . error ( ParsePatchErrorKind :: UnexpectedEof ) ) ?;
3741 self . offset += line. len ( ) ;
3842 Ok ( line)
3943 }
4044
45+ /// Creates an error with the current offset as span.
46+ fn error ( & self , kind : ParsePatchErrorKind ) -> ParsePatchError {
47+ ParsePatchError :: new ( kind, self . offset ..self . offset )
48+ }
49+
50+ /// Creates an error with a specific offset as span.
51+ fn error_at ( & self , kind : ParsePatchErrorKind , offset : usize ) -> ParsePatchError {
52+ ParsePatchError :: new ( kind, offset..offset)
53+ }
4154}
4255
4356pub fn parse ( input : & str ) -> Result < Patch < ' _ , str > > {
@@ -80,12 +93,12 @@ fn patch_header<'a, T: Text + ToOwned + ?Sized>(
8093 while let Some ( line) = parser. peek ( ) {
8194 if line. starts_with ( "--- " ) {
8295 if filename1. is_some ( ) {
83- return Err ( ParsePatchErrorKind :: MultipleOriginalHeaders . into ( ) ) ;
96+ return Err ( parser . error ( ParsePatchErrorKind :: MultipleOriginalHeaders ) ) ;
8497 }
8598 filename1 = Some ( parse_filename ( "--- " , parser. next ( ) ?) ?) ;
8699 } else if line. starts_with ( "+++ " ) {
87100 if filename2. is_some ( ) {
88- return Err ( ParsePatchErrorKind :: MultipleModifiedHeaders . into ( ) ) ;
101+ return Err ( parser . error ( ParsePatchErrorKind :: MultipleModifiedHeaders ) ) ;
89102 }
90103 filename2 = Some ( parse_filename ( "+++ " , parser. next ( ) ?) ?) ;
91104 } else {
@@ -149,20 +162,23 @@ fn hunks<'a, T: Text + ?Sized>(parser: &mut Parser<'a, T>) -> Result<Vec<Hunk<'a
149162
150163 // check and verify that the Hunks are in sorted order and don't overlap
151164 if !verify_hunks_in_order ( & hunks) {
152- return Err ( ParsePatchErrorKind :: HunksOutOfOrder . into ( ) ) ;
165+ return Err ( parser . error ( ParsePatchErrorKind :: HunksOutOfOrder ) ) ;
153166 }
154167
155168 Ok ( hunks)
156169}
157170
158171fn hunk < ' a , T : Text + ?Sized > ( parser : & mut Parser < ' a , T > ) -> Result < Hunk < ' a , T > > {
159- let ( range1, range2, function_context) = hunk_header ( parser. next ( ) ?) ?;
172+ let hunk_start = parser. offset ( ) ;
173+ let header_line = parser. next ( ) ?;
174+ let ( range1, range2, function_context) =
175+ hunk_header ( header_line) . map_err ( |e| parser. error_at ( e. kind , hunk_start) ) ?;
160176 let lines = hunk_lines ( parser) ?;
161177
162178 // check counts of lines to see if they match the ranges in the hunk header
163179 let ( len1, len2) = super :: hunk_lines_count ( & lines) ;
164180 if len1 != range1. len || len2 != range2. len {
165- return Err ( ParsePatchErrorKind :: HunkMismatch . into ( ) ) ;
181+ return Err ( parser . error_at ( ParsePatchErrorKind :: HunkMismatch , hunk_start ) ) ;
166182 }
167183
168184 Ok ( Hunk :: new ( range1, range2, function_context, lines) )
@@ -217,25 +233,25 @@ fn hunk_lines<'a, T: Text + ?Sized>(parser: &mut Parser<'a, T>) -> Result<Vec<Li
217233 let line = if line. starts_with ( "@" ) {
218234 break ;
219235 } else if no_newline_context {
220- return Err ( ParsePatchErrorKind :: ExpectedEndOfHunk . into ( ) ) ;
236+ return Err ( parser . error ( ParsePatchErrorKind :: ExpectedEndOfHunk ) ) ;
221237 } else if let Some ( line) = line. strip_prefix ( " " ) {
222238 Line :: Context ( line)
223239 } else if line. starts_with ( "\n " ) {
224240 Line :: Context ( * line)
225241 } else if let Some ( line) = line. strip_prefix ( "-" ) {
226242 if no_newline_delete {
227- return Err ( ParsePatchErrorKind :: TooManyDeletedLines . into ( ) ) ;
243+ return Err ( parser . error ( ParsePatchErrorKind :: TooManyDeletedLines ) ) ;
228244 }
229245 Line :: Delete ( line)
230246 } else if let Some ( line) = line. strip_prefix ( "+" ) {
231247 if no_newline_insert {
232- return Err ( ParsePatchErrorKind :: TooManyInsertedLines . into ( ) ) ;
248+ return Err ( parser . error ( ParsePatchErrorKind :: TooManyInsertedLines ) ) ;
233249 }
234250 Line :: Insert ( line)
235251 } else if line. starts_with ( NO_NEWLINE_AT_EOF ) {
236252 let last_line = lines
237253 . pop ( )
238- . ok_or ( ParsePatchErrorKind :: UnexpectedNoNewlineMarker ) ?;
254+ . ok_or_else ( || parser . error ( ParsePatchErrorKind :: UnexpectedNoNewlineMarker ) ) ?;
239255 match last_line {
240256 Line :: Context ( line) => {
241257 no_newline_context = true ;
@@ -251,7 +267,7 @@ fn hunk_lines<'a, T: Text + ?Sized>(parser: &mut Parser<'a, T>) -> Result<Vec<Li
251267 }
252268 }
253269 } else {
254- return Err ( ParsePatchErrorKind :: UnexpectedHunkLine . into ( ) ) ;
270+ return Err ( parser . error ( ParsePatchErrorKind :: UnexpectedHunkLine ) ) ;
255271 } ;
256272
257273 lines. push ( line) ;
0 commit comments