1use std::fmt;
41
42pub trait Reversible<S>: fmt::Debug {
49 fn forward(&self, state: &mut S);
51
52 fn backward(&self, state: &mut S);
54
55 fn description(&self) -> &str {
57 "reversible op"
58 }
59}
60
61#[derive(Debug, Clone, Copy)]
65pub struct AddOp<T> {
66 delta: T,
67}
68
69impl<T> AddOp<T> {
70 pub fn new(delta: T) -> Self {
71 Self { delta }
72 }
73}
74
75macro_rules! impl_add_op {
76 ($($ty:ty),*) => {
77 $(
78 impl Reversible<$ty> for AddOp<$ty> {
79 fn forward(&self, state: &mut $ty) {
80 *state = state.wrapping_add(self.delta);
81 }
82
83 fn backward(&self, state: &mut $ty) {
84 *state = state.wrapping_sub(self.delta);
85 }
86
87 fn description(&self) -> &str {
88 "add"
89 }
90 }
91 )*
92 };
93}
94
95impl_add_op!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
96
97impl Reversible<f64> for AddOp<f64> {
98 fn forward(&self, state: &mut f64) {
99 *state += self.delta;
100 }
101
102 fn backward(&self, state: &mut f64) {
103 *state -= self.delta;
104 }
105
106 fn description(&self) -> &str {
107 "add_f64"
108 }
109}
110
111impl Reversible<f32> for AddOp<f32> {
112 fn forward(&self, state: &mut f32) {
113 *state += self.delta;
114 }
115
116 fn backward(&self, state: &mut f32) {
117 *state -= self.delta;
118 }
119
120 fn description(&self) -> &str {
121 "add_f32"
122 }
123}
124
125#[derive(Debug, Clone, Copy)]
127pub struct XorOp<T> {
128 mask: T,
129}
130
131impl<T> XorOp<T> {
132 pub fn new(mask: T) -> Self {
133 Self { mask }
134 }
135}
136
137macro_rules! impl_xor_op {
138 ($($ty:ty),*) => {
139 $(
140 impl Reversible<$ty> for XorOp<$ty> {
141 fn forward(&self, state: &mut $ty) {
142 *state ^= self.mask;
143 }
144
145 fn backward(&self, state: &mut $ty) {
146 *state ^= self.mask;
148 }
149
150 fn description(&self) -> &str {
151 "xor"
152 }
153 }
154 )*
155 };
156}
157
158impl_xor_op!(u8, u16, u32, u64, usize);
159
160#[derive(Debug, Clone, Copy)]
164pub struct MulOp<T> {
165 factor: T,
166}
167
168impl<T> MulOp<T> {
169 pub fn new(factor: T) -> Self {
170 Self { factor }
171 }
172}
173
174impl Reversible<f64> for MulOp<f64> {
175 fn forward(&self, state: &mut f64) {
176 *state *= self.factor;
177 }
178
179 fn backward(&self, state: &mut f64) {
180 *state /= self.factor;
181 }
182
183 fn description(&self) -> &str {
184 "mul_f64"
185 }
186}
187
188#[derive(Debug, Clone, Copy)]
192pub struct SwapOp {
193 i: usize,
194 j: usize,
195}
196
197impl SwapOp {
198 pub fn new(i: usize, j: usize) -> Self {
199 Self { i, j }
200 }
201}
202
203impl<T> Reversible<Vec<T>> for SwapOp {
204 fn forward(&self, state: &mut Vec<T>) {
205 state.swap(self.i, self.j);
206 }
207
208 fn backward(&self, state: &mut Vec<T>) {
209 state.swap(self.i, self.j);
211 }
212
213 fn description(&self) -> &str {
214 "swap"
215 }
216}
217
218#[derive(Debug, Clone)]
222pub struct SetOp<T> {
223 new_value: T,
224 old_value: T,
225}
226
227impl<T: Clone> SetOp<T> {
228 pub fn new(old_value: T, new_value: T) -> Self {
230 Self {
231 new_value,
232 old_value,
233 }
234 }
235}
236
237impl<T: Clone + fmt::Debug> Reversible<T> for SetOp<T> {
238 fn forward(&self, state: &mut T) {
239 *state = self.new_value.clone();
240 }
241
242 fn backward(&self, state: &mut T) {
243 *state = self.old_value.clone();
244 }
245
246 fn description(&self) -> &str {
247 "set"
248 }
249}
250
251#[derive(Debug, Clone)]
255pub struct PushOp<T> {
256 value: T,
257}
258
259impl<T: Clone> PushOp<T> {
260 pub fn new(value: T) -> Self {
261 Self { value }
262 }
263}
264
265impl<T: Clone + fmt::Debug> Reversible<Vec<T>> for PushOp<T> {
266 fn forward(&self, state: &mut Vec<T>) {
267 state.push(self.value.clone());
268 }
269
270 fn backward(&self, state: &mut Vec<T>) {
271 state.pop();
272 }
273
274 fn description(&self) -> &str {
275 "push"
276 }
277}
278
279#[derive(Debug, Clone)]
281pub struct InsertOp<T> {
282 index: usize,
283 value: T,
284}
285
286impl<T: Clone> InsertOp<T> {
287 pub fn new(index: usize, value: T) -> Self {
288 Self { index, value }
289 }
290}
291
292impl<T: Clone + fmt::Debug> Reversible<Vec<T>> for InsertOp<T> {
293 fn forward(&self, state: &mut Vec<T>) {
294 state.insert(self.index, self.value.clone());
295 }
296
297 fn backward(&self, state: &mut Vec<T>) {
298 state.remove(self.index);
299 }
300
301 fn description(&self) -> &str {
302 "insert"
303 }
304}
305
306#[derive(Debug, Clone)]
308pub struct RemoveOp<T> {
309 index: usize,
310 removed: Option<T>,
311}
312
313impl<T: Clone> RemoveOp<T> {
314 pub fn new(index: usize) -> Self {
315 Self {
316 index,
317 removed: None,
318 }
319 }
320}
321
322impl<T: Clone + fmt::Debug> Reversible<Vec<T>> for RemoveOp<T> {
323 fn forward(&self, state: &mut Vec<T>) {
324 state.remove(self.index);
325 }
326
327 fn backward(&self, state: &mut Vec<T>) {
328 if let Some(val) = &self.removed {
329 state.insert(self.index, val.clone());
330 }
331 }
332
333 fn description(&self) -> &str {
334 "remove"
335 }
336}
337
338pub fn remove_capturing<T: Clone>(state: &[T], index: usize) -> RemoveOp<T> {
340 RemoveOp {
341 index,
342 removed: state.get(index).cloned(),
343 }
344}
345
346pub struct Sequence<S> {
353 ops: Vec<Box<dyn Reversible<S>>>,
354 label: &'static str,
355}
356
357impl<S> fmt::Debug for Sequence<S> {
358 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
359 f.debug_struct("Sequence")
360 .field("len", &self.ops.len())
361 .field("label", &self.label)
362 .finish()
363 }
364}
365
366impl<S> Sequence<S> {
367 pub fn new(ops: Vec<Box<dyn Reversible<S>>>) -> Self {
369 Self {
370 ops,
371 label: "sequence",
372 }
373 }
374
375 pub fn empty() -> Self {
377 Self {
378 ops: Vec::new(),
379 label: "sequence",
380 }
381 }
382
383 pub fn with_label(mut self, label: &'static str) -> Self {
385 self.label = label;
386 self
387 }
388
389 pub fn push(&mut self, op: Box<dyn Reversible<S>>) {
391 self.ops.push(op);
392 }
393
394 pub fn len(&self) -> usize {
396 self.ops.len()
397 }
398
399 pub fn is_empty(&self) -> bool {
401 self.ops.is_empty()
402 }
403}
404
405impl<S> Reversible<S> for Sequence<S> {
406 fn forward(&self, state: &mut S) {
407 for op in &self.ops {
408 op.forward(state);
409 }
410 }
411
412 fn backward(&self, state: &mut S) {
413 for op in self.ops.iter().rev() {
414 op.backward(state);
415 }
416 }
417
418 fn description(&self) -> &str {
419 self.label
420 }
421}
422
423pub struct Journal<S> {
427 applied: Vec<Box<dyn Reversible<S>>>,
428 undone: Vec<Box<dyn Reversible<S>>>,
429}
430
431impl<S> fmt::Debug for Journal<S> {
432 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433 f.debug_struct("Journal")
434 .field("applied", &self.applied.len())
435 .field("undone", &self.undone.len())
436 .finish()
437 }
438}
439
440impl<S> Journal<S> {
441 pub fn new() -> Self {
443 Self {
444 applied: Vec::new(),
445 undone: Vec::new(),
446 }
447 }
448
449 pub fn apply(&mut self, op: Box<dyn Reversible<S>>, state: &mut S) {
451 op.forward(state);
452 self.applied.push(op);
453 self.undone.clear(); }
455
456 pub fn undo(&mut self, state: &mut S) -> bool {
458 if let Some(op) = self.applied.pop() {
459 op.backward(state);
460 self.undone.push(op);
461 true
462 } else {
463 false
464 }
465 }
466
467 pub fn redo(&mut self, state: &mut S) -> bool {
469 if let Some(op) = self.undone.pop() {
470 op.forward(state);
471 self.applied.push(op);
472 true
473 } else {
474 false
475 }
476 }
477
478 pub fn undo_count(&self) -> usize {
480 self.applied.len()
481 }
482
483 pub fn redo_count(&self) -> usize {
485 self.undone.len()
486 }
487
488 pub fn clear(&mut self) {
490 self.applied.clear();
491 self.undone.clear();
492 }
493}
494
495impl<S> Default for Journal<S> {
496 fn default() -> Self {
497 Self::new()
498 }
499}
500
501#[cfg(test)]
502mod tests {
503 use super::*;
504
505 #[test]
508 fn add_forward_backward() {
509 let mut x = 10u64;
510 let op = AddOp::new(5u64);
511 op.forward(&mut x);
512 assert_eq!(x, 15);
513 op.backward(&mut x);
514 assert_eq!(x, 10);
515 }
516
517 #[test]
518 fn add_signed() {
519 let mut x = 0i32;
520 let op = AddOp::new(-5i32);
521 op.forward(&mut x);
522 assert_eq!(x, -5);
523 op.backward(&mut x);
524 assert_eq!(x, 0);
525 }
526
527 #[test]
528 fn add_f64_roundtrip() {
529 let mut x = 1.0f64;
530 let op = AddOp::new(0.5);
531 op.forward(&mut x);
532 assert!((x - 1.5).abs() < f64::EPSILON);
533 op.backward(&mut x);
534 assert!((x - 1.0).abs() < f64::EPSILON);
535 }
536
537 #[test]
540 fn xor_is_self_inverse() {
541 let mut x = 0xFFu8;
542 let op = XorOp::new(0x0Fu8);
543 op.forward(&mut x);
544 assert_eq!(x, 0xF0);
545 op.backward(&mut x);
546 assert_eq!(x, 0xFF);
547 }
548
549 #[test]
550 fn xor_double_apply_is_identity() {
551 let mut x = 42u64;
552 let op = XorOp::new(123u64);
553 op.forward(&mut x);
554 op.forward(&mut x); assert_eq!(x, 42);
556 }
557
558 #[test]
561 fn mul_f64_roundtrip() {
562 let mut x = 4.0f64;
563 let op = MulOp::new(2.5);
564 op.forward(&mut x);
565 assert!((x - 10.0).abs() < f64::EPSILON);
566 op.backward(&mut x);
567 assert!((x - 4.0).abs() < f64::EPSILON);
568 }
569
570 #[test]
573 fn swap_roundtrip() {
574 let mut v = vec![1, 2, 3, 4, 5];
575 let op = SwapOp::new(0, 4);
576 op.forward(&mut v);
577 assert_eq!(v, vec![5, 2, 3, 4, 1]);
578 op.backward(&mut v);
579 assert_eq!(v, vec![1, 2, 3, 4, 5]);
580 }
581
582 #[test]
583 fn swap_same_index_is_noop() {
584 let mut v = vec![1, 2, 3];
585 let op = SwapOp::new(1, 1);
586 op.forward(&mut v);
587 assert_eq!(v, vec![1, 2, 3]);
588 }
589
590 #[test]
593 fn set_roundtrip() {
594 let mut x = "hello".to_string();
595 let op = SetOp::new("hello".to_string(), "world".to_string());
596 op.forward(&mut x);
597 assert_eq!(x, "world");
598 op.backward(&mut x);
599 assert_eq!(x, "hello");
600 }
601
602 #[test]
605 fn push_roundtrip() {
606 let mut v: Vec<u32> = vec![1, 2];
607 let op = PushOp::new(3u32);
608 op.forward(&mut v);
609 assert_eq!(v, vec![1, 2, 3]);
610 op.backward(&mut v);
611 assert_eq!(v, vec![1, 2]);
612 }
613
614 #[test]
617 fn insert_roundtrip() {
618 let mut v = vec![1, 3, 4];
619 let op = InsertOp::new(1, 2);
620 op.forward(&mut v);
621 assert_eq!(v, vec![1, 2, 3, 4]);
622 op.backward(&mut v);
623 assert_eq!(v, vec![1, 3, 4]);
624 }
625
626 #[test]
629 fn remove_with_capture_roundtrip() {
630 let mut v = vec![10, 20, 30];
631 let op = remove_capturing(&v, 1);
632 op.forward(&mut v);
633 assert_eq!(v, vec![10, 30]);
634 op.backward(&mut v);
635 assert_eq!(v, vec![10, 20, 30]);
636 }
637
638 #[test]
641 fn sequence_forward_backward() {
642 let mut x = 0u64;
643 let seq = Sequence::new(vec![
644 Box::new(AddOp::new(10u64)),
645 Box::new(AddOp::new(20u64)),
646 Box::new(AddOp::new(30u64)),
647 ]);
648
649 seq.forward(&mut x);
650 assert_eq!(x, 60);
651
652 seq.backward(&mut x);
653 assert_eq!(x, 0);
654 }
655
656 #[test]
657 fn sequence_backward_reverses_order() {
658 let mut v = Vec::<u32>::new();
659 let seq = Sequence::new(vec![
660 Box::new(PushOp::new(1u32)),
661 Box::new(PushOp::new(2u32)),
662 Box::new(PushOp::new(3u32)),
663 ]);
664
665 seq.forward(&mut v);
666 assert_eq!(v, vec![1, 2, 3]);
667
668 seq.backward(&mut v);
669 assert!(v.is_empty());
670 }
671
672 #[test]
673 fn sequence_empty() {
674 let mut x = 42u64;
675 let seq = Sequence::<u64>::empty();
676 seq.forward(&mut x);
677 assert_eq!(x, 42);
678 seq.backward(&mut x);
679 assert_eq!(x, 42);
680 }
681
682 #[test]
683 fn sequence_push() {
684 let mut seq = Sequence::<u64>::empty();
685 seq.push(Box::new(AddOp::new(5u64)));
686 assert_eq!(seq.len(), 1);
687
688 let mut x = 0u64;
689 seq.forward(&mut x);
690 assert_eq!(x, 5);
691 }
692
693 #[test]
694 fn sequence_with_label() {
695 let seq = Sequence::<u64>::empty().with_label("batch insert");
696 assert_eq!(seq.description(), "batch insert");
697 }
698
699 #[test]
702 fn journal_apply_and_undo() {
703 let mut state = 0u64;
704 let mut journal = Journal::new();
705
706 journal.apply(Box::new(AddOp::new(10u64)), &mut state);
707 assert_eq!(state, 10);
708 assert_eq!(journal.undo_count(), 1);
709
710 journal.apply(Box::new(AddOp::new(20u64)), &mut state);
711 assert_eq!(state, 30);
712 assert_eq!(journal.undo_count(), 2);
713
714 assert!(journal.undo(&mut state));
715 assert_eq!(state, 10);
716 assert_eq!(journal.undo_count(), 1);
717 assert_eq!(journal.redo_count(), 1);
718
719 assert!(journal.undo(&mut state));
720 assert_eq!(state, 0);
721
722 assert!(!journal.undo(&mut state)); }
724
725 #[test]
726 fn journal_redo() {
727 let mut state = 0u64;
728 let mut journal = Journal::new();
729
730 journal.apply(Box::new(AddOp::new(10u64)), &mut state);
731 journal.apply(Box::new(AddOp::new(20u64)), &mut state);
732 assert_eq!(state, 30);
733
734 journal.undo(&mut state);
735 assert_eq!(state, 10);
736
737 assert!(journal.redo(&mut state));
738 assert_eq!(state, 30);
739
740 assert!(!journal.redo(&mut state)); }
742
743 #[test]
744 fn journal_new_op_clears_redo() {
745 let mut state = 0u64;
746 let mut journal = Journal::new();
747
748 journal.apply(Box::new(AddOp::new(10u64)), &mut state);
749 journal.undo(&mut state);
750 assert_eq!(journal.redo_count(), 1);
751
752 journal.apply(Box::new(AddOp::new(5u64)), &mut state);
753 assert_eq!(journal.redo_count(), 0); assert_eq!(state, 5);
755 }
756
757 #[test]
758 fn journal_clear() {
759 let mut state = 0u64;
760 let mut journal = Journal::new();
761
762 journal.apply(Box::new(AddOp::new(10u64)), &mut state);
763 journal.undo(&mut state);
764 journal.clear();
765
766 assert_eq!(journal.undo_count(), 0);
767 assert_eq!(journal.redo_count(), 0);
768 }
769
770 #[test]
771 fn journal_complex_sequence() {
772 let mut state = vec![1u32, 2, 3];
773 let mut journal = Journal::new();
774
775 journal.apply(Box::new(PushOp::new(4u32)), &mut state);
777 assert_eq!(state, vec![1, 2, 3, 4]);
778
779 journal.apply(Box::new(SwapOp::new(0, 3)), &mut state);
781 assert_eq!(state, vec![4, 2, 3, 1]);
782
783 journal.apply(Box::new(InsertOp::new(2, 99u32)), &mut state);
785 assert_eq!(state, vec![4, 2, 99, 3, 1]);
786
787 journal.undo(&mut state);
789 assert_eq!(state, vec![4, 2, 3, 1]);
790 journal.undo(&mut state);
791 assert_eq!(state, vec![1, 2, 3, 4]);
792 journal.undo(&mut state);
793 assert_eq!(state, vec![1, 2, 3]);
794
795 journal.redo(&mut state);
797 journal.redo(&mut state);
798 journal.redo(&mut state);
799 assert_eq!(state, vec![4, 2, 99, 3, 1]);
800 }
801
802 #[test]
803 fn description_returns_op_name() {
804 assert_eq!(AddOp::new(1u64).description(), "add");
805 assert_eq!(XorOp::new(1u64).description(), "xor");
806 assert_eq!(
807 Reversible::<Vec<u32>>::description(&SwapOp::new(0, 1)),
808 "swap"
809 );
810 assert_eq!(SetOp::new(0u32, 1u32).description(), "set");
811 assert_eq!(PushOp::new(1u32).description(), "push");
812 assert_eq!(InsertOp::new(0, 1u32).description(), "insert");
813 }
814
815 #[test]
816 fn debug_impls() {
817 let op = AddOp::new(5u64);
818 assert!(format!("{op:?}").contains("AddOp"));
819
820 let seq = Sequence::<u64>::empty();
821 assert!(format!("{seq:?}").contains("Sequence"));
822
823 let journal = Journal::<u64>::new();
824 assert!(format!("{journal:?}").contains("Journal"));
825 }
826}