1use std::ops::Range;
15
16use serde::{
17 Deserialize, Serialize,
18 de::{self, Visitor},
19 ser::SerializeStruct,
20};
21
22use super::{Point, Text};
23
24#[derive(Default, Debug, Clone, Serialize, Deserialize)]
26pub struct History {
27 moments: Vec<Moment>,
28 cur_moment: usize,
29 new_moment: Option<(Moment, SyncState)>,
30 unproc_moment: Option<(Moment, SyncState)>,
32}
33
34impl History {
35 pub fn new() -> Self {
37 Self::default()
38 }
39
40 pub fn add_change(&mut self, guess_i: Option<usize>, change: Change<String>) -> usize {
51 let (unproc_moment, unproc_ss) = self.unproc_moment.get_or_insert_default();
52 unproc_moment.add_change(guess_i, change.clone(), unproc_ss);
53
54 let (new_moment, new_ss) = self.new_moment.get_or_insert_default();
55 new_moment.add_change(guess_i, change, new_ss)
56 }
57
58 pub fn new_moment(&mut self) {
61 let Some((mut new_moment, mut new_ss)) = self.new_moment.take() else {
62 return;
63 };
64 finish_synchronizing(&mut new_moment, &mut new_ss);
65
66 self.moments.truncate(self.cur_moment);
67 self.moments.push(new_moment);
68 self.cur_moment += 1;
69 }
70
71 pub fn move_forward(&mut self) -> Option<Vec<Change<&str>>> {
76 self.new_moment();
77 if self.cur_moment == self.moments.len() {
78 None
79 } else {
80 self.cur_moment += 1;
81 Some(
82 self.moments[self.cur_moment - 1]
83 .0
84 .iter()
85 .map(|c| c.as_ref())
86 .collect(),
87 )
88 }
89 }
90
91 pub fn move_backwards(&mut self) -> Option<Vec<Change<&str>>> {
97 self.new_moment();
98 if self.cur_moment == 0 {
99 None
100 } else {
101 self.cur_moment -= 1;
102
103 let mut shift = (0, 0, 0);
104 let iter = self.moments[self.cur_moment].0.iter().map(move |c| {
105 let mut change = c.as_ref();
106 change.shift_by(shift);
107
108 shift.0 += change.taken_end().byte() as i32 - change.added_end().byte() as i32;
109 shift.1 += change.taken_end().char() as i32 - change.added_end().char() as i32;
110 shift.2 += change.taken_end().line() as i32 - change.added_end().line() as i32;
111
112 change.reverse()
113 });
114 Some(iter.collect())
115 }
116 }
117
118 pub fn unprocessed_changes(&mut self) -> Option<Vec<Change<String>>> {
119 self.unproc_moment
120 .take()
121 .map(|(c, _)| c.0.into_iter().collect())
122 }
123
124 pub fn has_unprocessed_changes(&self) -> bool {
125 self.unproc_moment.as_ref().is_some()
126 }
127}
128
129#[derive(Default, Debug, Clone, Serialize, Deserialize)]
135pub struct Moment(Vec<Change<String>>);
136
137impl Moment {
138 fn add_change(
157 &mut self,
158 guess_i: Option<usize>,
159 change: Change<String>,
160 ss: &mut SyncState,
161 ) -> usize {
162 let (shift, sh_from) = (ss.shift, ss.sh_from);
163 let b = change.added_end().byte() as i32 - change.taken_end().byte() as i32;
164 let c = change.added_end().char() as i32 - change.taken_end().char() as i32;
165 let l = change.added_end().line() as i32 - change.taken_end().line() as i32;
166
167 let (change_i, sh_from) = match self.add_change_inner(guess_i, change, shift, sh_from) {
168 Ok((change_i, sh_from)) => (change_i, sh_from),
169 Err((guess_i, change)) => {
174 finish_synchronizing(self, ss);
175 *ss = SyncState::default();
176 self.add_change_inner(Some(guess_i), change, (0, 0, 0), 0)
177 .unwrap()
178 }
179 };
180 ss.sh_from = sh_from;
181 ss.shift.0 += b;
182 ss.shift.1 += c;
183 ss.shift.2 += l;
184
185 change_i
186 }
187
188 fn add_change_inner(
190 &mut self,
191 guess_i: Option<usize>,
192 mut change: Change<String>,
193 shift: (i32, i32, i32),
194 sh_from: usize,
195 ) -> Result<(usize, usize), (usize, Change<String>)> {
196 let sh = |n: usize| if sh_from <= n { shift } else { (0, 0, 0) };
197
198 let c_range = if let Some(guess_i) = guess_i
200 && let Some(c) = self.0.get(guess_i)
201 && c.start.shift_by(sh(guess_i)) <= change.start
202 && change.start <= c.added_end().shift_by(sh(guess_i))
203 {
204 guess_i..guess_i + 1
206 } else {
207 let f = |i: usize, c: &Change<String>| c.start.shift_by(sh(i));
208 match binary_search_by_key_and_index(&self.0, change.start, f) {
209 Ok(i) => i..i + 1,
211 Err(i) => {
212 if let Some(older_i) = i.checked_sub(1)
214 && change.start <= self.0[older_i].added_end().shift_by(sh(older_i))
215 {
216 older_i..i
217 } else {
220 i..i
221 }
222 }
223 }
224 };
225
226 if c_range.start < sh_from {
227 return Err((c_range.start, change));
228 }
229
230 let c_range = if self
232 .0
233 .get(c_range.end)
234 .is_none_or(|c| change.taken_end() < c.start.shift_by(sh(c_range.end)))
235 {
236 c_range
238 } else {
239 let start_i = c_range.start + 1;
240 let f = |i: usize, c: &Change<String>| c.start.shift_by(sh(start_i + i));
242 match binary_search_by_key_and_index(&self.0[start_i..], change.taken_end(), f) {
243 Ok(i) => c_range.start..start_i + i + 1,
244 Err(i) => {
245 if let Some(older) = self.0.get(start_i + i)
246 && older.start.shift_by(sh(start_i + i)) <= change.taken_end()
247 {
248 c_range.start..start_i + i + 1
249 } else {
250 c_range.start..start_i + i
251 }
252 }
253 }
254 };
256
257 if shift != (0, 0, 0) && sh_from < c_range.end {
259 for change in &mut self.0[sh_from..c_range.end] {
260 change.shift_by(shift);
261 }
262 }
263
264 for c in self.0.drain(c_range.clone()).rev() {
265 change.try_merge(c);
266 }
267
268 let sh_from = if !(change.added_text() == "" && change.taken_text() == "") {
269 self.0.insert(c_range.start, change);
270 c_range.start + 1
271 } else {
272 c_range.start
273 };
274
275 Ok((c_range.start, sh_from))
276 }
277
278 pub fn changes(&self) -> &[Change<String>] {
279 &self.0
280 }
281}
282
283#[derive(Default, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
285pub struct Change<S: AsRef<str>> {
286 start: Point,
287 added: S,
288 taken: S,
289}
290
291impl Change<String> {
292 pub fn new(edit: impl ToString, (start, end): (Point, Point), text: &Text) -> Self {
294 let added = edit.to_string();
295 let taken: String = text.strs_in(start.byte()..end.byte()).collect();
296 Change { start, added, taken }
297 }
298
299 pub fn as_ref(&self) -> Change<&str> {
301 Change {
302 start: self.start,
303 added: &self.added,
304 taken: &self.taken,
305 }
306 }
307
308 pub fn try_merge(&mut self, mut older: Self) {
313 if has_start_of(older.added_range(), self.taken_range()) {
314 let fixed_end = older.added_end().min(self.taken_end());
315
316 let start = self.start - older.start;
317 let end = fixed_end - older.start;
318 let range = start.byte()..end.byte();
319 older.added.replace_range(range, &self.added);
320
321 let range = (fixed_end.byte() - self.start.byte())..;
322 older.taken.push_str(&self.taken[range]);
323
324 *self = older;
325 } else if has_start_of(self.taken_range(), older.added_range()) {
326 let fixed_end = self.taken_end().min(older.added_end());
327
328 let start = older.start - self.start;
329 let end = fixed_end - self.start;
330 let range = start.byte()..end.byte();
331 self.taken.replace_range(range, &older.taken);
332
333 let range = (fixed_end.byte() - older.start.byte())..;
334 self.added.push_str(&older.added[range]);
335 } else {
336 unreachable!("Files chosen that don't interact");
337 }
338 }
339}
340
341impl<'a> Change<&'a str> {
342 pub fn str_insert(added_text: &'a str, start: Point) -> Self {
344 Self { start, added: added_text, taken: "" }
345 }
346}
347
348impl<S: AsRef<str>> Change<S> {
349 pub fn reverse(self) -> Change<S> {
351 Change {
352 start: self.start,
353 added: self.taken,
354 taken: self.added,
355 }
356 }
357
358 pub fn start(&self) -> Point {
360 self.start
361 }
362
363 pub(crate) fn shift_by(&mut self, shift: (i32, i32, i32)) {
365 self.start = self.start.shift_by(shift);
366 }
367
368 pub fn taken_end(&self) -> Point {
370 self.start + Point::len_of(&self.taken)
371 }
372
373 pub fn added_end(&self) -> Point {
375 self.start + Point::len_of(&self.added)
376 }
377
378 pub fn taken_range(&self) -> Range<usize> {
380 self.start.byte()..self.taken_end().byte()
381 }
382
383 pub fn added_range(&self) -> Range<usize> {
385 self.start.byte()..self.added_end().byte()
386 }
387
388 pub fn added_text(&self) -> &str {
390 self.added.as_ref()
391 }
392
393 pub fn taken_text(&self) -> &str {
395 self.taken.as_ref()
396 }
397
398 pub fn chars_diff(&self) -> i32 {
400 self.added.as_ref().chars().count() as i32 - self.taken.as_ref().chars().count() as i32
401 }
402}
403
404impl Copy for Change<&str> {}
405
406impl Serialize for Change<String> {
407 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
408 where
409 S: serde::Serializer,
410 {
411 let mut ser_change = serializer.serialize_struct("Change", 3)?;
412
413 ser_change.serialize_field("start", &self.start)?;
414 ser_change.serialize_field("added", &self.added)?;
415 ser_change.serialize_field("taken", &self.taken)?;
416
417 ser_change.end()
418 }
419}
420
421impl<'de> Deserialize<'de> for Change<String> {
422 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
423 where
424 D: serde::Deserializer<'de>,
425 {
426 static FIELDS: [&str; 3] = ["start", "added", "taken"];
427 struct ChangeVisitor;
428
429 impl<'de> Visitor<'de> for ChangeVisitor {
430 type Value = Change<String>;
431
432 fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
433 formatter.write_str("struct Change")
434 }
435
436 fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
437 where
438 A: de::SeqAccess<'de>,
439 {
440 let start = seq
441 .next_element()?
442 .ok_or(de::Error::invalid_length(0, &self))?;
443 let added = seq
444 .next_element()?
445 .ok_or(de::Error::invalid_length(1, &self))?;
446 let taken = seq
447 .next_element()?
448 .ok_or(de::Error::invalid_length(2, &self))?;
449 Ok(Change { start, added, taken })
450 }
451 }
452
453 deserializer.deserialize_struct("Change", &FIELDS, ChangeVisitor)
454 }
455}
456
457fn has_start_of(lhs: Range<usize>, rhs: Range<usize>) -> bool {
459 lhs.start <= rhs.start && rhs.start <= lhs.end
460}
461
462#[derive(Default, Debug, Clone, Serialize, Deserialize)]
463struct SyncState {
464 shift: (i32, i32, i32),
465 sh_from: usize,
466}
467
468fn binary_search_by_key_and_index<T, K>(
470 vec: &[T],
471 key: K,
472 f: impl Fn(usize, &T) -> K,
473) -> std::result::Result<usize, usize>
474where
475 K: PartialEq + Eq + PartialOrd + Ord,
476{
477 let mut size = vec.len();
478 let mut left = 0;
479 let mut right = size;
480
481 while left < right {
482 let mid = left + size / 2;
483
484 let k = f(mid, &vec[mid]);
485
486 match k.cmp(&key) {
487 std::cmp::Ordering::Less => left = mid + 1,
488 std::cmp::Ordering::Equal => return Ok(mid),
489 std::cmp::Ordering::Greater => right = mid,
490 }
491
492 size = right - left;
493 }
494
495 Err(left)
496}
497
498fn finish_synchronizing(moment: &mut Moment, ss: &mut SyncState) {
500 if ss.shift != (0, 0, 0) {
501 for change in &mut moment.0[ss.sh_from..] {
503 change.shift_by(ss.shift);
504 }
505 }
506}