1use std::collections::VecDeque;
6
7const MAX_UNDO_SIZE: usize = 256;
9
10#[derive(Debug, Clone)]
12pub struct UndoStack<T> {
13 states: VecDeque<T>,
15 max_size: usize,
17}
18
19impl<T: Clone> UndoStack<T> {
20 pub fn new() -> Self {
22 Self {
23 states: VecDeque::with_capacity(MAX_UNDO_SIZE),
24 max_size: MAX_UNDO_SIZE,
25 }
26 }
27
28 pub fn with_max_size(max_size: usize) -> Self {
30 Self {
31 states: VecDeque::with_capacity(max_size),
32 max_size,
33 }
34 }
35
36 pub fn push(&mut self, state: T) {
38 self.states.push_back(state);
39
40 while self.states.len() > self.max_size {
42 self.states.pop_front();
43 }
44 }
45
46 pub fn pop(&mut self) -> Option<T> {
48 self.states.pop_back()
49 }
50
51 pub fn peek(&self) -> Option<&T> {
53 self.states.back()
54 }
55
56 pub fn len(&self) -> usize {
58 self.states.len()
59 }
60
61 pub fn is_empty(&self) -> bool {
63 self.states.is_empty()
64 }
65
66 pub fn clear(&mut self) {
68 self.states.clear();
69 }
70
71 pub fn states(&self) -> impl Iterator<Item = &T> {
73 self.states.iter()
74 }
75
76 pub fn get(&self, index: usize) -> Option<&T> {
78 self.states.get(index)
79 }
80
81 pub fn can_undo(&self) -> bool {
83 !self.states.is_empty()
84 }
85
86 pub fn undo_to(&mut self, target_len: usize) -> Vec<T> {
88 let mut popped = Vec::new();
89 while self.states.len() > target_len {
90 if let Some(state) = self.states.pop_back() {
91 popped.push(state);
92 }
93 }
94 popped
95 }
96}
97
98impl<T: Clone> Default for UndoStack<T> {
99 fn default() -> Self {
100 Self::new()
101 }
102}
103
104#[derive(Debug, Clone)]
106pub struct RedoStack<T> {
107 states: VecDeque<T>,
109 max_size: usize,
110}
111
112impl<T: Clone> RedoStack<T> {
113 pub fn new() -> Self {
115 Self {
116 states: VecDeque::with_capacity(MAX_UNDO_SIZE),
117 max_size: MAX_UNDO_SIZE,
118 }
119 }
120
121 pub fn push(&mut self, state: T) {
123 self.states.push_back(state);
124
125 while self.states.len() > self.max_size {
126 self.states.pop_front();
127 }
128 }
129
130 pub fn pop(&mut self) -> Option<T> {
132 self.states.pop_back()
133 }
134
135 pub fn len(&self) -> usize {
137 self.states.len()
138 }
139
140 pub fn is_empty(&self) -> bool {
142 self.states.is_empty()
143 }
144
145 pub fn clear(&mut self) {
147 self.states.clear();
148 }
149
150 pub fn can_redo(&self) -> bool {
152 !self.states.is_empty()
153 }
154}
155
156impl<T: Clone> Default for RedoStack<T> {
157 fn default() -> Self {
158 Self::new()
159 }
160}
161
162#[derive(Debug, Clone)]
164pub struct UndoRedoManager<T> {
165 undo_stack: UndoStack<T>,
166 redo_stack: RedoStack<T>,
167}
168
169impl<T: Clone> UndoRedoManager<T> {
170 pub fn new() -> Self {
172 Self {
173 undo_stack: UndoStack::new(),
174 redo_stack: RedoStack::new(),
175 }
176 }
177
178 pub fn push(&mut self, state: T) {
180 self.undo_stack.push(state);
181 self.redo_stack.clear();
182 }
183
184 pub fn undo(&mut self, current: T) -> Option<T> {
186 if let Some(prev) = self.undo_stack.pop() {
187 self.redo_stack.push(current);
188 Some(prev)
189 } else {
190 None
191 }
192 }
193
194 pub fn redo(&mut self, current: T) -> Option<T> {
196 if let Some(next) = self.redo_stack.pop() {
197 self.undo_stack.push(current);
198 Some(next)
199 } else {
200 None
201 }
202 }
203
204 pub fn can_undo(&self) -> bool {
206 self.undo_stack.can_undo()
207 }
208
209 pub fn can_redo(&self) -> bool {
211 self.redo_stack.can_redo()
212 }
213
214 pub fn clear(&mut self) {
216 self.undo_stack.clear();
217 self.redo_stack.clear();
218 }
219
220 pub fn undo_count(&self) -> usize {
222 self.undo_stack.len()
223 }
224
225 pub fn redo_count(&self) -> usize {
227 self.redo_stack.len()
228 }
229}
230
231impl<T: Clone> Default for UndoRedoManager<T> {
232 fn default() -> Self {
233 Self::new()
234 }
235}
236
237#[cfg(test)]
238mod tests {
239 use super::*;
240
241 #[test]
242 fn test_push_and_pop() {
243 let mut stack: UndoStack<i32> = UndoStack::new();
244 stack.push(1);
245 stack.push(2);
246 stack.push(3);
247
248 assert_eq!(stack.len(), 3);
249 assert_eq!(stack.pop(), Some(3));
250 assert_eq!(stack.pop(), Some(2));
251 assert_eq!(stack.pop(), Some(1));
252 assert_eq!(stack.pop(), None);
253 }
254
255 #[test]
256 fn test_max_size() {
257 let mut stack: UndoStack<i32> = UndoStack::with_max_size(2);
258 stack.push(1);
259 stack.push(2);
260 stack.push(3);
261
262 assert_eq!(stack.len(), 2);
263 assert_eq!(stack.pop(), Some(3));
264 assert_eq!(stack.pop(), Some(2));
265 assert_eq!(stack.pop(), None);
266 }
267
268 #[test]
269 fn test_undo_redo_manager() {
270 let mut manager = UndoRedoManager::new();
271
272 manager.push("state1".to_string());
273 manager.push("state2".to_string());
274 manager.push("state3".to_string());
275
276 assert!(manager.can_undo());
277 assert!(!manager.can_redo());
278
279 let prev = manager.undo("current".to_string());
281 assert_eq!(prev, Some("state3".to_string()));
282 assert!(manager.can_redo());
283
284 let next = manager.redo("state3".to_string());
286 assert_eq!(next, Some("current".to_string()));
287 }
288
289 #[test]
290 fn test_push_clears_redo() {
291 let mut manager = UndoRedoManager::new();
292
293 manager.push("state1".to_string());
294 manager.push("state2".to_string());
295
296 let _ = manager.undo("current".to_string());
297 assert!(manager.can_redo());
298
299 manager.push("new_state".to_string());
301 assert!(!manager.can_redo());
302 }
303}