undo_map.rs

  1use crate::UndoOperation;
  2use std::cmp;
  3use sum_tree::{Bias, SumTree};
  4
  5#[derive(Copy, Clone, Debug)]
  6struct UndoMapEntry {
  7    key: UndoMapKey,
  8    undo_count: u32,
  9}
 10
 11impl sum_tree::Item for UndoMapEntry {
 12    type Summary = UndoMapKey;
 13
 14    fn summary(&self, _cx: ()) -> Self::Summary {
 15        self.key
 16    }
 17}
 18
 19impl sum_tree::KeyedItem for UndoMapEntry {
 20    type Key = UndoMapKey;
 21
 22    fn key(&self) -> Self::Key {
 23        self.key
 24    }
 25}
 26
 27#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
 28struct UndoMapKey {
 29    edit_id: clock::Lamport,
 30    undo_id: clock::Lamport,
 31}
 32
 33impl sum_tree::ContextLessSummary for UndoMapKey {
 34    fn zero() -> Self {
 35        Default::default()
 36    }
 37
 38    fn add_summary(&mut self, summary: &Self) {
 39        *self = cmp::max(*self, *summary);
 40    }
 41}
 42
 43#[derive(Clone, Default)]
 44pub struct UndoMap(SumTree<UndoMapEntry>);
 45
 46impl UndoMap {
 47    pub fn insert(&mut self, undo: &UndoOperation) {
 48        let edits = undo
 49            .counts
 50            .iter()
 51            .map(|(edit_id, count)| {
 52                sum_tree::Edit::Insert(UndoMapEntry {
 53                    key: UndoMapKey {
 54                        edit_id: *edit_id,
 55                        undo_id: undo.timestamp,
 56                    },
 57                    undo_count: *count,
 58                })
 59            })
 60            .collect::<Vec<_>>();
 61        self.0.edit(edits, ());
 62    }
 63
 64    pub fn is_undone(&self, edit_id: clock::Lamport) -> bool {
 65        self.undo_count(edit_id) % 2 == 1
 66    }
 67    pub fn was_undone(&self, edit_id: clock::Lamport, version: &clock::Global) -> bool {
 68        let mut cursor = self.0.cursor::<UndoMapKey>(());
 69        cursor.seek(
 70            &UndoMapKey {
 71                edit_id,
 72                undo_id: Default::default(),
 73            },
 74            Bias::Left,
 75        );
 76
 77        let mut undo_count = 0;
 78        for entry in cursor {
 79            if entry.key.edit_id != edit_id {
 80                break;
 81            }
 82
 83            if version.observed(entry.key.undo_id) {
 84                undo_count = cmp::max(undo_count, entry.undo_count);
 85            }
 86        }
 87
 88        undo_count % 2 == 1
 89    }
 90
 91    pub fn undo_count(&self, edit_id: clock::Lamport) -> u32 {
 92        let mut cursor = self.0.cursor::<UndoMapKey>(());
 93        cursor.seek(
 94            &UndoMapKey {
 95                edit_id,
 96                undo_id: Default::default(),
 97            },
 98            Bias::Left,
 99        );
100
101        let mut undo_count = 0;
102        for entry in cursor {
103            if entry.key.edit_id != edit_id {
104                break;
105            }
106
107            undo_count = cmp::max(undo_count, entry.undo_count);
108        }
109        undo_count
110    }
111}