use std::borrow::Borrow;
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use sled::Tree;
use crate::database::{
CompareAndSwapTransaction, CustomTransactionError, Database, DatabaseError, EntryId,
TransactionError, deserialize_from_ivec, sled_get_all_raw, sled_get_batch_raw, sled_get_raw,
transaction_args::db_transaction,
};
pub trait DatabaseEntry:
Serialize + DeserializeOwned + for<'de> Deserialize<'de> + Clone + std::fmt::Debug + 'static
{
type EntryDb: Database;
type Id: EntryId<Entry = Self, IdDb = Self::EntryDb>;
const VERSION_NUMBER: u32;
fn db_check(id: Self::Id) -> Result<bool, DatabaseError> {
let db = Self::EntryDb::open()?;
Ok(Self::tree(&db).contains_key(&*id)?)
}
fn db_get_from(id: Self::Id, db: &Self::EntryDb) -> Result<Option<Self>, DatabaseError> {
Ok(sled_get_raw(&Self::tree(db), id.as_bytes())?
.map(deserialize_from_ivec)
.transpose()?)
}
fn db_get(id: Self::Id) -> Result<Option<Self>, DatabaseError> {
let db = Self::EntryDb::open()?;
Self::db_get_from(id, &db)
}
fn db_get_all_from(db: &Self::EntryDb) -> Result<Vec<Self>, DatabaseError> {
sled_get_all_raw(&Self::tree(db))?
.into_iter()
.map(deserialize_from_ivec)
.collect()
}
fn db_get_all() -> Result<Vec<Self>, DatabaseError> {
let db = Self::EntryDb::open()?;
Self::db_get_all_from(&db)
}
fn db_get_batch_from<I, A>(ids: I, db: &Self::EntryDb) -> Result<Vec<Self>, DatabaseError>
where
I: IntoIterator<Item = A>,
A: Borrow<Self::Id>,
{
let items = sled_get_batch_raw(
&Self::tree(db),
ids.into_iter().map(|a| *a.borrow().as_bytes()),
)?;
items.into_iter().map(deserialize_from_ivec).collect()
}
fn db_get_batch<I, A>(ids: I) -> Result<Vec<Self>, DatabaseError>
where
I: IntoIterator<Item = A>,
A: Borrow<Self::Id>,
{
let db = Self::EntryDb::open()?;
Self::db_get_batch_from(ids, &db)
}
fn pre_upsert(
&mut self,
_cas_tx: &CompareAndSwapTransaction<Self::EntryDb>,
) -> Result<(), TransactionError> {
Ok(())
}
fn db_upsert(&self) -> Result<(), TransactionError> {
db_transaction(
|cas_tx| {
cas_tx
.tx_upsert(self.id(), Some(self.clone()))
.map_err(CustomTransactionError::from)
},
None,
false,
)?;
Ok(())
}
fn read_only(&self) -> bool {
false
}
fn id(&self) -> Self::Id;
fn tree(db: &Self::EntryDb) -> Tree;
}