use crate::{Location, StoreImpl};
use serde::{de::DeserializeOwned, Serialize};
#[derive(Debug)]
pub struct RocksDBStore {
db: rocksdb::DB,
}
pub use RocksDBStore as InnerStore;
#[derive(thiserror::Error, Debug)]
pub enum GetError {
#[error("Rocksdb error")]
Rocksdb(#[from] rocksdb::Error),
#[error("MessagePack deserialization error")]
MessagePack(#[from] rmp_serde::decode::Error),
#[error("No value found for the given key")]
NotFound,
}
#[derive(thiserror::Error, Debug)]
pub enum SetError {
#[error("Rocksdb error")]
Rocksdb(#[from] rocksdb::Error),
#[error("MessagePack serialization error")]
MessagePack(#[from] rmp_serde::encode::Error),
}
#[derive(thiserror::Error, Debug)]
pub enum RemoveError {
#[error("Rocksdb error")]
Rocksdb(#[from] rocksdb::Error),
#[error("MessagePack deserialization error")]
MessagePack(#[from] rmp_serde::decode::Error),
#[error("No value found for the given key")]
NotFound,
}
impl RocksDBStore {
pub(crate) fn new(location: Location) -> Self {
let mut options = rocksdb::Options::default();
options.set_error_if_exists(false);
options.create_if_missing(true);
options.create_missing_column_families(true);
let db_path = location.get_path().join("bevy_rocksdb_pkv");
let db = rocksdb::DB::open(&options, db_path).expect("Failed to init key value store");
Self { db }
}
pub(crate) fn new_with_filename(location: Location, filename: &str) -> Self {
let mut options = rocksdb::Options::default();
options.set_error_if_exists(false);
options.create_if_missing(true);
options.create_missing_column_families(true);
let db_path = location.get_path().join(filename);
let db = rocksdb::DB::open(&options, db_path).expect("Failed to init key value store");
Self { db }
}
}
impl StoreImpl for RocksDBStore {
type GetError = GetError;
type SetError = SetError;
type RemoveError = RemoveError;
fn set<T: Serialize>(&mut self, key: &str, value: &T) -> Result<(), Self::SetError> {
let mut serializer = rmp_serde::Serializer::new(Vec::new()).with_struct_map();
value.serialize(&mut serializer)?;
self.db.put(key, serializer.into_inner())?;
Ok(())
}
fn set_string(&mut self, key: &str, value: &str) -> Result<(), Self::SetError> {
let bytes = rmp_serde::to_vec(value)?;
self.db.put(key, bytes)?;
Ok(())
}
fn get<T: DeserializeOwned>(&self, key: &str) -> Result<T, Self::GetError> {
let bytes = self.db.get(key)?.ok_or(Self::GetError::NotFound)?;
let value = rmp_serde::from_slice(&bytes)?;
Ok(value)
}
fn clear(&mut self) -> Result<(), Self::SetError> {
let kv_iter = self.db.iterator(rocksdb::IteratorMode::Start);
for kv in kv_iter {
let (key, _) = kv?;
self.db.delete(key)?;
}
Ok(())
}
fn remove(&mut self, key: &str) -> Result<(), Self::RemoveError> {
self.db.delete(key)?;
Ok(())
}
fn remove_and_get<T: DeserializeOwned>(
&mut self,
key: &str,
) -> Result<Option<T>, Self::RemoveError> {
let bytes = self.db.get(key)?.ok_or(Self::RemoveError::NotFound)?;
let value = rmp_serde::from_slice(&bytes)?;
self.db.delete(key)?;
Ok(value)
}
}