common/database/
rope_store.rs1use crate::database::block_offset_index::BlockOffsetIndex;
11use crate::entities::*;
12use crate::format_runs::{FormatRun, ImageAnchor};
13use crate::snapshot::{StoreSnapshot, StoreSnapshotTrait};
14use crate::types::EntityId;
15use im::HashMap;
16use ropey::Rope;
17use std::collections::HashMap as StdHashMap;
18use std::sync::RwLock;
19
20#[derive(Debug, Default)]
25pub struct RopeStore {
26 pub rope: RwLock<Rope>,
28
29 pub roots: RwLock<HashMap<EntityId, Root>>,
31 pub documents: RwLock<HashMap<EntityId, Document>>,
32 pub frames: RwLock<HashMap<EntityId, Frame>>,
33 pub blocks: RwLock<HashMap<EntityId, Block>>,
34 pub lists: RwLock<HashMap<EntityId, List>>,
35 pub resources: RwLock<HashMap<EntityId, Resource>>,
36 pub tables: RwLock<HashMap<EntityId, Table>>,
37 pub table_cells: RwLock<HashMap<EntityId, TableCell>>,
38
39 pub format_runs: RwLock<HashMap<EntityId, Vec<FormatRun>>>,
41 pub block_images: RwLock<HashMap<EntityId, Vec<ImageAnchor>>>,
42
43 pub block_offsets: RwLock<BlockOffsetIndex>,
45
46 pub counters: RwLock<StdHashMap<String, EntityId>>,
49
50 savepoints: RwLock<StdHashMap<u64, RopeStoreSnapshot>>,
52 next_savepoint_id: RwLock<u64>,
53}
54
55impl RopeStore {
56 pub fn new() -> Self {
57 Self::default()
58 }
59
60 pub fn snapshot(&self) -> RopeStoreSnapshot {
64 RopeStoreSnapshot {
65 rope: self.rope.read().unwrap().clone(),
66 roots: self.roots.read().unwrap().clone(),
67 documents: self.documents.read().unwrap().clone(),
68 frames: self.frames.read().unwrap().clone(),
69 blocks: self.blocks.read().unwrap().clone(),
70 lists: self.lists.read().unwrap().clone(),
71 resources: self.resources.read().unwrap().clone(),
72 tables: self.tables.read().unwrap().clone(),
73 table_cells: self.table_cells.read().unwrap().clone(),
74 format_runs: self.format_runs.read().unwrap().clone(),
75 block_images: self.block_images.read().unwrap().clone(),
76 block_offsets: self.block_offsets.read().unwrap().clone(),
77 counters: self.counters.read().unwrap().clone(),
78 }
79 }
80
81 pub fn restore(&self, snap: &RopeStoreSnapshot) {
84 *self.rope.write().unwrap() = snap.rope.clone();
85 *self.roots.write().unwrap() = snap.roots.clone();
86 *self.documents.write().unwrap() = snap.documents.clone();
87 *self.frames.write().unwrap() = snap.frames.clone();
88 *self.blocks.write().unwrap() = snap.blocks.clone();
89 *self.lists.write().unwrap() = snap.lists.clone();
90 *self.resources.write().unwrap() = snap.resources.clone();
91 *self.tables.write().unwrap() = snap.tables.clone();
92 *self.table_cells.write().unwrap() = snap.table_cells.clone();
93 *self.format_runs.write().unwrap() = snap.format_runs.clone();
94 *self.block_images.write().unwrap() = snap.block_images.clone();
95 *self.block_offsets.write().unwrap() = snap.block_offsets.clone();
96 *self.counters.write().unwrap() = snap.counters.clone();
97 }
98
99 pub fn restore_without_counters(&self, snap: &RopeStoreSnapshot) {
102 *self.rope.write().unwrap() = snap.rope.clone();
103 *self.roots.write().unwrap() = snap.roots.clone();
104 *self.documents.write().unwrap() = snap.documents.clone();
105 *self.frames.write().unwrap() = snap.frames.clone();
106 *self.blocks.write().unwrap() = snap.blocks.clone();
107 *self.lists.write().unwrap() = snap.lists.clone();
108 *self.resources.write().unwrap() = snap.resources.clone();
109 *self.tables.write().unwrap() = snap.tables.clone();
110 *self.table_cells.write().unwrap() = snap.table_cells.clone();
111 *self.format_runs.write().unwrap() = snap.format_runs.clone();
112 *self.block_images.write().unwrap() = snap.block_images.clone();
113 *self.block_offsets.write().unwrap() = snap.block_offsets.clone();
114 }
116
117 pub fn create_savepoint(&self) -> u64 {
118 let snap = self.snapshot();
119 let mut id_counter = self.next_savepoint_id.write().unwrap();
120 let id = *id_counter;
121 *id_counter += 1;
122 self.savepoints.write().unwrap().insert(id, snap);
123 id
124 }
125
126 pub fn restore_savepoint(&self, savepoint_id: u64) {
127 let snap = self
128 .savepoints
129 .read()
130 .unwrap()
131 .get(&savepoint_id)
132 .expect("savepoint not found")
133 .clone();
134 self.restore(&snap);
135 }
136
137 pub fn discard_savepoint(&self, savepoint_id: u64) {
138 self.savepoints.write().unwrap().remove(&savepoint_id);
139 }
140
141 pub(crate) fn next_id(&self, entity_name: &str) -> EntityId {
143 let mut counters = self.counters.write().unwrap();
144 let counter = counters.entry(entity_name.to_string()).or_insert(1);
145 let id = *counter;
146 *counter += 1;
147 id
148 }
149
150 pub fn store_snapshot(&self) -> StoreSnapshot {
152 StoreSnapshot::new(self.snapshot())
153 }
154
155 pub fn restore_store_snapshot(&self, snap: &StoreSnapshot) {
158 let s = snap
159 .downcast_ref::<RopeStoreSnapshot>()
160 .expect("StoreSnapshot must contain RopeStoreSnapshot");
161 self.restore_without_counters(s);
162 }
163}
164
165#[derive(Debug, Clone, Default)]
172pub struct RopeStoreSnapshot {
173 pub(crate) rope: Rope,
174 pub(crate) roots: HashMap<EntityId, Root>,
175 pub(crate) documents: HashMap<EntityId, Document>,
176 pub(crate) frames: HashMap<EntityId, Frame>,
177 pub(crate) blocks: HashMap<EntityId, Block>,
178 pub(crate) lists: HashMap<EntityId, List>,
179 pub(crate) resources: HashMap<EntityId, Resource>,
180 pub(crate) tables: HashMap<EntityId, Table>,
181 pub(crate) table_cells: HashMap<EntityId, TableCell>,
182 pub(crate) format_runs: HashMap<EntityId, Vec<FormatRun>>,
183 pub(crate) block_images: HashMap<EntityId, Vec<ImageAnchor>>,
184 pub(crate) block_offsets: BlockOffsetIndex,
185 pub(crate) counters: StdHashMap<String, EntityId>,
186}
187
188impl StoreSnapshotTrait for RopeStoreSnapshot {
189 fn clone_box(&self) -> Box<dyn StoreSnapshotTrait> {
190 Box::new(self.clone())
191 }
192
193 fn as_any(&self) -> &dyn std::any::Any {
194 self
195 }
196}