Another project
1use std::collections::VecDeque;
2use std::mem;
3use std::num::NonZeroUsize;
4
5use crate::Document;
6
7#[derive(Clone, Debug)]
8pub struct UndoStack {
9 past: VecDeque<Document>,
10 future: VecDeque<Document>,
11 capacity: NonZeroUsize,
12}
13
14impl UndoStack {
15 #[must_use]
16 pub fn with_capacity(capacity: NonZeroUsize) -> Self {
17 Self {
18 past: VecDeque::new(),
19 future: VecDeque::new(),
20 capacity,
21 }
22 }
23
24 pub fn record(&mut self, previous: Document) {
25 self.future.clear();
26 if self.past.len() == self.capacity.get() {
27 self.past.pop_front();
28 }
29 self.past.push_back(previous);
30 }
31
32 pub fn undo(&mut self, current: &mut Document) -> bool {
33 let Some(previous) = self.past.pop_back() else {
34 return false;
35 };
36 let old = mem::replace(current, previous);
37 self.future.push_back(old);
38 true
39 }
40
41 pub fn redo(&mut self, current: &mut Document) -> bool {
42 let Some(next) = self.future.pop_back() else {
43 return false;
44 };
45 let old = mem::replace(current, next);
46 self.past.push_back(old);
47 true
48 }
49
50 #[must_use]
51 pub fn can_undo(&self) -> bool {
52 !self.past.is_empty()
53 }
54
55 #[must_use]
56 pub fn can_redo(&self) -> bool {
57 !self.future.is_empty()
58 }
59
60 #[must_use]
61 pub fn capacity(&self) -> NonZeroUsize {
62 self.capacity
63 }
64
65 #[must_use]
66 pub fn past_len(&self) -> usize {
67 self.past.len()
68 }
69
70 #[must_use]
71 pub fn future_len(&self) -> usize {
72 self.future.len()
73 }
74}