undo/history/
checkpoint.rs1use crate::{At, Edit, History, Slot};
2use alloc::vec::Vec;
3
4#[derive(Debug)]
5enum CheckpointEntry {
6 Edit(usize),
7 Undo,
8 Redo,
9}
10
11#[derive(Debug)]
13pub struct Checkpoint<'a, E, S> {
14 history: &'a mut History<E, S>,
15 entries: Vec<CheckpointEntry>,
16}
17
18impl<E, S> Checkpoint<'_, E, S> {
19 pub fn reserve(&mut self, additional: usize) {
24 self.entries.reserve(additional);
25 }
26
27 pub fn commit(self) {}
29}
30
31impl<E: Edit, S: Slot> Checkpoint<'_, E, S> {
32 pub fn edit(&mut self, target: &mut E::Target, edit: E) -> E::Output {
34 self.entries.push(CheckpointEntry::Edit(self.history.root));
35 self.history.edit(target, edit)
36 }
37
38 pub fn undo(&mut self, target: &mut E::Target) -> Option<E::Output> {
40 self.entries.push(CheckpointEntry::Undo);
41 self.history.undo(target)
42 }
43
44 pub fn redo(&mut self, target: &mut E::Target) -> Option<E::Output> {
46 self.entries.push(CheckpointEntry::Redo);
47 self.history.redo(target)
48 }
49
50 pub fn cancel(self, target: &mut E::Target) -> Vec<E::Output> {
52 self.entries
53 .into_iter()
54 .rev()
55 .filter_map(|entry| match entry {
56 CheckpointEntry::Edit(root) => {
57 let output = self.history.undo(target)?;
58 if self.history.root == root {
59 self.history.record.entries.pop_back();
60 } else {
61 let mut branch = self.history.branches.remove(root);
64 debug_assert_eq!(branch.parent, self.history.head());
65
66 let new = At::new(root, self.history.record.head());
67 let (_, rm_saved) = self.history.record.rm_tail();
68 self.history.record.entries.append(&mut branch.entries);
69 self.history.set_root(new, rm_saved);
70 }
71 Some(output)
72 }
73 CheckpointEntry::Undo => self.history.redo(target),
74 CheckpointEntry::Redo => self.history.undo(target),
75 })
76 .collect()
77 }
78}
79
80impl<'a, E, S> From<&'a mut History<E, S>> for Checkpoint<'a, E, S> {
81 fn from(history: &'a mut History<E, S>) -> Self {
82 Checkpoint {
83 history,
84 entries: Vec::new(),
85 }
86 }
87}