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) -> 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::Summary for UndoMapKey {
 34    type Context = ();
 35
 36    fn add_summary(&mut self, summary: &Self, _: &Self::Context) {
 37        *self = cmp::max(*self, *summary);
 38    }
 39}
 40
 41#[derive(Clone, Default)]
 42pub struct UndoMap(SumTree<UndoMapEntry>);
 43
 44impl UndoMap {
 45    pub fn insert(&mut self, undo: &UndoOperation) {
 46        let edits = undo
 47            .counts
 48            .iter()
 49            .map(|(edit_id, count)| {
 50                sum_tree::Edit::Insert(UndoMapEntry {
 51                    key: UndoMapKey {
 52                        edit_id: *edit_id,
 53                        undo_id: undo.timestamp,
 54                    },
 55                    undo_count: *count,
 56                })
 57            })
 58            .collect::<Vec<_>>();
 59        self.0.edit(edits, &());
 60    }
 61
 62    pub fn is_undone(&self, edit_id: clock::Lamport) -> bool {
 63        self.undo_count(edit_id) % 2 == 1
 64    }
 65
 66    pub fn was_undone(&self, edit_id: clock::Lamport, version: &clock::Global) -> bool {
 67        let mut cursor = self.0.cursor::<UndoMapKey>();
 68        cursor.seek(
 69            &UndoMapKey {
 70                edit_id,
 71                undo_id: Default::default(),
 72            },
 73            Bias::Left,
 74            &(),
 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
102        let mut undo_count = 0;
103        for entry in cursor {
104            if entry.key.edit_id != edit_id {
105                break;
106            }
107
108            undo_count = cmp::max(undo_count, entry.undo_count);
109        }
110        undo_count
111    }
112}