Skip to content

Instantly share code, notes, and snippets.

@DrBluefall
Created September 5, 2020 16:25
Show Gist options
  • Save DrBluefall/d7f20b6394a5c1db25e42f27939b0f04 to your computer and use it in GitHub Desktop.
Save DrBluefall/d7f20b6394a5c1db25e42f27939b0f04 to your computer and use it in GitHub Desktop.
//! Database-specific traits.
//!
//! The main traits for implementing a database within Telephone. Backends for the bot should implement [`Database`], along with all the relevant
//! database operation traits in this module for the types they wish to use with the backend.
use serenity::futures::future::BoxFuture as BoxedFuture;
use serenity::futures::FutureExt;
use sqlx::Acquire;
#[cfg(any(
feature = "with-postgres",
feature = "with-mysql",
feature = "with-sqlite"
))]
impl<'c, A: 'c> Database<'c> for A
where
A: Acquire<'c> + Send,
for<'e> &'e mut <A::Database as sqlx::Database>::Connection: sqlx::Executor<'e>,
{
type Error = sqlx::Error;
type Backend = &'c mut sqlx::Transaction<'c, <A as Acquire<'c>>::Database>;
fn create<T: Create<'c, Self>>(self, key: T::Key) -> BoxedFuture<'c, Result<(), Self::Error>> {
async move {
let tx = self.begin().await?;
match T::create(key, &mut tx).await {
Ok(v) => {
tx.commit().await;
Ok(())
}
Err(e) => {
tx.rollback().await;
Err(e)
}
}
}.boxed()
/*
error[E0308]: mismatched types
--> src/util/database.rs:36:11
|
36 | }.boxed()
| ^^^^^ one type is more general than the other
|
= note: expected type `sqlx::Acquire<'_>`
found type `sqlx::Acquire<'c>`
*/
}
fn read<T: Read<'c, Self>>(self, key: T::Key) -> BoxedFuture<'c, Result<Option<T>, Self::Error>> {
todo!()
}
fn update<T: Update<'c, Self>>(self, target: T) -> BoxedFuture<'c, Result<(), Self::Error>> {
todo!()
}
fn delete<T: Delete<'c, Self>>(self, target: T) -> BoxedFuture<'c, Result<(), Self::Error>> {
todo!()
}
}
/// The main trait for backends.
///
/// This is the main trait for backends to implement in order to be used with the bot, and allows for a generic interface between the discord frontend and
/// database backend.
pub trait Database<'c>: Send + Sized {
type Error: std::error::Error;
type Backend;
fn create<T: Create<'c, Self>>(self, key: T::Key) -> BoxedFuture<'c, Result<(), Self::Error>>;
fn read<T: Read<'c, Self>>(self, key: T::Key) -> BoxedFuture<'c, Result<Option<T>, Self::Error>>;
fn update<T: Update<'c, Self>>(self, target: T) -> BoxedFuture<'c, Result<(), Self::Error>>;
fn delete<T: Delete<'c, Self>>(self, target: T) -> BoxedFuture<'c, Result<(), Self::Error>>;
}
/// Trait for creating a database object.
pub trait Create<'c, T: Database<'c>>: Sized {
type Key: Send + Sync;
fn create(key: Self::Key, db: T::Backend) -> BoxedFuture<'c, Result<(), T::Error>>;
}
/// Trait for reading an object from the database.
pub trait Read<'c, T: Database<'c>>: Sized {
type Key: Send + Sync;
fn read(key: Self::Key, db: T::Backend) -> BoxedFuture<'c, Result<Option<Self>, T::Error>>;
}
/// Trait for updating a database object.
pub trait Update<'c, T: Database<'c>>: Sized + Send {
fn update(self, db: T::Backend) -> BoxedFuture<'c, Result<(), T::Error>>;
}
/// Trait for deleting a database object.
pub trait Delete<'c, T: Database<'c>>: Sized + Send {
fn delete(self, db: T::Backend) -> BoxedFuture<'c, Result<(), T::Error>>;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment