@@ -82,37 +82,6 @@ impl SubAssign<u32> for Offset {
8282 }
8383}
8484
85- #[ derive( Clone , Copy , Debug ) ]
86- struct LineRange {
87- start : u32 ,
88- end : u32 ,
89- }
90-
91- impl LineRange {
92- fn with_offset ( range : Range < u32 > , offset : Offset ) -> Self {
93- match offset {
94- Offset :: Added ( added) => {
95- assert ! ( range. start >= added, "{range:?} {offset:?}" ) ;
96-
97- Self {
98- start : range. start - added,
99- end : range. end - added,
100- }
101- }
102- Offset :: Deleted ( deleted) => Self {
103- start : range. start + deleted,
104- end : range. end + deleted,
105- } ,
106- }
107- }
108- }
109-
110- impl From < LineRange > for Range < u32 > {
111- fn from ( line_range : LineRange ) -> Self {
112- line_range. start ..line_range. end
113- }
114- }
115-
11685#[ derive( Debug , PartialEq ) ]
11786pub struct BlameEntry {
11887 pub range_in_blamed_file : Range < u32 > ,
@@ -173,6 +142,12 @@ pub struct UnblamedHunk {
173142 pub range_in_destination : Range < u32 > ,
174143}
175144
145+ #[ derive( Debug ) ]
146+ enum Either < T , U > {
147+ Left ( T ) ,
148+ Right ( U ) ,
149+ }
150+
176151impl UnblamedHunk {
177152 pub fn new ( range_in_blamed_file : Range < u32 > , offset : Offset ) -> Self {
178153 assert ! (
@@ -231,6 +206,22 @@ impl UnblamedHunk {
231206 Self :: new ( self . range_in_blamed_file . clone ( ) , combined_offset)
232207 }
233208
209+ fn split_at ( self , line_number_in_destination : u32 ) -> Either < Self , ( Self , Self ) > {
210+ if line_number_in_destination > self . range_in_destination . start
211+ && line_number_in_destination < self . range_in_destination . end
212+ {
213+ let first_range_in_destination = self . range_in_destination . start ..line_number_in_destination;
214+ let second_range_in_destination = line_number_in_destination..self . range_in_destination . end ;
215+
216+ Either :: Right ( (
217+ Self :: from_destination ( first_range_in_destination, self . offset ( ) ) ,
218+ Self :: from_destination ( second_range_in_destination, self . offset ( ) ) ,
219+ ) )
220+ } else {
221+ Either :: Left ( self )
222+ }
223+ }
224+
234225 fn offset ( & self ) -> Offset {
235226 if self . range_in_blamed_file . start > self . range_in_destination . start {
236227 Offset :: Added ( self . range_in_blamed_file . start - self . range_in_destination . start )
@@ -379,59 +370,48 @@ pub fn process_change(
379370 // <---> (added)
380371 // <---> (blamed)
381372 // <--> <-> (new hunk)
382- if added. start > hunk. range_in_destination . start {
383- let line_range_in_next_destination = LineRange :: with_offset (
384- hunk. range_in_destination . start ..added. start ,
385- * offset_in_destination,
386- ) ;
387-
388- new_hunks_to_blame. push ( UnblamedHunk :: from_destination (
389- line_range_in_next_destination. into ( ) ,
390- hunk. offset ( ) + * offset_in_destination,
391- ) ) ;
392- }
373+
374+ let new_hunk = match hunk. split_at ( added. start ) {
375+ Either :: Left ( hunk) => hunk,
376+ Either :: Right ( ( before, after) ) => {
377+ new_hunks_to_blame. push ( before. shift_by ( * offset_in_destination) ) ;
378+
379+ after
380+ }
381+ } ;
393382
394383 * offset_in_destination += added. end - added. start ;
395384 * offset_in_destination -= number_of_lines_deleted;
396385
397- out. push ( BlameEntry :: with_offset ( added. clone ( ) , suspect, hunk. offset ( ) ) ) ;
398-
399- let new_hunk = if hunk. range_in_destination . end > added. end {
400- Some ( UnblamedHunk :: from_destination (
401- added. end ..hunk. range_in_destination . end ,
402- hunk. offset ( ) ,
403- ) )
404- } else {
405- None
406- } ;
386+ out. push ( BlameEntry :: with_offset ( added. clone ( ) , suspect, new_hunk. offset ( ) ) ) ;
407387
408- ( new_hunk, None )
388+ match new_hunk. split_at ( added. end ) {
389+ Either :: Left ( _) => ( None , None ) ,
390+ Either :: Right ( ( _, after) ) => ( Some ( after) , None ) ,
391+ }
409392 }
410393 ( true , false ) => {
411394 // <--------> (hunk)
412395 // <-------> (added)
413396 // <----> (blamed)
414397 // <--> (new hunk)
415398
416- if added. start > hunk. range_in_destination . start {
417- let line_range_in_next_destination = LineRange :: with_offset (
418- hunk. range_in_destination . start ..added. start ,
419- * offset_in_destination,
420- ) ;
399+ let new_hunk = match hunk. split_at ( added. start ) {
400+ Either :: Left ( hunk) => hunk,
401+ Either :: Right ( ( before, after) ) => {
402+ new_hunks_to_blame. push ( before. shift_by ( * offset_in_destination) ) ;
421403
422- new_hunks_to_blame. push ( UnblamedHunk :: from_destination (
423- line_range_in_next_destination. into ( ) ,
424- hunk. offset ( ) + * offset_in_destination,
425- ) ) ;
426- }
404+ after
405+ }
406+ } ;
427407
428408 out. push ( BlameEntry :: with_offset (
429- added. start ..hunk . range_in_destination . end ,
409+ added. start ..new_hunk . range_in_destination . end ,
430410 suspect,
431- hunk . offset ( ) ,
411+ new_hunk . offset ( ) ,
432412 ) ) ;
433413
434- if added. end > hunk . range_in_destination . end {
414+ if added. end > new_hunk . range_in_destination . end {
435415 ( None , Some ( Change :: Added ( added, number_of_lines_deleted) ) )
436416 } else {
437417 todo ! ( ) ;
@@ -452,16 +432,10 @@ pub fn process_change(
452432 * offset_in_destination += added. end - added. start ;
453433 * offset_in_destination -= number_of_lines_deleted;
454434
455- let new_hunk = if hunk. range_in_destination . end > added. end {
456- Some ( UnblamedHunk :: from_destination (
457- added. end ..hunk. range_in_destination . end ,
458- hunk. offset ( ) ,
459- ) )
460- } else {
461- None
462- } ;
463-
464- ( new_hunk, None )
435+ match hunk. split_at ( added. end ) {
436+ Either :: Left ( _) => ( None , None ) ,
437+ Either :: Right ( ( _, after) ) => ( Some ( after) , None ) ,
438+ }
465439 }
466440 ( false , false ) => {
467441 // Any of the following cases are handled by this branch:
@@ -517,26 +491,18 @@ pub fn process_change(
517491 // <-----> (hunk)
518492 // | (line_number_in_destination)
519493
520- if hunk. range_in_destination . start < line_number_in_destination {
521- let line_range_in_next_destination = LineRange :: with_offset (
522- hunk. range_in_destination . start ..line_number_in_destination,
523- * offset_in_destination,
524- ) ;
494+ let new_hunk = match hunk. split_at ( line_number_in_destination) {
495+ Either :: Left ( hunk) => hunk,
496+ Either :: Right ( ( before, after) ) => {
497+ new_hunks_to_blame. push ( before. shift_by ( * offset_in_destination) ) ;
525498
526- new_hunks_to_blame. push ( UnblamedHunk :: from_destination (
527- line_range_in_next_destination. into ( ) ,
528- hunk. offset ( ) + * offset_in_destination,
529- ) ) ;
530- }
499+ after
500+ }
501+ } ;
531502
532503 * offset_in_destination -= number_of_lines_deleted;
533504
534- let new_hunk = Some ( UnblamedHunk :: from_destination (
535- line_number_in_destination..hunk. range_in_destination . end ,
536- hunk. offset ( ) ,
537- ) ) ;
538-
539- ( new_hunk, None )
505+ ( Some ( new_hunk) , None )
540506 } else {
541507 // <---> (hunk)
542508 // | (line_number_in_destination)
0 commit comments