use crate::error::NetabaseError;
use crate::traits::definition::NetabaseDefinitionTrait;
use crate::traits::model::NetabaseModelTrait;
use crate::traits::store_ops::OpenTree;
use std::marker::PhantomData;
use std::path::Path;
pub trait BackendFor<D: NetabaseDefinitionTrait> {}
pub trait BackendConstructor<D: NetabaseDefinitionTrait>: BackendFor<D> + Sized {
fn new_backend<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError>;
}
#[cfg(feature = "sled")]
impl<D> BackendFor<D> for crate::databases::sled_store::SledStore<D> where D: NetabaseDefinitionTrait
{}
#[cfg(feature = "sled")]
impl<D> BackendConstructor<D> for crate::databases::sled_store::SledStore<D>
where
D: NetabaseDefinitionTrait + crate::traits::convert::ToIVec,
<D as strum::IntoDiscriminant>::Discriminant: crate::traits::definition::NetabaseDiscriminant,
{
fn new_backend<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
crate::databases::sled_store::SledStore::new(path)
}
}
#[cfg(feature = "redb")]
impl<D> BackendFor<D> for crate::databases::redb_store::RedbStore<D> where D: NetabaseDefinitionTrait
{}
#[cfg(feature = "redb")]
impl<D> BackendConstructor<D> for crate::databases::redb_store::RedbStore<D>
where
D: NetabaseDefinitionTrait + crate::traits::convert::ToIVec,
<D as strum::IntoDiscriminant>::Discriminant: crate::traits::definition::NetabaseDiscriminant,
{
fn new_backend<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
crate::databases::redb_store::RedbStore::new(path)
}
}
pub struct NetabaseStore<D, Backend>
where
D: NetabaseDefinitionTrait,
Backend: BackendFor<D>,
{
backend: Backend,
_phantom: PhantomData<D>,
}
impl<D, Backend> NetabaseStore<D, Backend>
where
D: NetabaseDefinitionTrait,
Backend: BackendFor<D>,
{
pub fn from_backend(backend: Backend) -> Self {
Self {
backend,
_phantom: PhantomData,
}
}
}
impl<D, Backend> NetabaseStore<D, Backend>
where
D: NetabaseDefinitionTrait,
Backend: BackendConstructor<D>,
{
pub fn new<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
Ok(Self::from_backend(Backend::new_backend(path)?))
}
}
impl<D, Backend> NetabaseStore<D, Backend>
where
D: NetabaseDefinitionTrait,
Backend: BackendFor<D>,
{
pub fn backend(&self) -> &Backend {
&self.backend
}
pub fn backend_mut(&mut self) -> &mut Backend {
&mut self.backend
}
pub fn into_backend(self) -> Backend {
self.backend
}
}
impl<D, M, Backend> OpenTree<D, M> for NetabaseStore<D, Backend>
where
D: NetabaseDefinitionTrait,
M: NetabaseModelTrait<D>,
<D as strum::IntoDiscriminant>::Discriminant: crate::traits::definition::NetabaseDiscriminant,
Backend: BackendFor<D> + OpenTree<D, M>,
{
type Tree<'a>
= Backend::Tree<'a>
where
Self: 'a;
fn open_tree(&self) -> Self::Tree<'_> {
self.backend.open_tree()
}
}
impl<D, Backend> NetabaseStore<D, Backend>
where
D: NetabaseDefinitionTrait,
Backend: BackendFor<D>,
{
#[inline]
pub fn open_tree<M>(&self) -> Backend::Tree<'_>
where
M: crate::traits::model::NetabaseModelTrait<D>,
Backend: crate::traits::store_ops::OpenTree<D, M>,
{
use crate::traits::store_ops::OpenTree;
OpenTree::open_tree(self)
}
}
#[cfg(feature = "sled")]
impl<D> NetabaseStore<D, crate::databases::sled_store::SledStore<D>>
where
D: NetabaseDefinitionTrait + crate::traits::convert::ToIVec,
<D as strum::IntoDiscriminant>::Discriminant: crate::traits::definition::NetabaseDiscriminant,
{
pub fn sled<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
Ok(Self::from_backend(
crate::databases::sled_store::SledStore::new(path)?,
))
}
pub fn temp() -> Result<Self, NetabaseError> {
Ok(Self::from_backend(
crate::databases::sled_store::SledStore::temp()?,
))
}
}
#[cfg(feature = "redb")]
impl<D> NetabaseStore<D, crate::databases::redb_store::RedbStore<D>>
where
D: NetabaseDefinitionTrait + crate::traits::convert::ToIVec,
<D as strum::IntoDiscriminant>::Discriminant: crate::traits::definition::NetabaseDiscriminant,
{
pub fn redb<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
Ok(Self::from_backend(
crate::databases::redb_store::RedbStore::new(path)?,
))
}
pub fn open_redb<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
Ok(Self::from_backend(
crate::databases::redb_store::RedbStore::open(path)?,
))
}
}
#[cfg(feature = "sled")]
impl<D> NetabaseStore<D, crate::databases::sled_store::SledStore<D>>
where
D: NetabaseDefinitionTrait + crate::traits::convert::ToIVec,
<D as strum::IntoDiscriminant>::Discriminant: crate::traits::definition::NetabaseDiscriminant,
{
pub fn db(&self) -> &sled::Db {
self.backend.db()
}
pub fn flush(&self) -> Result<usize, NetabaseError> {
Ok(self.backend.db().flush()?)
}
pub fn size_on_disk(&self) -> Result<u64, NetabaseError> {
Ok(self.backend.db().size_on_disk()?)
}
pub fn was_recovered(&self) -> bool {
self.backend.db().was_recovered()
}
pub fn generate_id(&self) -> Result<u64, NetabaseError> {
Ok(self.backend.db().generate_id()?)
}
pub fn read(&self) -> crate::transaction::TxnGuard<'_, D, crate::transaction::ReadOnly> {
crate::transaction::TxnGuard::read_sled(self.backend.db())
}
pub fn write(&self) -> crate::transaction::TxnGuard<'_, D, crate::transaction::ReadWrite> {
crate::transaction::TxnGuard::write_sled(self.backend.db())
}
pub fn transaction<M, F, R>(&self, f: F) -> Result<R, NetabaseError>
where
M: NetabaseModelTrait<D> + TryFrom<D> + Into<D>,
D: TryFrom<M>,
F: Fn(
&crate::databases::sled_store::SledTransactionalTree<D, M>,
) -> Result<R, Box<dyn std::error::Error>>,
{
self.backend.transaction(f)
}
}
#[cfg(feature = "redb")]
impl<D> NetabaseStore<D, crate::databases::redb_store::RedbStore<D>>
where
D: NetabaseDefinitionTrait + crate::traits::convert::ToIVec,
<D as strum::IntoDiscriminant>::Discriminant: crate::traits::definition::NetabaseDiscriminant,
{
pub fn check_integrity(&mut self) -> Result<bool, NetabaseError> {
self.backend.check_integrity()
}
pub fn compact(&mut self) -> Result<bool, NetabaseError> {
self.backend.compact()
}
pub fn db(&self) -> &redb::Database {
self.backend.db()
}
pub fn tree_names(&self) -> Vec<D::Discriminant> {
self.backend.tree_names()
}
}
#[cfg(all(feature = "redb", feature = "redb-zerocopy"))]
impl<D> BackendFor<D> for crate::databases::redb_zerocopy::RedbStoreZeroCopy<D> where
D: NetabaseDefinitionTrait
{
}
#[cfg(all(feature = "redb", feature = "redb-zerocopy"))]
impl<D> BackendConstructor<D> for crate::databases::redb_zerocopy::RedbStoreZeroCopy<D>
where
D: NetabaseDefinitionTrait,
{
fn new_backend<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
crate::databases::redb_zerocopy::RedbStoreZeroCopy::new(path)
}
}
#[cfg(all(feature = "redb", feature = "redb-zerocopy"))]
impl<D> NetabaseStore<D, crate::databases::redb_zerocopy::RedbStoreZeroCopy<D>>
where
D: NetabaseDefinitionTrait,
{
pub fn redb_zerocopy<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
Ok(Self::from_backend(
crate::databases::redb_zerocopy::RedbStoreZeroCopy::new(path)?,
))
}
pub fn open_redb_zerocopy<P: AsRef<Path>>(path: P) -> Result<Self, NetabaseError> {
Ok(Self::from_backend(
crate::databases::redb_zerocopy::RedbStoreZeroCopy::open(path)?,
))
}
pub fn begin_write(
&self,
) -> Result<crate::databases::redb_zerocopy::RedbWriteTransactionZC<'_, D>, NetabaseError> {
self.backend.begin_write()
}
pub fn begin_read(
&self,
) -> Result<crate::databases::redb_zerocopy::RedbReadTransactionZC<'_, D>, NetabaseError> {
self.backend.begin_read()
}
pub fn quick_put<M>(&self, model: M) -> Result<(), NetabaseError>
where
M: NetabaseModelTrait<D>,
M::Keys: crate::traits::model::NetabaseModelTraitKey<D>,
{
self.backend.quick_put(model)
}
pub fn quick_get<M>(
&self,
key: &<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
) -> Result<Option<M>, NetabaseError>
where
M: NetabaseModelTrait<D>,
M::Keys: crate::traits::model::NetabaseModelTraitKey<D>,
{
self.backend.quick_get(key)
}
pub fn quick_remove<M>(
&self,
key: &<M::Keys as crate::traits::model::NetabaseModelTraitKey<D>>::PrimaryKey,
) -> Result<Option<M>, NetabaseError>
where
M: NetabaseModelTrait<D>,
M::Keys: crate::traits::model::NetabaseModelTraitKey<D>,
{
self.backend.quick_remove(key)
}
}