use crate::database::block_offset_index::BlockOffsetIndex;
use crate::entities::*;
use crate::format_runs::{FormatRun, ImageAnchor};
use crate::snapshot::{StoreSnapshot, StoreSnapshotTrait};
use crate::types::EntityId;
use im::HashMap;
use ropey::Rope;
use std::collections::HashMap as StdHashMap;
use std::sync::RwLock;
#[derive(Debug, Default)]
pub struct RopeStore {
pub rope: RwLock<Rope>,
pub roots: RwLock<HashMap<EntityId, Root>>,
pub documents: RwLock<HashMap<EntityId, Document>>,
pub frames: RwLock<HashMap<EntityId, Frame>>,
pub blocks: RwLock<HashMap<EntityId, Block>>,
pub lists: RwLock<HashMap<EntityId, List>>,
pub resources: RwLock<HashMap<EntityId, Resource>>,
pub tables: RwLock<HashMap<EntityId, Table>>,
pub table_cells: RwLock<HashMap<EntityId, TableCell>>,
pub format_runs: RwLock<HashMap<EntityId, Vec<FormatRun>>>,
pub block_images: RwLock<HashMap<EntityId, Vec<ImageAnchor>>>,
pub block_offsets: RwLock<BlockOffsetIndex>,
pub counters: RwLock<StdHashMap<String, EntityId>>,
savepoints: RwLock<StdHashMap<u64, RopeStoreSnapshot>>,
next_savepoint_id: RwLock<u64>,
}
impl RopeStore {
pub fn new() -> Self {
Self::default()
}
pub fn snapshot(&self) -> RopeStoreSnapshot {
RopeStoreSnapshot {
rope: self.rope.read().unwrap().clone(),
roots: self.roots.read().unwrap().clone(),
documents: self.documents.read().unwrap().clone(),
frames: self.frames.read().unwrap().clone(),
blocks: self.blocks.read().unwrap().clone(),
lists: self.lists.read().unwrap().clone(),
resources: self.resources.read().unwrap().clone(),
tables: self.tables.read().unwrap().clone(),
table_cells: self.table_cells.read().unwrap().clone(),
format_runs: self.format_runs.read().unwrap().clone(),
block_images: self.block_images.read().unwrap().clone(),
block_offsets: self.block_offsets.read().unwrap().clone(),
counters: self.counters.read().unwrap().clone(),
}
}
pub fn restore(&self, snap: &RopeStoreSnapshot) {
*self.rope.write().unwrap() = snap.rope.clone();
*self.roots.write().unwrap() = snap.roots.clone();
*self.documents.write().unwrap() = snap.documents.clone();
*self.frames.write().unwrap() = snap.frames.clone();
*self.blocks.write().unwrap() = snap.blocks.clone();
*self.lists.write().unwrap() = snap.lists.clone();
*self.resources.write().unwrap() = snap.resources.clone();
*self.tables.write().unwrap() = snap.tables.clone();
*self.table_cells.write().unwrap() = snap.table_cells.clone();
*self.format_runs.write().unwrap() = snap.format_runs.clone();
*self.block_images.write().unwrap() = snap.block_images.clone();
*self.block_offsets.write().unwrap() = snap.block_offsets.clone();
*self.counters.write().unwrap() = snap.counters.clone();
}
pub fn restore_without_counters(&self, snap: &RopeStoreSnapshot) {
*self.rope.write().unwrap() = snap.rope.clone();
*self.roots.write().unwrap() = snap.roots.clone();
*self.documents.write().unwrap() = snap.documents.clone();
*self.frames.write().unwrap() = snap.frames.clone();
*self.blocks.write().unwrap() = snap.blocks.clone();
*self.lists.write().unwrap() = snap.lists.clone();
*self.resources.write().unwrap() = snap.resources.clone();
*self.tables.write().unwrap() = snap.tables.clone();
*self.table_cells.write().unwrap() = snap.table_cells.clone();
*self.format_runs.write().unwrap() = snap.format_runs.clone();
*self.block_images.write().unwrap() = snap.block_images.clone();
*self.block_offsets.write().unwrap() = snap.block_offsets.clone();
}
pub fn create_savepoint(&self) -> u64 {
let snap = self.snapshot();
let mut id_counter = self.next_savepoint_id.write().unwrap();
let id = *id_counter;
*id_counter += 1;
self.savepoints.write().unwrap().insert(id, snap);
id
}
pub fn restore_savepoint(&self, savepoint_id: u64) {
let snap = self
.savepoints
.read()
.unwrap()
.get(&savepoint_id)
.expect("savepoint not found")
.clone();
self.restore(&snap);
}
pub fn discard_savepoint(&self, savepoint_id: u64) {
self.savepoints.write().unwrap().remove(&savepoint_id);
}
pub(crate) fn next_id(&self, entity_name: &str) -> EntityId {
let mut counters = self.counters.write().unwrap();
let counter = counters.entry(entity_name.to_string()).or_insert(1);
let id = *counter;
*counter += 1;
id
}
pub fn store_snapshot(&self) -> StoreSnapshot {
StoreSnapshot::new(self.snapshot())
}
pub fn restore_store_snapshot(&self, snap: &StoreSnapshot) {
let s = snap
.downcast_ref::<RopeStoreSnapshot>()
.expect("StoreSnapshot must contain RopeStoreSnapshot");
self.restore_without_counters(s);
}
}
#[derive(Debug, Clone, Default)]
pub struct RopeStoreSnapshot {
pub(crate) rope: Rope,
pub(crate) roots: HashMap<EntityId, Root>,
pub(crate) documents: HashMap<EntityId, Document>,
pub(crate) frames: HashMap<EntityId, Frame>,
pub(crate) blocks: HashMap<EntityId, Block>,
pub(crate) lists: HashMap<EntityId, List>,
pub(crate) resources: HashMap<EntityId, Resource>,
pub(crate) tables: HashMap<EntityId, Table>,
pub(crate) table_cells: HashMap<EntityId, TableCell>,
pub(crate) format_runs: HashMap<EntityId, Vec<FormatRun>>,
pub(crate) block_images: HashMap<EntityId, Vec<ImageAnchor>>,
pub(crate) block_offsets: BlockOffsetIndex,
pub(crate) counters: StdHashMap<String, EntityId>,
}
impl StoreSnapshotTrait for RopeStoreSnapshot {
fn clone_box(&self) -> Box<dyn StoreSnapshotTrait> {
Box::new(self.clone())
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
}