1use std::ops::Range;
15
16use bincode::{Decode, Encode};
17use parking_lot::Mutex;
18
19use super::{Point, Text};
20use crate::{add_shifts, merging_range_by_guess_and_lazy_shift};
21
22#[derive(Default, Debug)]
24pub struct History {
25 moments: Vec<Moment>,
26 cur_moment: usize,
27 new_changes: Option<(Vec<Change>, (usize, [i32; 3]))>,
28 unproc_changes: Mutex<Option<(Vec<Change>, (usize, [i32; 3]))>>,
30 unproc_moments: Mutex<Vec<Moment>>,
31}
32
33impl History {
34 pub fn new() -> Self {
36 Self::default()
37 }
38
39 pub fn apply_change(&mut self, guess_i: Option<usize>, change: Change) -> usize {
41 let (changes, shift_state) = self.unproc_changes.get_mut().get_or_insert_default();
42 add_change(changes, guess_i, change.clone(), shift_state);
43
44 let (changes, shift_state) = self.new_changes.get_or_insert_default();
45 add_change(changes, guess_i, change, shift_state)
46 }
47
48 pub fn new_moment(&mut self) {
51 let Some((mut new_changes, (sh_from, shift))) = self.new_changes.take() else {
52 return;
53 };
54 finish_shifting(&mut new_changes, sh_from, shift);
55
56 if let Some((mut unproc_changes, (sh_from, shift))) = self.unproc_changes.get_mut().take() {
57 finish_shifting(&mut unproc_changes, sh_from, shift);
58 self.unproc_moments.get_mut().push(Moment {
59 changes: Box::leak(Box::from(unproc_changes)),
60 is_rev: false,
61 });
62 }
63
64 self.moments.truncate(self.cur_moment);
65
66 self.moments.push(Moment {
67 changes: Box::leak(Box::from(new_changes)),
68 is_rev: false,
69 });
70 self.cur_moment += 1;
71 }
72
73 pub fn move_forward(&mut self) -> Option<Moment> {
78 self.new_moment();
79 if self.cur_moment == self.moments.len() {
80 None
81 } else {
82 self.cur_moment += 1;
83
84 let moment = self.moments[self.cur_moment - 1];
85 self.unproc_moments.get_mut().push(moment);
86
87 Some(moment)
88 }
89 }
90
91 pub fn move_backwards(&mut self) -> Option<Moment> {
97 self.new_moment();
98 if self.cur_moment == 0 {
99 None
100 } else {
101 self.cur_moment -= 1;
102
103 let mut moment = self.moments[self.cur_moment];
104 moment.is_rev = true;
105 self.unproc_moments.get_mut().push(moment);
106
107 Some(moment)
108 }
109 }
110
111 pub(crate) fn unprocessed_moments(&self) -> Vec<Moment> {
113 let fresh_moment =
114 self.unproc_changes
115 .lock()
116 .take()
117 .map(|(mut changes, (sh_from, shift))| {
118 finish_shifting(&mut changes, sh_from, shift);
119
120 Moment {
121 changes: Box::leak(Box::from(changes)),
122 is_rev: false,
123 }
124 });
125
126 let mut unproc_moments = self.unproc_moments.lock();
127
128 unproc_moments.extend(fresh_moment);
129
130 std::mem::take(&mut unproc_moments)
131 }
132}
133
134impl Encode for History {
135 fn encode<E: bincode::enc::Encoder>(
136 &self,
137 encoder: &mut E,
138 ) -> Result<(), bincode::error::EncodeError> {
139 Encode::encode(&self.moments, encoder)?;
140 Encode::encode(&self.cur_moment, encoder)?;
141 Encode::encode(&self.new_changes, encoder)?;
142 Encode::encode(&*self.unproc_changes.lock(), encoder)?;
143 Encode::encode(&*self.unproc_moments.lock(), encoder)?;
144 Ok(())
145 }
146}
147
148impl<Context> Decode<Context> for History {
149 fn decode<D: bincode::de::Decoder<Context = Context>>(
150 decoder: &mut D,
151 ) -> Result<Self, bincode::error::DecodeError> {
152 Ok(History {
153 moments: Decode::decode(decoder)?,
154 cur_moment: Decode::decode(decoder)?,
155 new_changes: Decode::decode(decoder)?,
156 unproc_changes: Mutex::new(Decode::decode(decoder)?),
157 unproc_moments: Mutex::new(Decode::decode(decoder)?),
158 })
159 }
160}
161
162impl Clone for History {
163 fn clone(&self) -> Self {
164 Self {
165 moments: self.moments.clone(),
166 cur_moment: self.cur_moment,
167 new_changes: self.new_changes.clone(),
168 unproc_changes: Mutex::new(self.unproc_changes.lock().clone()),
169 unproc_moments: Mutex::new(self.unproc_moments.lock().clone()),
170 }
171 }
172}
173
174#[derive(Clone, Copy, Default, Debug, Encode)]
180pub struct Moment {
181 changes: &'static [Change],
182 is_rev: bool,
183}
184
185impl Moment {
186 pub fn changes(&self) -> impl ExactSizeIterator<Item = Change<&str>> + '_ {
191 let mut shift = [0; 3];
192 self.changes.iter().map(move |change| {
193 if self.is_rev {
194 let mut change = change.as_ref().reverse();
195 change.shift_by(shift);
196
197 shift = add_shifts(shift, change.shift());
198
199 change
200 } else {
201 change.as_ref()
202 }
203 })
204 }
205
206 pub fn len(&self) -> usize {
216 self.changes.len()
217 }
218
219 #[must_use]
223 pub fn is_empty(&self) -> bool {
224 self.len() == 0
225 }
226}
227
228impl<Context> Decode<Context> for Moment {
229 fn decode<D: bincode::de::Decoder<Context = Context>>(
230 decoder: &mut D,
231 ) -> Result<Self, bincode::error::DecodeError> {
232 Ok(Moment {
233 changes: Vec::decode(decoder)?.leak(),
234 is_rev: Decode::decode(decoder)?,
235 })
236 }
237}
238
239fn add_change(
242 changes: &mut Vec<Change>,
243 guess_i: Option<usize>,
244 mut change: Change,
245 shift_state: &mut (usize, [i32; 3]),
246) -> usize {
247 let (sh_from, shift) = std::mem::take(shift_state);
248 let new_shift = change.shift();
249
250 let c_range = merging_range_by_guess_and_lazy_shift(
252 (changes, changes.len()),
253 (guess_i.unwrap_or(0), [change.start(), change.taken_end()]),
254 (sh_from, shift, [0; 3], Point::shift_by),
255 (Change::start, Change::added_end),
256 );
257
258 if sh_from < c_range.end && shift != [0; 3] {
261 for change in &mut changes[sh_from..c_range.end] {
262 change.shift_by(shift);
263 }
264 } else if sh_from > c_range.end && new_shift != [0; 3] {
271 let shift = change.shift();
272 for change in &mut changes[c_range.end..sh_from] {
273 change.shift_by(shift);
274 }
275 }
276
277 for c in changes.drain(c_range.clone()).rev() {
278 change.try_merge(c);
279 }
280
281 let changes_taken = c_range.clone().count();
282 let new_sh_from = if !(change.added_str() == "" && change.taken_str() == "") {
283 changes.insert(c_range.start, change);
284 sh_from.saturating_sub(changes_taken).max(c_range.start) + 1
285 } else {
286 sh_from.saturating_sub(changes_taken).max(c_range.start)
287 };
288 if new_sh_from < changes.len() {
290 let shift = add_shifts(shift, new_shift);
291 *shift_state = (new_sh_from, shift);
292 }
293
294 c_range.start
295}
296
297#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Encode, Decode)]
299pub struct Change<S = String> {
300 start: Point,
301 added: S,
302 taken: S,
303 added_end: Point,
304 taken_end: Point,
305}
306
307impl Change {
308 pub fn new(edit: impl ToString, [p0, p1]: [Point; 2], text: &Text) -> Self {
310 let added = {
311 let edit = edit.to_string();
312 if p1 == text.len() && !edit.ends_with('\n') {
314 edit + "\n"
315 } else {
316 edit
317 }
318 };
319
320 let taken = text.strs(p0..p1).unwrap().collect();
321 let added_end = p0 + Point::len_of(&added);
322 Change {
323 start: p0,
324 added,
325 taken,
326 added_end,
327 taken_end: p1,
328 }
329 }
330
331 pub fn as_ref(&self) -> Change<&str> {
333 Change {
334 start: self.start,
335 added: &self.added,
336 taken: &self.taken,
337 added_end: self.added_end,
338 taken_end: self.taken_end,
339 }
340 }
341
342 pub fn try_merge(&mut self, mut older: Self) {
347 if has_start_of(older.added_range(), self.taken_range()) {
348 let fixed_end = older.added_end().min(self.taken_end());
349
350 let start = self.start - older.start;
351 let end = fixed_end - older.start;
352 let range = start.byte()..end.byte();
353 older.added.replace_range(range, &self.added);
354
355 let range = (fixed_end.byte() - self.start.byte())..;
356 older.taken.push_str(&self.taken[range]);
357
358 *self = older;
359 } else if has_start_of(self.taken_range(), older.added_range()) {
360 let fixed_end = self.taken_end().min(older.added_end());
361
362 let start = older.start - self.start;
363 let end = fixed_end - self.start;
364 let range = start.byte()..end.byte();
365 self.taken.replace_range(range, &older.taken);
366
367 let range = (fixed_end.byte() - older.start.byte())..;
368
369 self.added.push_str(&older.added[range]);
370 } else {
371 unreachable!("Changes chosen that don't interact");
372 }
373 self.added_end = self.start + Point::len_of(&self.added);
374 self.taken_end = self.start + Point::len_of(&self.taken);
375 }
376}
377
378impl<'a> Change<&'a str> {
379 pub fn str_insert(added_str: &'a str, start: Point) -> Self {
381 Self {
382 start,
383 added: added_str,
384 taken: "",
385 added_end: start + Point::len_of(added_str),
386 taken_end: start,
387 }
388 }
389
390 pub(super) fn remove_last_nl(len: Point) -> Self {
391 Self {
392 start: len.rev('\n'),
393 added: "",
394 taken: "\n",
395 added_end: len.rev('\n'),
396 taken_end: len,
397 }
398 }
399}
400
401impl<S: std::borrow::Borrow<str>> Change<S> {
402 pub fn reverse(self) -> Change<S> {
404 Change {
405 start: self.start,
406 added: self.taken,
407 taken: self.added,
408 added_end: self.taken_end,
409 taken_end: self.added_end,
410 }
411 }
412
413 pub fn start(&self) -> Point {
415 self.start
416 }
417
418 pub(crate) fn shift_by(&mut self, shift: [i32; 3]) {
420 self.start = self.start.shift_by(shift);
421 self.added_end = self.added_end.shift_by(shift);
422 self.taken_end = self.taken_end.shift_by(shift);
423 }
424
425 pub fn taken_end(&self) -> Point {
427 self.taken_end
428 }
429
430 pub fn added_end(&self) -> Point {
432 self.added_end
433 }
434
435 pub fn taken_range(&self) -> Range<Point> {
437 self.start..self.taken_end()
438 }
439
440 pub fn added_range(&self) -> Range<Point> {
442 self.start..self.added_end()
443 }
444
445 pub fn added_str(&self) -> &str {
447 self.added.borrow()
448 }
449
450 pub fn taken_str(&self) -> &str {
452 self.taken.borrow()
453 }
454
455 pub fn shift(&self) -> [i32; 3] {
457 [
458 self.added_end().byte() as i32 - self.taken_end().byte() as i32,
459 self.added_end().char() as i32 - self.taken_end().char() as i32,
460 self.added_end().line() as i32 - self.taken_end().line() as i32,
461 ]
462 }
463}
464
465fn has_start_of(lhs: Range<Point>, rhs: Range<Point>) -> bool {
467 lhs.start <= rhs.start && rhs.start <= lhs.end
468}
469
470fn finish_shifting(changes: &mut [Change], sh_from: usize, shift: [i32; 3]) {
471 if shift != [0; 3] {
472 for change in changes[sh_from..].iter_mut() {
473 change.shift_by(shift);
474 }
475 }
476}