use std::cell::RefCell;
use std::rc::Rc;
use super::cache::CacheOp::{Remove, Update};
use super::node::Node;
use super::{ORDER, ROOT_KEY};
use crate::__private::{
read_field, storage_gen_sub_key, storage_has_key, storage_remove, write_field,
};
use nohash_hasher::IntMap;
use serde::de::DeserializeOwned;
use serde::Serialize;
enum CacheOp {
Update,
Remove,
}
pub struct Cache<V> {
base_key: u64,
map: RefCell<IntMap<u64, Rc<RefCell<Node<V>>>>>,
operations: IntMap<u64, CacheOp>,
}
impl<V> Cache<V>
where
V: Serialize + DeserializeOwned,
{
pub(crate) fn new(base_key: u64, init: bool) -> Self {
let mut cache = Cache {
base_key,
map: RefCell::default(),
operations: IntMap::default(),
};
if init {
cache.init();
}
cache
}
pub(crate) fn exists(&self) -> bool {
storage_has_key(self.base_key, ROOT_KEY)
}
pub(crate) fn init(&mut self) {
self.write(ROOT_KEY, Node::<V>::empty_leaf(ORDER));
}
pub(crate) fn reset(&mut self) {
self.map = RefCell::default();
self.operations = IntMap::default();
}
pub(crate) fn new_key(&mut self) -> u64 {
storage_gen_sub_key()
}
pub(crate) fn read(&self, key: u64) -> Rc<RefCell<Node<V>>> {
if let Some(node) = self.map.borrow().get(&key) {
return node.clone();
};
let node = read_field::<Node<V>>(self.base_key, key).unwrap();
let node = Rc::new(RefCell::new(node));
self.map.borrow_mut().insert(key, node.clone());
node
}
pub(crate) fn remove(&mut self, key: u64) {
self.operations.insert(key, Remove);
self.map.borrow_mut().remove(&key);
}
pub(crate) fn flag_write(&mut self, key: u64) {
self.operations.insert(key, Update);
}
pub(crate) fn replace(&mut self, old_key: u64, new_key: u64, cell: Rc<RefCell<Node<V>>>) {
self.operations.insert(new_key, Update);
self.map.borrow_mut().insert(new_key, cell);
self.remove(old_key);
}
pub(crate) fn write(&mut self, key: u64, node: Node<V>) {
self.operations.insert(key, Update);
self.map
.borrow_mut()
.insert(key, Rc::new(RefCell::new(node)));
}
pub(crate) fn clear(&mut self) {
for key in self.map.borrow().keys() {
self.operations.insert(*key, Remove);
}
self.map.borrow_mut().clear();
self.init();
}
pub(crate) fn commit(self) {
for (key, op) in &self.operations {
match op {
Update => {
let map = self.map.borrow();
let node = map.get(key).expect("Cache corruption");
write_field(self.base_key, *key, node.as_ref());
}
Remove => storage_remove(self.base_key, *key),
}
}
}
}