fast_pull/base/
merge_progress.rs1use crate::{Mergeable, ProgressEntry};
2
3pub trait MergeProgress {
4 fn merge_progress(&mut self, new: ProgressEntry);
5}
6
7impl MergeProgress for Vec<ProgressEntry> {
8 fn merge_progress(&mut self, new: ProgressEntry) {
9 let i = self.partition_point(|old| old.start < new.start);
10 if i == self.len() {
11 match self.last_mut() {
12 Some(last) if last.end == new.start => {
13 last.end = new.end;
14 }
15 _ => self.push(new),
16 }
17 } else {
18 let u1 = if i == 0 {
19 false
20 } else {
21 self[i - 1].can_merge(&new)
22 };
23 let u2 = self[i].can_merge(&new);
24 if u1 && u2 {
25 self[i - 1].end = self[i].end;
26 self.remove(i);
27 } else if u1 {
28 self[i - 1].end = new.end;
29 } else if u2 {
30 self[i].start = new.start;
31 } else {
32 self.insert(i, new);
33 }
34 }
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn test_merge_into_empty_vec() {
44 let mut v: Vec<ProgressEntry> = Vec::new();
45 v.merge_progress(10..20);
46 assert_eq!(v, vec![10..20]);
47 }
48
49 #[test]
50 fn test_append_non_overlapping() {
51 #[allow(clippy::single_range_in_vec_init)]
52 let mut v = vec![1..5];
53 v.merge_progress(6..10);
54 assert_eq!(v, vec![1..5, 6..10]);
55 }
56
57 #[test]
58 fn test_prepend_non_overlapping() {
59 #[allow(clippy::single_range_in_vec_init)]
60 let mut v = vec![6..10];
61 v.merge_progress(1..5);
62 assert_eq!(v, vec![1..5, 6..10]);
63 }
64
65 #[test]
66 fn test_merge_with_last() {
67 #[allow(clippy::single_range_in_vec_init)]
68 let mut v = vec![1..5];
69 v.merge_progress(5..10);
70 assert_eq!(v, vec![1..10]);
71 }
72
73 #[test]
74 fn test_insert_between_two() {
75 let mut v = vec![1..5, 10..15];
76 v.merge_progress(6..8);
77 assert_eq!(v, vec![1..5, 6..8, 10..15]);
78 }
79
80 #[test]
81 fn test_merge_adjacent() {
82 #[allow(clippy::single_range_in_vec_init)]
83 let mut v = vec![1..5];
84 v.merge_progress(5..10);
85 assert_eq!(v, vec![1..10]);
86 }
87}