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
111
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.state,
            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
    }
}