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
}
}