use crate::{Error, Result};
use std::future::Future;
use std::pin::Pin;
pub type HookResult = Result<(), Box<dyn std::error::Error + Send + Sync>>;
pub type BoxFuture<'a> = Pin<Box<dyn Future<Output = HookResult> + Send + 'a>>;
pub trait ModelHooks: Sized {
fn before_save(&mut self) -> BoxFuture<'_> {
Box::pin(async { Ok(()) })
}
fn after_save(&self) -> BoxFuture<'_> {
Box::pin(async { Ok(()) })
}
fn before_create(&mut self) -> BoxFuture<'_> {
Box::pin(async { Ok(()) })
}
fn after_create(&self) -> BoxFuture<'_> {
Box::pin(async { Ok(()) })
}
fn before_update(&mut self) -> BoxFuture<'_> {
Box::pin(async { Ok(()) })
}
fn after_update(&self) -> BoxFuture<'_> {
Box::pin(async { Ok(()) })
}
fn before_delete(&self) -> BoxFuture<'_> {
Box::pin(async { Ok(()) })
}
fn after_delete(&self) -> BoxFuture<'_> {
Box::pin(async { Ok(()) })
}
}
fn run(r: HookResult) -> Result<()> {
r.map_err(Error::Hook)
}
#[doc(hidden)]
pub async fn before_insert<M: ModelHooks>(m: &mut M) -> Result<()> {
run(m.before_save().await)?;
run(m.before_create().await)
}
#[doc(hidden)]
pub async fn after_insert<M: ModelHooks>(m: &M) -> Result<()> {
run(m.after_create().await)?;
run(m.after_save().await)
}
#[doc(hidden)]
pub async fn before_update<M: ModelHooks>(m: &mut M) -> Result<()> {
run(m.before_save().await)?;
run(m.before_update().await)
}
#[doc(hidden)]
pub async fn after_update<M: ModelHooks>(m: &M) -> Result<()> {
run(m.after_update().await)?;
run(m.after_save().await)
}
#[doc(hidden)]
pub async fn before_delete<M: ModelHooks>(m: &M) -> Result<()> {
run(m.before_delete().await)
}
#[doc(hidden)]
pub async fn after_delete<M: ModelHooks>(m: &M) -> Result<()> {
run(m.after_delete().await)
}