easy-sqlite 0.4.1

Little sqlite framework
Documentation
#[cfg(feature = "async")]
use std::future::Future;
#[cfg(feature = "async")]
use std::pin::Pin;

use rusqlite::{Connection, Row, ToSql};

use crate::entities::errors::DbResult;

#[cfg(feature = "async")]
pub(crate) type DynFut<T> = Pin<Box<dyn Future<Output = T> + Send + 'static>>;
#[cfg(feature = "async")]
pub(crate) type DynFutDbRes<T> = Pin<Box<dyn Future<Output = DbResult<T>> + Send + 'static>>;

pub trait IConnection {
    type Locked: IConnection;

    fn lock_sync(&self) -> DbResult<Self::Locked>;
    fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T>;
}

#[cfg(feature = "async")]
pub trait IAsyncConnection {
    type Locked: IConnection;

    fn lock_sync(&self) -> DynFut<Self::Locked>;
    fn with<
        T: Send + Sync + 'static,
        F: FnOnce(&Connection) -> DbResult<T> + Send + Sync + 'static,
    >(
        &self,
        fun: F,
    ) -> DynFutDbRes<T>;
}

pub trait INewDbRepo<Connection> {
    fn create(connect: Connection) -> Self;
}

pub trait IDbRepo {
    fn as_super(&self) -> &dyn IDbRepo {
        unimplemented!()
    }
    fn init(&self) -> DbResult<()> {
        self.as_super().init()
    }
    fn recreate_tables(&self) -> DbResult<()> {
        // self.as_super().recreate_table()
        self.drop()?;
        self.init()
    }
    fn drop(&self) -> DbResult<()> {
        self.as_super().drop()
    }
    fn set_indexes(&self) -> DbResult<()> {
        self.as_super().set_indexes()
    }
    fn drop_indexes(&self) -> DbResult<()> {
        self.as_super().drop_indexes()
    }
    fn get_size(&self) -> DbResult<usize> {
        self.as_super().get_size()
    }
}
/*
#[cfg(feature = "async")]
pub trait IAsyncDbRepo {
    fn as_super(&self) -> &dyn IAsyncDbRepo {
        unimplemented!()
    }
    fn init(&self) -> DynFutDbRes<()> {
        self.as_super().init()
    }
    fn recreate_tables(&self) -> DynFutDbRes<()> {
        async fn seq(drop: DynFutDbRes<()>, init: DynFutDbRes<()>) -> DbResult<()> {
            drop.await?;
            init.await
        }

        Box::pin(seq(self.drop(), self.init()))
    }
    fn drop(&self) -> DynFutDbRes<()> {
        self.as_super().drop()
    }
    fn set_indexes(&self) -> DynFutDbRes<()> {
        self.as_super().set_indexes()
    }
    fn drop_indexes(&self) -> DynFutDbRes<()> {
        self.as_super().drop_indexes()
    }
    fn get_size(&self) -> DynFutDbRes<usize> {
        self.as_super().get_size()
    }
}
*/

pub trait IExecutor {
    type Locked: IExecutor;

    fn lock(&self) -> DbResult<Self::Locked>;
    fn get_one<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DbResult<T>;
    fn get_many<T, F: FnMut(&rusqlite::Row<'_>) -> DbResult<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DbResult<Vec<T>>;
    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()>;
    fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64>;
}

#[cfg(feature = "async")]
pub trait IAsyncExecutor {
    type Locked: IExecutor;

    fn lock(&self) -> DynFut<Self::Locked>;
    fn get_one<
        T: Send + Sync + 'static,
        F: FnMut(&rusqlite::Row<'_>) -> DbResult<T> + Send + Sync + 'static,
    >(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DynFutDbRes<T>;
    fn get_many<
        T: Send + Sync + 'static,
        F: FnMut(&rusqlite::Row<'_>) -> DbResult<T> + Send + Sync + 'static,
    >(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DynFutDbRes<Vec<T>>;
    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DynFutDbRes<()>;
}

// ---------------------------
// ------ IMPLS --------------
// ---------------------------

impl IConnection for Connection {
    type Locked = Self;

    fn lock_sync(&self) -> DbResult<Self::Locked> {
        panic!("Can not lock bare connection")
    }

    fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
        fun(self)
    }
}

#[cfg(feature = "async")]
impl IAsyncConnection for Connection {
    type Locked = Self;

    fn lock_sync(&self) -> DynFut<Self::Locked> {
        panic!("Can not lock bare connection")
    }

    fn with<
        T: Send + Sync + 'static,
        F: FnOnce(&Connection) -> DbResult<T> + Send + Sync + 'static,
    >(
        &self,
        fun: F,
    ) -> DynFutDbRes<T> {
        let res = fun(self);
        Box::pin(async move { res })
    }
}

impl<Cnn: IConnection> IConnection for &Cnn {
    type Locked = Cnn::Locked;

    fn lock_sync(&self) -> DbResult<Self::Locked> {
        (**self).lock_sync()
    }

    fn with<T, F: FnOnce(&Connection) -> DbResult<T>>(&self, fun: F) -> DbResult<T> {
        (**self).with(fun)
    }
}

#[cfg(feature = "async")]
impl<Cnn: IAsyncConnection> IAsyncConnection for &Cnn {
    type Locked = Cnn::Locked;

    fn lock_sync(&self) -> DynFut<Self::Locked> {
        (**self).lock_sync()
    }

    fn with<
        T: Send + Sync + 'static,
        F: FnOnce(&Connection) -> DbResult<T> + Send + Sync + 'static,
    >(
        &self,
        fun: F,
    ) -> DynFutDbRes<T> {
        (**self).with(fun)
    }
}

impl<Ex: IExecutor> IExecutor for &Ex {
    type Locked = Ex::Locked;

    fn lock(&self) -> DbResult<Self::Locked> {
        (**self).lock()
    }

    fn get_one<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DbResult<T> {
        (**self).get_one(query, params, serializer)
    }

    fn get_many<T, F: FnMut(&Row<'_>) -> DbResult<T>>(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DbResult<Vec<T>> {
        (**self).get_many(query, params, serializer)
    }

    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<()> {
        (**self).execute(query, params)
    }

    fn execute_return_id(&self, query: &str, params: &[&dyn ToSql]) -> DbResult<i64> {
        (**self).execute_return_id(query, params)
    }
}

#[cfg(feature = "async")]
impl<Ex: IAsyncExecutor> IAsyncExecutor for &Ex {
    type Locked = Ex::Locked;

    fn lock(&self) -> DynFut<Self::Locked> {
        (**self).lock()
    }

    fn get_one<
        T: Send + Sync + 'static,
        F: FnMut(&Row<'_>) -> DbResult<T> + Send + Sync + 'static,
    >(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DynFutDbRes<T> {
        (**self).get_one(query, params, serializer)
    }

    fn get_many<
        T: Send + Sync + 'static,
        F: FnMut(&Row<'_>) -> DbResult<T> + Send + Sync + 'static,
    >(
        &self,
        query: &str,
        params: &[&dyn ToSql],
        serializer: F,
    ) -> DynFutDbRes<Vec<T>> {
        (**self).get_many(query, params, serializer)
    }

    fn execute(&self, query: &str, params: &[&dyn ToSql]) -> DynFutDbRes<()> {
        (**self).execute(query, params)
    }
}