1use std::{marker::PhantomData, ops::Range, sync::Arc};
15
16use bincode::{BorrowDecode, Decode, Encode};
17use parking_lot::Mutex;
18
19use super::{Point, Text};
20use crate::{
21 text::Bytes,
22 utils::{add_shifts as add, merging_range_by_guess_and_lazy_shift},
23};
24
25#[derive(Default, Debug)]
27pub struct History {
28 new_moment: Moment,
29 moments: Vec<Moment>,
30 cur_moment: usize,
31 fetcher_moments: Arc<Mutex<Vec<FetcherState>>>,
32 saved_moment: Option<usize>,
33}
34
35impl History {
36 pub fn apply_change(
38 &mut self,
39 guess_i: Option<usize>,
40 change: Change<'static, String>,
41 ) -> usize {
42 let mut remote = self.fetcher_moments.lock();
43 for state in remote.iter_mut() {
44 state.add_change(change.clone());
45 }
46
47 self.new_moment.add_change(guess_i, change)
48 }
49
50 pub fn new_moment(&mut self) {
53 if self.new_moment.is_empty() {
54 return;
55 }
56
57 self.moments.truncate(self.cur_moment);
58
59 if let Some(saved_moment) = self.saved_moment
60 && saved_moment >= self.cur_moment
61 {
62 self.saved_moment = None;
63 }
64
65 self.moments.push(std::mem::take(&mut self.new_moment));
66 self.cur_moment += 1;
67 }
68
69 pub(super) fn move_forward(
74 &mut self,
75 ) -> Option<(impl ExactSizeIterator<Item = Change<'_>>, bool)> {
76 self.new_moment();
77 if self.cur_moment == self.moments.len() {
78 None
79 } else {
80 let mut remote = self.fetcher_moments.lock();
81 self.cur_moment += 1;
82
83 let iter = self.moments[self.cur_moment - 1]
84 .changes()
85 .inspect(move |change| {
86 for state in remote.iter_mut() {
87 state.add_change(change.to_string_change());
88 }
89 });
90
91 let is_saved = self.saved_moment.is_some_and(|m| m == self.cur_moment);
92 Some((iter, is_saved))
93 }
94 }
95
96 pub(super) fn move_backwards(
102 &mut self,
103 ) -> Option<(impl ExactSizeIterator<Item = Change<'_>>, bool)> {
104 self.new_moment();
105 if self.cur_moment == 0 {
106 None
107 } else {
108 let mut remote = self.fetcher_moments.lock();
109 self.cur_moment -= 1;
110
111 let mut shift = [0; 3];
112 let iter = self.moments[self.cur_moment].changes().map(move |change| {
113 let mut change = change.reverse();
114 change.shift_by(shift);
115 shift = add(shift, change.shift());
116
117 for state in remote.iter_mut() {
118 state.add_change(change.to_string_change());
119 }
120
121 change
122 });
123
124 let is_saved = self.saved_moment.is_some_and(|m| m == self.cur_moment);
125 Some((iter, is_saved))
126 }
127 }
128
129 pub(crate) fn new_fetcher(&self) -> MomentFetcher {
131 let mut remote = self.fetcher_moments.lock();
132 remote.push(FetcherState::Alive(Moment::default()));
133 MomentFetcher {
134 list: self.fetcher_moments.clone(),
135 index: remote.len() - 1,
136 }
137 }
138
139 pub(super) fn prepare_for_reloading(&mut self) {
141 self.fetcher_moments = Arc::default();
142 }
143
144 pub(super) fn declare_saved(&mut self) {
147 self.saved_moment = Some(self.cur_moment)
148 }
149}
150
151impl Clone for History {
152 fn clone(&self) -> Self {
153 Self {
154 new_moment: self.new_moment.clone(),
155 moments: self.moments.clone(),
156 cur_moment: self.cur_moment,
157 fetcher_moments: Arc::default(),
158 saved_moment: self.saved_moment,
159 }
160 }
161}
162
163#[derive(Clone, Default, Debug, Encode, Decode)]
169pub struct Moment {
170 changes: Vec<Change<'static, String>>,
171 shift_state: (usize, [i32; 3]),
172}
173
174impl Moment {
175 fn add_change(&mut self, guess_i: Option<usize>, mut change: Change<'static, String>) -> usize {
178 let new_shift = change.shift();
179 let (from, shift) = self.shift_state;
180
181 let m_range = merging_range_by_guess_and_lazy_shift(
183 (&self.changes, self.changes.len()),
184 (guess_i.unwrap_or(0), [change.start(), change.taken_end()]),
185 (from, shift, [0; 3], Point::shift_by),
186 (Change::start, Change::added_end),
187 );
188
189 if from < m_range.end && shift != [0; 3] {
192 for change in &mut self.changes[from..m_range.end] {
193 change.shift_by(shift);
194 }
195 } else if from > m_range.end && shift != [0; 3] {
199 for change in &mut self.changes[m_range.end..from] {
200 change.shift_by(shift.map(|i| -i));
201 }
202 }
203
204 for c in self.changes.drain(m_range.clone()).rev() {
205 change.try_merge(c);
206 }
207
208 let (from, shift) = if !(change.added_str() == "" && change.taken_str() == "") {
210 self.changes.insert(m_range.start, change);
211 (m_range.start + 1, add(shift, new_shift))
212 } else {
213 (m_range.start, shift)
214 };
215
216 if from < self.changes.len() {
217 self.shift_state = (from, shift);
218 } else {
219 self.shift_state = (0, [0; 3]);
220 }
221
222 m_range.start
223 }
224
225 pub fn changes(&self) -> impl ExactSizeIterator<Item = Change<'_>> + '_ {
230 let (from, shift) = self.shift_state;
231 self.changes.iter().enumerate().map(move |(i, change)| {
232 let mut change = change.as_ref();
233 if i >= from {
234 change.shift_by(shift);
235 }
236 change
237 })
238 }
239
240 pub fn len(&self) -> usize {
250 self.changes.len()
251 }
252
253 #[must_use]
257 pub fn is_empty(&self) -> bool {
258 self.len() == 0
259 }
260}
261
262#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
264pub struct Change<'s, S = &'s str> {
265 start: [i32; 3],
266 added: S,
267 taken: S,
268 added_end: [i32; 3],
269 taken_end: [i32; 3],
270 _ghost: PhantomData<&'s str>,
271}
272
273impl Change<'static, String> {
274 pub fn new(edit: impl ToString, range: Range<Point>, text: &Text) -> Self {
276 let added = {
277 let edit = edit.to_string();
278 if range.start == text.len() && !edit.ends_with('\n') || range.end == text.len() {
280 edit + "\n"
281 } else {
282 edit
283 }
284 };
285
286 let taken = text.strs(range.clone()).unwrap().collect();
287 let added_end = add(range.start.as_signed(), Point::len_of(&added).as_signed());
288 Change {
289 start: range.start.as_signed(),
290 added,
291 taken,
292 added_end,
293 taken_end: range.end.as_signed(),
294 _ghost: PhantomData,
295 }
296 }
297
298 pub fn as_ref(&self) -> Change<'_, &str> {
300 Change {
301 start: self.start,
302 added: &self.added,
303 taken: &self.taken,
304 added_end: self.added_end,
305 taken_end: self.taken_end,
306 _ghost: PhantomData,
307 }
308 }
309
310 pub fn try_merge(&mut self, mut older: Self) {
315 if has_start_of(older.added_range(), self.taken_range()) {
316 let fixed_end = older.added_end().min(self.taken_end());
317
318 let start = sub(self.start, older.start);
319 let end = sub(fixed_end.as_signed(), older.start);
320 let range = start[0] as usize..end[0] as usize;
321 older.added.replace_range(range, &self.added);
322
323 let range = (fixed_end.byte() - self.start[0] as usize)..;
324 older.taken.push_str(&self.taken[range]);
325
326 *self = older;
327 } else if has_start_of(self.taken_range(), older.added_range()) {
328 let fixed_end = self.taken_end().min(older.added_end());
329
330 let start = sub(older.start, self.start);
331 let end = sub(fixed_end.as_signed(), self.start);
332 let range = start[0] as usize..end[0] as usize;
333 self.taken.replace_range(range, &older.taken);
334
335 let range = (fixed_end.byte() - older.start[0] as usize)..;
336
337 self.added.push_str(&older.added[range]);
338 } else {
339 unreachable!("Changes chosen that don't interact");
340 }
341 self.added_end = add(self.start, Point::len_of(&self.added).as_signed());
342 self.taken_end = add(self.start, Point::len_of(&self.taken).as_signed());
343 }
344}
345
346impl<'a> Change<'a> {
347 pub fn to_string_change(&self) -> Change<'static, String> {
349 Change {
350 start: self.start,
351 added: self.added.to_string(),
352 taken: self.taken.to_string(),
353 added_end: self.added_end,
354 taken_end: self.taken_end,
355 _ghost: PhantomData,
356 }
357 }
358
359 pub fn str_insert(added_str: &'a str, start: Point) -> Self {
361 Self {
362 start: start.as_signed(),
363 added: added_str,
364 taken: "",
365 added_end: (start + Point::len_of(added_str)).as_signed(),
366 taken_end: start.as_signed(),
367 _ghost: PhantomData,
368 }
369 }
370
371 pub(super) fn remove_last_nl(len: Point) -> Change<'static> {
372 Change {
373 start: len.rev('\n').as_signed(),
374 added: "",
375 taken: "\n",
376 added_end: len.rev('\n').as_signed(),
377 taken_end: len.as_signed(),
378 _ghost: PhantomData,
379 }
380 }
381}
382
383impl<'s, S: std::borrow::Borrow<str>> Change<'s, S> {
384 pub fn reverse(self) -> Self {
386 Self {
387 start: self.start,
388 added: self.taken,
389 taken: self.added,
390 added_end: self.taken_end,
391 taken_end: self.added_end,
392 _ghost: PhantomData,
393 }
394 }
395
396 pub fn line_range(&self, bytes: &Bytes) -> Range<Point> {
412 let start = bytes.point_at_line(self.start[2] as usize);
413 let end_range = bytes.line_range(self.added_end[2] as usize);
414 start..end_range.end
415 }
416
417 pub fn start(&self) -> Point {
419 to_point(self.start)
420 }
421
422 pub fn taken_end(&self) -> Point {
424 to_point(self.taken_end)
425 }
426
427 pub fn added_end(&self) -> Point {
429 to_point(self.added_end)
430 }
431
432 pub fn taken_range(&self) -> Range<Point> {
434 self.start()..self.taken_end()
435 }
436
437 pub fn added_range(&self) -> Range<Point> {
439 self.start()..self.added_end()
440 }
441
442 pub fn added_str(&self) -> &str {
444 self.added.borrow()
445 }
446
447 pub fn taken_str(&self) -> &str {
449 self.taken.borrow()
450 }
451
452 pub fn shift(&self) -> [i32; 3] {
454 [
455 self.added_end[0] - self.taken_end[0],
456 self.added_end[1] - self.taken_end[1],
457 self.added_end[2] - self.taken_end[2],
458 ]
459 }
460
461 pub(crate) fn shift_by(&mut self, shift: [i32; 3]) {
463 self.start = add(self.start, shift);
464 self.added_end = add(self.added_end, shift);
465 self.taken_end = add(self.taken_end, shift);
466 }
467}
468
469impl Encode for Change<'static, String> {
470 fn encode<E: bincode::enc::Encoder>(
471 &self,
472 encoder: &mut E,
473 ) -> Result<(), bincode::error::EncodeError> {
474 Encode::encode(&self.start, encoder)?;
475 Encode::encode(&self.added, encoder)?;
476 Encode::encode(&self.taken, encoder)?;
477 Encode::encode(&self.added_end, encoder)?;
478 Encode::encode(&self.taken_end, encoder)?;
479 Ok(())
480 }
481}
482
483impl<Context> Decode<Context> for Change<'static, String> {
484 fn decode<D: bincode::de::Decoder<Context = Context>>(
485 decoder: &mut D,
486 ) -> Result<Self, bincode::error::DecodeError> {
487 Ok(Self {
488 start: Decode::decode(decoder)?,
489 added: Decode::decode(decoder)?,
490 taken: Decode::decode(decoder)?,
491 added_end: Decode::decode(decoder)?,
492 taken_end: Decode::decode(decoder)?,
493 _ghost: PhantomData,
494 })
495 }
496}
497
498impl<'de, Context> BorrowDecode<'de, Context> for Change<'static, String> {
499 fn borrow_decode<D: bincode::de::BorrowDecoder<'de, Context = Context>>(
500 decoder: &mut D,
501 ) -> Result<Self, bincode::error::DecodeError> {
502 Ok(Self {
503 start: Decode::decode(decoder)?,
504 added: Decode::decode(decoder)?,
505 taken: Decode::decode(decoder)?,
506 added_end: Decode::decode(decoder)?,
507 taken_end: Decode::decode(decoder)?,
508 _ghost: PhantomData,
509 })
510 }
511}
512
513fn has_start_of(lhs: Range<Point>, rhs: Range<Point>) -> bool {
515 lhs.start <= rhs.start && rhs.start <= lhs.end
516}
517
518#[derive(Debug)]
523pub(crate) struct MomentFetcher {
524 list: Arc<Mutex<Vec<FetcherState>>>,
525 index: usize,
526}
527
528impl MomentFetcher {
529 pub(crate) fn get_moment(&self) -> Moment {
531 self.list.lock()[self.index].take().expect(
532 "This should only return None if the MomentFetcher has been dropped, at which point \
533 calling this function should not be possible.",
534 )
535 }
536}
537
538impl Drop for MomentFetcher {
541 fn drop(&mut self) {
542 self.list.lock()[self.index] = FetcherState::Dead;
543 }
544}
545
546#[derive(Clone, Debug, Encode, Decode)]
551enum FetcherState {
552 Alive(Moment),
553 Dead,
554}
555
556impl FetcherState {
557 fn take(&mut self) -> Option<Moment> {
560 match self {
561 FetcherState::Alive(moment) => Some(std::mem::take(moment)),
562 FetcherState::Dead => None,
563 }
564 }
565
566 fn add_change(&mut self, change: Change<'static, String>) {
568 match self {
569 FetcherState::Alive(moment) => {
570 moment.add_change(None, change);
571 }
572 FetcherState::Dead => {}
573 }
574 }
575}
576
577fn sub(lhs: [i32; 3], rhs: [i32; 3]) -> [i32; 3] {
579 [lhs[0] - rhs[0], lhs[1] - rhs[1], lhs[2] - rhs[2]]
580}
581
582fn to_point(signed: [i32; 3]) -> Point {
584 Point::from_raw(signed[0] as usize, signed[1] as usize, signed[2] as usize)
585}