use std::{fs::File, mem::size_of};
use crate::import_export::JsonWrapper;
use crate::{Error};
use crate::error::Result;
use crate::relation::{DeletionBehaviour, EntityRelations, FamilyDescriptor, Relation};
use serde::{de::DeserializeOwned, Serialize};
use sled::{Batch, Db, IVec, Tree};
use std::convert::TryInto;
pub trait Entity: Serialize + DeserializeOwned {
type Key: AsBytes + Clone;
fn store_name() -> &'static str;
fn get_key(&self) -> &Self::Key;
fn set_key(&mut self, key: &Self::Key);
fn get_sibling_stores() -> Vec<(&'static str, DeletionBehaviour)> {
Vec::new()
}
fn get_child_stores() -> Vec<(&'static str, DeletionBehaviour)> {
Vec::new()
}
fn register(db: &Db) -> Result<()> {
let desc = FamilyDescriptor {
tree_name: String::from(Self::store_name()),
child_trees: Self::get_child_stores()
.iter()
.map(|e| (String::from(e.0), e.1))
.collect(),
sibling_trees: Self::get_sibling_stores()
.iter()
.map(|e| (String::from(e.0), e.1))
.collect(),
};
desc.save(db)?;
Ok(())
}
#[doc(hidden)]
fn get_tree(db: &Db) -> Result<Tree> {
Ok(db.open_tree(Self::store_name())?)
}
#[doc(hidden)]
fn from_ivec(vec: IVec) -> Self {
bincode::deserialize::<Self>(vec.as_ref()).unwrap()
}
#[doc(hidden)]
fn to_ivec(&self) -> IVec {
IVec::from(bincode::serialize(self).unwrap())
}
fn get(key: &Self::Key, db: &Db) -> Result<Option<Self>> {
Self::get_from_u8_array(&key.as_bytes(), db)
}
fn get_all(db: &Db) -> Result<Vec<Self>> {
Ok(Self::get_tree(db)?
.iter()
.map(|elem| Self::from_ivec(elem.unwrap().1))
.collect())
}
fn get_count(db: &Db) -> Result<usize> {
Ok(Self::get_tree(db)?.len())
}
#[doc(hidden)]
fn get_from_u8_array(key: &[u8], db: &Db) -> Result<Option<Self>> {
Ok(Self::get_tree(db)?
.get(key)?
.map(|vec| Self::from_ivec(vec)))
}
#[doc(hidden)]
fn get_with_prefix(key: &impl AsBytes, db: &Db) -> Result<Vec<Self>> {
Ok(Self::get_tree(db)?
.scan_prefix(key.as_bytes())
.map(|elem| Self::from_ivec(elem.unwrap().1))
.collect())
}
fn get_in_range(start: impl AsBytes, end: impl AsBytes, db: &Db) -> Result<Vec<Self>> {
Ok(Self::get_tree(db)?
.range(start.as_bytes()..end.as_bytes())
.map(|elem| Self::from_ivec(elem.unwrap().1))
.collect())
}
fn get_from_start(
start: usize,
count: usize,
parent: Option<impl AsBytes>,
db: &Db,
) -> Result<Vec<Self>> {
let mut iter = if let Some(prefix) = parent {
Self::get_tree(db)?.scan_prefix(prefix.as_bytes())
} else {
Self::get_tree(db)?.iter()
};
let mut result = Vec::new();
for i in 0..(start + count) {
match iter.next() {
Some(e) => {
if i >= start {
result.push(Self::from_ivec(e.unwrap().1));
}
}
None => return Ok(result),
}
}
Ok(result)
}
fn get_from_end(
start: usize,
offset: usize,
prefix: Option<impl AsBytes>,
db: &Db,
) -> Result<Vec<Self>> {
let mut iter = if let Some(prefix) = prefix {
Self::get_tree(db)?.scan_prefix(prefix.as_bytes())
} else {
Self::get_tree(db)?.iter()
};
let mut result = Vec::new();
for i in 0..(start + offset) {
match iter.next_back() {
Some(e) => {
if i >= start {
result.push(Self::from_ivec(e.unwrap().1));
}
}
None => break,
}
}
result.reverse();
Ok(result)
}
fn get_with_filter<F: Fn(&Self) -> bool>(f: F, db: &Db) -> Result<Vec<Self>> {
Ok(Self::get_tree(db)?
.iter()
.map(|elem| Self::from_ivec(elem.unwrap().1))
.filter(|e| f(e))
.collect())
}
fn get_each(keys: &[Self::Key], db: &Db) -> Vec<Self> {
keys.iter()
.map(|key| Self::get(key, db))
.filter_map(|res| match res {
Ok(opt) => opt,
Err(_) => None,
})
.collect()
}
#[doc(hidden)]
fn get_each_u8(keys: &[Vec<u8>], db: &Db) -> Vec<Self> {
keys.iter()
.map(|key| Self::get_from_u8_array(key, db))
.filter_map(|res| match res {
Ok(opt) => opt,
Err(_) => None,
})
.collect()
}
fn save(&self, db: &Db) -> Result<()> {
Self::get_tree(db)?.insert(
&self.get_key().as_bytes(),
bincode::serialize(self).unwrap(),
)?;
Ok(())
}
fn update<F: Fn(&mut Self)>(key: &Self::Key, f: F, db: &Db) -> Result<()> {
Self::get_tree(db)?.fetch_and_update(&key.as_bytes(), |e| {
e.map(|u8_arr| {
let mut value: Self = Self::from_ivec(IVec::from(u8_arr));
f(&mut value);
value.to_ivec()
})
})?;
Ok(())
}
fn filter_update<F: Fn(&Self) -> bool, M: Fn(&mut Self)>(
filter: F,
modifier: M,
db: &Db,
) -> Result<()> {
let mut res = Self::get_with_filter(filter, db)?;
for entity in &mut res {
modifier(entity);
entity.save(db)?;
}
Ok(())
}
fn use_pre_remove_hook() -> bool {
false
}
fn pre_remove_hook(&self, _db : &Db) -> Result<()> {
Ok(())
}
#[doc(hidden)]
fn pre_remove(key: &[u8], db: &Db) -> Result<()> {
let mut to_be_removed = EntityRelations::default();
Relation::can_be_deleted(Self::store_name(), key, &Vec::new(), &mut to_be_removed, db)?;
for (tree, keys) in &to_be_removed.related_entities {
let tree = db.open_tree(tree)?;
let mut batch = Batch::default();
keys.iter().for_each(|rd| batch.remove(rd.key.as_slice()));
tree.apply_batch(batch)?;
}
Relation::remove_entity_entry::<Self>(key, db)?;
Relation::remove_descriptor(Self::store_name(), key, db)?;
Ok(())
}
#[doc(hidden)]
fn can_be_removed(key: &[u8], db: &Db) -> Result<()> {
Relation::can_be_deleted(
Self::store_name(),
key,
&Vec::new(),
&mut EntityRelations::default(),
db,
)?;
Ok(())
}
fn remove(key: &Self::Key, db: &Db) -> Result<()> {
Self::remove_from_u8_array(&key.as_bytes(), db)
}
#[doc(hidden)]
fn remove_from_u8_array(key: &[u8], db: &Db) -> Result<()> {
Self::pre_remove(key, db)?;
if Self::use_pre_remove_hook() {
Self::pre_remove_hook(&Self::get_from_u8_array(key, db)?.ok_or(Error::new(crate::ErrorKind::IntegrityError,"Entry was not found".to_string()))?, db)?;
}
Self::get_tree(db)?.remove(key)?;
Ok(())
}
#[doc(hidden)]
fn remove_prefixed(prefix: impl AsBytes, db: &Db) -> Result<()> {
Self::remove_prefixed_in_tree(Self::store_name(), &prefix.as_bytes(), db)
}
#[doc(hidden)]
fn remove_prefixed_in_tree(tree_name: &str, prefix: &[u8], db: &Db) -> Result<()> {
let tree = db.open_tree(tree_name)?;
let mut batch = Batch::default();
tree.scan_prefix(prefix).for_each(|elem| {
if let Ok((key, _)) = elem {
if Self::pre_remove(&key, db).is_ok() {
batch.remove(key)
}
}
});
tree.apply_batch(batch)?;
Ok(())
}
fn filter_remove<F: Fn(&Self) -> bool>(f: F, db: &Db) -> Result<Vec<Self>> {
let mut res = Self::get_with_filter(f, db)?;
let mut to_remove_from_result = Vec::new();
for (index, entity) in res.iter().enumerate() {
if Self::remove(entity.get_key(), db).is_err() {
to_remove_from_result.push(index)
};
}
for index in to_remove_from_result {
res.remove(index);
}
Ok(res)
}
fn exists(key: &Self::Key, db: &Db) -> Result<bool> {
Ok(Self::get_tree(db)?.contains_key(&key.as_bytes())?)
}
fn export_json(f: File, pretty : bool, db: &Db) -> Result<()> {
let all = Self::get_all(db)?;
if pretty {
serde_json::to_writer_pretty(f, &JsonWrapper::from(all, db)?)?;
}
else {
serde_json::to_writer(f, &JsonWrapper::from(all, db)?)?;
}
Ok(())
}
fn import_json(f: File, db: &Db) -> Result<()> {
let wrapper : JsonWrapper<Self> = serde_json::from_reader(f)?;
wrapper.save(db)?;
Ok(())
}
fn create_relation<E: Entity>(
&self,
other: &E,
self_to_other: DeletionBehaviour,
other_to_self: DeletionBehaviour,
name: Option<&str>,
db: &Db,
) -> Result<()> {
Relation::create(self, other, self_to_other, other_to_self, name, db)
}
fn remove_relation<E: Entity>(&self, other: &E, db: &Db) -> Result<()> {
Relation::remove(self, other, db)
}
fn remove_relation_with_name<E: Entity>(&self, other: &E, name: &str, db: &Db) -> Result<()> {
Relation::remove_with_name(self, other, name, db)
}
#[doc(hidden)]
fn remove_relation_with_key<E: Entity>(&self, other: &[u8], db: &Db) -> Result<()> {
Relation::remove_by_keys::<Self, E>(&self.get_key().as_bytes(), other, db)
}
fn get_related<E: Entity>(&self, db: &Db) -> Result<Vec<E>> {
Relation::get::<Self, E>(self, db)
}
fn get_related_with_name<E: Entity>(&self, name: &str, db: &Db) -> Result<Vec<E>> {
Relation::get_with_name::<Self, E>(self, name, db)
}
fn get_single_related<E: Entity>(&self, db: &Db) -> Result<Option<E>> {
Relation::get_one::<Self, E>(self, db)
}
fn get_single_related_with_name<E: Entity>(&self, name: &str, db: &Db) -> Result<Option<E>> {
Relation::get_one_with_name::<Self, E>(self, name, db)
}
fn is_related_to<E: Entity>(&self, other: &E, db: &Db) -> Result<bool> {
Relation::are_related(self, other, db)
}
fn is_related_to_with_name<E: Entity>(&self, other: &E, name: &str, db: &Db) -> Result<bool> {
Relation::are_related_with_name(self, other, name, db)
}
fn is_related_to_with_any_name<E: Entity>(
&self,
other: &E,
names: &[&str],
db: &Db,
) -> Result<bool> {
Relation::are_related_with_any_name(self, other, names, db)
}
fn save_sibling<E: Entity<Key = Self::Key>>(&self, sibling: &mut E, db: &Db) -> Result<()> {
sibling.set_key(self.get_key());
sibling.save(db)
}
fn get_sibling<E: Entity<Key = Self::Key>>(&self, db: &Db) -> Result<Option<E>> {
E::get(self.get_key(), db)
}
fn save_child<E: Entity<Key = (Self::Key, T)>, T: Clone>(
&self,
child: &mut E,
db: &Db,
) -> Result<E::Key> {
let key = (self.get_key().clone(), child.get_key().1.clone());
child.set_key(&key);
child.save(db)?;
Ok(key)
}
fn save_next_child<E: Entity<Key = (Self::Key, u32)>>(
&self,
child: &mut E,
db: &Db,
) -> Result<E::Key> {
let increment = match E::get_tree(db)?.last()? {
Some((key, _)) => {
let u32_part = key
.iter()
.rev()
.take(size_of::<u32>())
.rev()
.copied()
.collect::<Vec<u8>>();
u32::from_be_bytes(u32_part.try_into().unwrap()) + 1
}
None => Default::default(),
};
let key = (self.get_key().clone(), increment);
child.set_key(&key);
child.save(db)?;
Ok(key)
}
fn adopt_as_next_child<E: Entity<Key = (Self::Key, u32)>>(
&self,
child: &mut E,
db: &Db,
) -> Result<()> {
let old_id = child.get_key().clone();
self.save_next_child(child, db)?;
Relation::change_entity_id(
E::store_name(),
&old_id.as_bytes(),
&child.get_key().as_bytes(),
db,
)?;
E::remove(&old_id, db)?;
Ok(())
}
fn adopt_child<E: Entity<Key = (Self::Key, T)>, T: Clone + AsBytes>(
&self,
child: &mut E,
db: &Db,
) -> Result<()> where <Self as Entity>::Key : PartialEq {
if child.get_key().0 == *self.get_key() {
return Ok(());
}
let old_id = child.get_key().clone();
self.save_child(child, db)?;
Relation::change_entity_id(
E::store_name(),
&old_id.as_bytes(),
&child.get_key().as_bytes(),
db,
)?;
E::remove(&old_id, db)?;
Ok(())
}
fn get_children<E: Entity<Key = (Self::Key, impl AsBytes)>>(&self, db: &Db) -> Result<Vec<E>> {
E::get_with_prefix(self.get_key(), db)
}
}
pub trait AutoIncrementEntity: Entity<Key = u32> {
fn get_next_key(db: &Db) -> Result<u32>;
fn save_next(&mut self, db: &Db) -> Result<u32>;
}
impl<T> AutoIncrementEntity for T
where
T: Entity<Key = u32>,
{
fn get_next_key(db: &Db) -> Result<u32> {
match Self::get_tree(db)?.last()? {
Some((key, _)) => Ok(u32::from_be_bytes(key.as_ref().try_into().unwrap()) + 1),
None => Ok(Default::default()),
}
}
fn save_next(&mut self, db: &Db) -> Result<u32> {
let next_key = Self::get_next_key(db)?;
self.set_key(&next_key);
self.save(db)?;
Ok(next_key)
}
}
pub trait AsBytes {
fn as_bytes(&self) -> Vec<u8>;
}
impl AsBytes for String {
fn as_bytes(&self) -> Vec<u8> {
self.as_bytes().to_owned()
}
}
impl AsBytes for u32 {
fn as_bytes(&self) -> Vec<u8> {
self.to_be_bytes().to_vec()
}
}
impl AsBytes for u64 {
fn as_bytes(&self) -> Vec<u8> {
self.to_be_bytes().to_vec()
}
}
impl AsBytes for i32 {
fn as_bytes(&self) -> Vec<u8> {
self.to_be_bytes().to_vec()
}
}
impl AsBytes for i64 {
fn as_bytes(&self) -> Vec<u8> {
self.to_be_bytes().to_vec()
}
}
impl AsBytes for Vec<u8> {
fn as_bytes(&self) -> Vec<u8> {
self.clone()
}
}
impl AsBytes for &[u8] {
fn as_bytes(&self) -> Vec<u8> {
self.to_vec()
}
}
impl<K1, K2> AsBytes for (K1, K2)
where
K1: AsBytes,
K2: AsBytes,
{
fn as_bytes(&self) -> Vec<u8> {
vec![self.0.as_bytes(), self.1.as_bytes()].concat()
}
}