use crate::fx::FxHashMap; use crate::undo_log::{Rollback, Snapshots, UndoLogs, VecLog}; use std::borrow::{Borrow, BorrowMut}; use std::hash::Hash; use std::marker::PhantomData; use std::ops; pub use crate::undo_log::Snapshot; #[cfg(test)] mod tests; pub type SnapshotMapStorage = SnapshotMap, ()>; pub type SnapshotMapRef<'a, K, V, L> = SnapshotMap, &'a mut L>; #[derive(Clone)] pub struct SnapshotMap, L = VecLog>> { map: M, undo_log: L, _marker: PhantomData<(K, V)>, } // HACK(eddyb) manual impl avoids `Default` bounds on `K` and `V`. impl Default for SnapshotMap where M: Default, L: Default, { fn default() -> Self { SnapshotMap { map: Default::default(), undo_log: Default::default(), _marker: PhantomData } } } #[derive(Clone)] pub enum UndoLog { Inserted(K), Overwrite(K, V), Purged, } impl SnapshotMap { #[inline] pub fn with_log(&mut self, undo_log: L2) -> SnapshotMap { SnapshotMap { map: &mut self.map, undo_log, _marker: PhantomData } } } impl SnapshotMap where K: Hash + Clone + Eq, M: BorrowMut> + Borrow>, L: UndoLogs>, { pub fn clear(&mut self) { self.map.borrow_mut().clear(); self.undo_log.clear(); } pub fn insert(&mut self, key: K, value: V) -> bool { match self.map.borrow_mut().insert(key.clone(), value) { None => { self.undo_log.push(UndoLog::Inserted(key)); true } Some(old_value) => { self.undo_log.push(UndoLog::Overwrite(key, old_value)); false } } } pub fn remove(&mut self, key: K) -> bool { match self.map.borrow_mut().remove(&key) { Some(old_value) => { self.undo_log.push(UndoLog::Overwrite(key, old_value)); true } None => false, } } pub fn get(&self, key: &K) -> Option<&V> { self.map.borrow().get(key) } } impl SnapshotMap where K: Hash + Clone + Eq, { pub fn snapshot(&mut self) -> Snapshot { self.undo_log.start_snapshot() } pub fn commit(&mut self, snapshot: Snapshot) { self.undo_log.commit(snapshot) } pub fn rollback_to(&mut self, snapshot: Snapshot) { let map = &mut self.map; self.undo_log.rollback_to(|| map, snapshot) } } impl<'k, K, V, M, L> ops::Index<&'k K> for SnapshotMap where K: Hash + Clone + Eq, M: Borrow>, { type Output = V; fn index(&self, key: &'k K) -> &V { &self.map.borrow()[key] } } impl Rollback> for SnapshotMap where K: Eq + Hash, M: Rollback>, { fn reverse(&mut self, undo: UndoLog) { self.map.reverse(undo) } } impl Rollback> for FxHashMap where K: Eq + Hash, { fn reverse(&mut self, undo: UndoLog) { match undo { UndoLog::Inserted(key) => { self.remove(&key); } UndoLog::Overwrite(key, old_value) => { self.insert(key, old_value); } UndoLog::Purged => {} } } }