diffy_fork_filenames/diff/
cleanup.rs1use crate::range::{DiffRange, SliceLike};
2
3#[allow(clippy::needless_lifetimes)]
6pub fn compact<'a, 'b, T: ?Sized + SliceLike>(diffs: &mut Vec<DiffRange<'a, 'b, T>>) {
7 let mut pointer = 0;
9 while let Some(&diff) = diffs.get(pointer) {
10 if let DiffRange::Delete(_) = diff {
11 pointer = shift_diff_up(diffs, pointer);
12 pointer = shift_diff_down(diffs, pointer);
13 }
14 pointer += 1;
15 }
16
17 let mut pointer = 0;
20 while let Some(&diff) = diffs.get(pointer) {
21 if let DiffRange::Insert(_) = diff {
22 pointer = shift_diff_up(diffs, pointer);
23 pointer = shift_diff_down(diffs, pointer);
24 }
25 pointer += 1;
26 }
27}
28
29#[allow(clippy::needless_lifetimes)]
31fn shift_diff_up<'a, 'b, T: ?Sized + SliceLike>(
32 diffs: &mut Vec<DiffRange<'a, 'b, T>>,
33 mut pointer: usize,
34) -> usize {
35 while let Some(&prev_diff) = pointer.checked_sub(1).and_then(|idx| diffs.get(idx)) {
36 match (diffs[pointer], prev_diff) {
37 (DiffRange::Insert(this_diff), DiffRange::Equal(prev_diff1, _)) => {
41 let suffix_len = this_diff.common_suffix_len(prev_diff1);
43 if suffix_len != 0 {
44 if let Some(DiffRange::Equal(..)) = diffs.get(pointer + 1) {
45 diffs[pointer + 1].grow_up(suffix_len);
46 } else {
47 diffs.insert(
48 pointer + 1,
49 DiffRange::Equal(
50 prev_diff1.slice(prev_diff1.len() - suffix_len..),
51 this_diff.slice(this_diff.len() - suffix_len..),
52 ),
53 );
54 }
55 diffs[pointer].shift_up(suffix_len);
56 diffs[pointer - 1].shrink_back(suffix_len);
57
58 if diffs[pointer - 1].is_empty() {
59 diffs.remove(pointer - 1);
60 pointer -= 1;
61 }
62 } else if diffs[pointer - 1].is_empty() {
63 diffs.remove(pointer - 1);
64 pointer -= 1;
65 } else {
66 break;
68 }
69 }
70
71 (DiffRange::Delete(this_diff), DiffRange::Equal(_, prev_diff2)) => {
75 let suffix_len = this_diff.common_suffix_len(prev_diff2);
77 if suffix_len != 0 {
78 if let Some(DiffRange::Equal(..)) = diffs.get(pointer + 1) {
79 diffs[pointer + 1].grow_up(suffix_len);
80 } else {
81 diffs.insert(
82 pointer + 1,
83 DiffRange::Equal(
84 this_diff.slice(this_diff.len() - suffix_len..),
85 prev_diff2.slice(prev_diff2.len() - suffix_len..),
86 ),
87 );
88 }
89 diffs[pointer].shift_up(suffix_len);
90 diffs[pointer - 1].shrink_back(suffix_len);
91
92 if diffs[pointer - 1].is_empty() {
93 diffs.remove(pointer - 1);
94 pointer -= 1;
95 }
96 } else if diffs[pointer - 1].is_empty() {
97 diffs.remove(pointer - 1);
98 pointer -= 1;
99 } else {
100 break;
102 }
103 }
104
105 (DiffRange::Insert(_), DiffRange::Delete(_))
109 | (DiffRange::Delete(_), DiffRange::Insert(_)) => {
110 diffs.swap(pointer - 1, pointer);
111 pointer -= 1;
112 }
113
114 (this_diff @ DiffRange::Insert(_), DiffRange::Insert(_))
118 | (this_diff @ DiffRange::Delete(_), DiffRange::Delete(_)) => {
119 diffs[pointer - 1].grow_down(this_diff.len());
120 diffs.remove(pointer);
121 pointer -= 1;
122 }
123
124 _ => panic!("range to shift must be either Insert or Delete"),
125 }
126 }
127
128 pointer
129}
130
131#[allow(clippy::needless_lifetimes)]
133fn shift_diff_down<'a, 'b, T: ?Sized + SliceLike>(
134 diffs: &mut Vec<DiffRange<'a, 'b, T>>,
135 mut pointer: usize,
136) -> usize {
137 while let Some(&next_diff) = pointer.checked_add(1).and_then(|idx| diffs.get(idx)) {
138 match (diffs[pointer], next_diff) {
139 (DiffRange::Insert(this_diff), DiffRange::Equal(next_diff1, _)) => {
143 let prefix_len = this_diff.common_prefix_len(next_diff1);
145 if prefix_len != 0 {
146 if let Some(DiffRange::Equal(..)) =
147 pointer.checked_sub(1).and_then(|idx| diffs.get(idx))
148 {
149 diffs[pointer - 1].grow_down(prefix_len);
150 } else {
151 diffs.insert(
152 pointer,
153 DiffRange::Equal(
154 next_diff1.slice(..prefix_len),
155 this_diff.slice(..prefix_len),
156 ),
157 );
158 pointer += 1;
159 }
160
161 diffs[pointer].shift_down(prefix_len);
162 diffs[pointer + 1].shrink_front(prefix_len);
163
164 if diffs[pointer + 1].is_empty() {
165 diffs.remove(pointer + 1);
166 }
167 } else if diffs[pointer + 1].is_empty() {
168 diffs.remove(pointer + 1);
169 } else {
170 break;
172 }
173 }
174
175 (DiffRange::Delete(this_diff), DiffRange::Equal(_, next_diff2)) => {
179 let prefix_len = this_diff.common_prefix_len(next_diff2);
181 if prefix_len != 0 {
182 if let Some(DiffRange::Equal(..)) =
183 pointer.checked_sub(1).and_then(|idx| diffs.get(idx))
184 {
185 diffs[pointer - 1].grow_down(prefix_len);
186 } else {
187 diffs.insert(
188 pointer,
189 DiffRange::Equal(
190 this_diff.slice(..prefix_len),
191 next_diff2.slice(..prefix_len),
192 ),
193 );
194 pointer += 1;
195 }
196
197 diffs[pointer].shift_down(prefix_len);
198 diffs[pointer + 1].shrink_front(prefix_len);
199
200 if diffs[pointer + 1].is_empty() {
201 diffs.remove(pointer + 1);
202 }
203 } else if diffs[pointer + 1].is_empty() {
204 diffs.remove(pointer + 1);
205 } else {
206 break;
208 }
209 }
210
211 (DiffRange::Insert(_), DiffRange::Delete(_))
215 | (DiffRange::Delete(_), DiffRange::Insert(_)) => {
216 diffs.swap(pointer, pointer + 1);
217 pointer += 1;
218 }
219
220 (DiffRange::Insert(_), next_diff @ DiffRange::Insert(_))
224 | (DiffRange::Delete(_), next_diff @ DiffRange::Delete(_)) => {
225 diffs[pointer].grow_down(next_diff.len());
226 diffs.remove(pointer + 1);
227 }
228
229 _ => panic!("range to shift must be either Insert or Delete"),
230 }
231 }
232
233 pointer
234}