use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use sled::{IVec, Tree};
use uuid::Uuid;
use crate::{error::ErrorKind, Result};
use super::{decode, encode, Collectable, Identifiable};
#[derive(Clone, Debug)]
pub struct SledDb {
inner: sled::Db,
}
impl SledDb {
pub fn new() -> Result<Self> {
let inner = sled::Config::default()
.path("./db")
.open()
.expect("failed to open db");
Ok(Self { inner })
}
pub fn trees_for<T: Collectable>(&self) -> Result<Vec<String>> {
Ok(self
.inner
.tree_names()
.into_iter()
.map(|s| String::from_utf8_lossy(&s).into_owned())
.filter(|t| t.contains(T::get_collection_name()))
.collect::<Vec<_>>())
}
pub fn get_collection<T: DeserializeOwned + Collectable>(&self) -> Result<Vec<T>> {
self.get_collection_at(T::get_collection_name())
}
pub fn get_collection_at<T: DeserializeOwned + Collectable>(
&self,
name: impl AsRef<[u8]>,
) -> Result<Vec<T>> {
let tree = self.inner.open_tree(name)?;
let mut out = Vec::new();
for entry in tree.iter() {
let (_, value_bytes) = entry?;
let value: T = decode(&value_bytes).unwrap();
out.push(value);
}
Ok(out)
}
pub fn len<T: Collectable>(&self) -> Result<usize> {
Ok(self.inner.open_tree(T::get_collection_name())?.len())
}
pub fn get_collection_raw<T: Collectable>(&self) -> Result<Vec<(Vec<u8>, Vec<u8>)>> {
let tree = self.inner.open_tree(T::get_collection_name())?;
let mut out = Vec::new();
for entry in tree.iter() {
let (key, value) = entry?;
out.push((key.to_vec(), value.to_vec()));
}
Ok(out)
}
pub fn get<T: DeserializeOwned + Collectable>(&self, id: Uuid) -> Result<T> {
self.get_at(T::get_collection_name(), id)
}
pub fn get_at<T: DeserializeOwned>(&self, collection: &str, id: Uuid) -> Result<T> {
let tree = self.inner.open_tree(collection)?;
for entry in tree.iter() {
let (id_bytes, value_bytes) = entry?;
let _id = Uuid::from_slice(&id_bytes)?;
if _id == id {
let value: T = decode(&value_bytes)?;
return Ok(value);
}
}
Err(ErrorKind::DbError(format!(
"entity with id '{}' not found in collection {}",
id, collection
))
.into())
}
pub fn get_or_create<T: Serialize + DeserializeOwned + Identifiable + Collectable + Default>(
&self,
id: Uuid,
) -> Result<T> {
self.get::<T>(id).or_else(|_| {
let default = T::default();
self.set(&default).map(|_| default)
})
}
pub fn set<T: Serialize + Identifiable + Collectable>(&self, value: &T) -> Result<()> {
self.set_at(T::get_collection_name(), value)?;
Ok(())
}
pub fn set_at<T: Serialize + Identifiable + Collectable>(
&self,
collection: impl AsRef<[u8]>,
value: &T,
) -> Result<()> {
self.set_raw_at(collection, value, value.get_id())?;
Ok(())
}
pub fn set_raw_at<T: Serialize>(
&self,
collection: impl AsRef<[u8]>,
value: &T,
id: Uuid,
) -> Result<()> {
let tree = self.inner.open_tree(collection)?;
let encoded = encode(value)?;
tree.insert(id, encoded)?;
Ok(())
}
pub fn remove<T: Identifiable + Collectable>(&self, value: &T) -> Result<()> {
self.remove_at(T::get_collection_name(), value)
}
pub fn remove_at<T: Identifiable + Collectable>(
&self,
collection: impl AsRef<[u8]>,
value: &T,
) -> Result<()> {
let tree = self.inner.open_tree(collection)?;
tree.remove(value.get_id())?;
Ok(())
}
pub fn clear_at(&self, collection: &str) -> Result<()> {
let tree = self.inner.open_tree(collection)?;
tree.clear()?;
Ok(())
}
pub fn clear<T: Collectable>(&self) -> Result<()> {
let tree = self.inner.open_tree(T::get_collection_name())?;
tree.clear()?;
Ok(())
}
}