undo_map.rs

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