use crate::prelude::*;
#[derive(HasSchema)]
#[schema(no_clone)]
pub struct Storage {
pub backend: Box<dyn StorageApi>,
pub cache: HashMap<SchemaId, SchemaBox>,
}
#[allow(clippy::derivable_impls)] impl Default for Storage {
fn default() -> Self {
Self {
backend: Box::<MemoryBackend>::default(),
cache: Default::default(),
}
}
}
impl Storage {
pub fn with_backend(backend: Box<dyn StorageApi>) -> Self {
Self {
backend,
cache: default(),
}
}
pub fn load(&mut self) {
self.cache = self
.backend
.load()
.into_iter()
.map(|x| (x.schema().id(), x))
.collect();
}
pub fn save(&mut self) {
self.backend.save(self.cache.values().cloned().collect())
}
pub fn insert<T: HasSchema>(&mut self, data: T) {
let b = SchemaBox::new(data);
self.cache.insert(b.schema().id(), b);
}
pub fn get<T: HasSchema>(&self) -> Option<&T> {
self.cache.get(&T::schema().id()).map(|x| x.cast_ref())
}
pub fn get_mut<T: HasSchema>(&mut self) -> Option<&mut T> {
self.cache.get_mut(&T::schema().id()).map(|x| x.cast_mut())
}
pub fn get_or_insert_default<T: HasSchema + Default>(&mut self) -> &T {
self.cache
.entry(T::schema().id())
.or_insert_with(|| SchemaBox::default(T::schema()))
.cast_ref()
}
pub fn get_or_insert_default_mut<T: HasSchema + Default>(&mut self) -> &mut T {
self.cache
.entry(T::schema().id())
.or_insert_with(|| SchemaBox::default(T::schema()))
.cast_mut()
}
pub fn remove<T: HasSchema>(&mut self) {
self.cache.remove(&T::schema().id());
}
}
pub trait StorageApi: Sync + Send {
fn save(&mut self, data: Vec<SchemaBox>);
fn load(&mut self) -> Vec<SchemaBox>;
}
#[derive(Default)]
pub struct MemoryBackend {
data: Vec<SchemaBox>,
}
impl StorageApi for MemoryBackend {
fn save(&mut self, data: Vec<SchemaBox>) {
self.data = data;
}
fn load(&mut self) -> Vec<SchemaBox> {
self.data.clone()
}
}