1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
use crate::{Prepare, PrepareError, ServerPrepare};
use futures::future::Ready;
use std::any::type_name;
use std::convert::Infallible;
use std::future::Future;
impl<C, Effect, Log, State, Graceful, Decorator>
    ServerPrepare<C, Effect, Log, State, Graceful, Decorator>
{
    /// Add Decorator apply on every prepare [`Future`]
    ///
    /// This [`PrepareDecorator`] result will affect all following prepares
    ///
    /// this will overwrite old [`PrepareDecorator`], combine multiply [`PrepareDecorator`] is **Not**
    ///support. Manual writing combining code instead
    ///
    /// see also [`prepare_decorator`](Self::prepare_decorator)
    pub fn set_decorator<D>(self, decorator: D) -> ServerPrepare<C, Effect, Log, State, Graceful, D>
    where
        D: PrepareDecorator,
    {
        ServerPrepare::new(
            self.prepares.change_decorator(decorator),
            self.graceful,
            self.span,
        )
    }
    /// Add Decorator generated by a [`Prepare`] task,
    ///
    ///
    /// ## NOTE
    /// the [`Prepare`] task must be a sync task, in another word, the [`Prepare::Future`] should to
    /// be [`Ready`]
    ///
    /// This [`PrepareDecorator`] result will affect all following prepares
    ///
    /// If you using [`prepare`](axum_starter_macro::prepare),
    /// you can mark the [`Prepare`] task as `sync`.
    ///
    /// ```rust
    /// use axum_starter::prepare;
    ///
    /// // using `sync` make macro generate prepare return Ready
    /// #[prepare(sync Decorator)]
    /// fn foo_decorator(foo:i32)->FooDecorator{
    ///     FooDecorator(foo)
    /// }
    ///
    /// struct FooDecorator(i32);
    /// ```
    ///
    /// If your [`Decorator`] do not need any information from the `C`,
    /// you'd better using [`set_decorator`](Self::set_decorator)
    ///
    ///
    pub fn prepare_decorator<D, P>(
        self,
        prepare: P,
    ) -> ServerPrepare<C, Effect, Log, State, Graceful, D>
    where
        P: Prepare<C, Effect = D, Error = Infallible, Future = Ready<Result<D, Infallible>>>,
        C: 'static,
        D: PrepareDecorator,
    {
        let decorator = prepare
            .prepare(self.prepares.get_configure())
            .into_inner()
            .unwrap();
        self.set_decorator(decorator)
    }
}
/// add decorator for each prepare 's [`Future`]
///
///It is useful for adding extra functional on original prepare task
pub trait PrepareDecorator: 'static {
    type OutFut<Fut, T>: Future<Output = Result<T, PrepareError>> + 'static
    where
        Fut: Future<Output = Result<T, PrepareError>> + 'static,
        T: 'static;
    fn decorator<Fut, T>(&self, src: &'static str, in_fut: Fut) -> Self::OutFut<Fut, T>
    where
        Fut: Future<Output = Result<T, PrepareError>> + 'static,
        T: 'static;
    fn prepare_decorator<C, P, Fut>(&self, in_fut: Fut) -> Self::OutFut<Fut, P::Effect>
    where
        Fut: Future<Output = Result<P::Effect, PrepareError>> + 'static,
        P: Prepare<C>,
        C: 'static,
    {
        PrepareDecorator::decorator(self, type_name::<P>(), in_fut)
    }
}
/// Default Decorator without any effect
pub struct EmptyDecorator;
impl PrepareDecorator for EmptyDecorator {
    type OutFut<Fut, T> = Fut where Fut: Future<Output=Result<T, PrepareError>> + 'static, T: 'static;
    fn decorator<Fut, T>(&self, _src: &'static str, in_fut: Fut) -> Self::OutFut<Fut, T>
    where
        Fut: Future<Output = Result<T, PrepareError>> + 'static,
        T: 'static,
    {
        in_fut
    }
}