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