pub struct Handler<'a, Input, Output, Descr = Unspecified> { /* private fields */ }
Expand description
An instance that receives an input and decides whether to break a chain or pass the value further.
In order to create this structure, you can use the predefined functions from
crate
.
The difference between chaining and branching
Handlers can be chained via Handler::chain
and branched via
Handler::branch
. To understand the difference between the two, consider
the following examples: a.chain(b).c
and a.branch(b).c
.
In a.chain(b).c
, the handler a
is given the rest of the handler chain,
b
and c
; if a
decides to pass the value further, it invokes b
. Then,
if b
decides to pass the value further, it invokes c
. Thus, the handler
chain is linear.
In a.branch(b).c
, if a
decides to pass the value further, it invokes
b
. But since b
is “branched”, it receives an empty chain, so it cannot
invoke c
. Instead, if b
decides to continue execution
(ControlFlow::Continue
), a
invokes c
; otherwise
(ControlFlow::Break
), the process is terminated. The handler chain is
nested.
To sum up, chaining looks like this:
a -> b -> c
And branching looks like this:
a -> b
-> c
This is very crucial when b
is a filter: if it is chained, it decides
whether or not to call c
, but when it is branched, whether c
is called
depends solely on a
.
Implementations§
source§impl<'a, Input, Output, Descr> Handler<'a, Input, Output, Descr>where
Input: Send + 'a,
Output: 'a,
Descr: HandlerDescription,
impl<'a, Input, Output, Descr> Handler<'a, Input, Output, Descr>where Input: Send + 'a, Output: 'a, Descr: HandlerDescription,
sourcepub fn chain(
self,
next: Handler<'a, Input, Output, Descr>
) -> Handler<'a, Input, Output, Descr>
pub fn chain( self, next: Handler<'a, Input, Output, Descr> ) -> Handler<'a, Input, Output, Descr>
Chain two handlers to form a chain of responsibility.
Chaining is different from branching. See “The difference between chaining and branching”.
Examples
use dptree::prelude::*;
let handler: Handler<_, _> =
dptree::filter(|x: i32| x > 0).chain(dptree::endpoint(|| async { "done" }));
assert_eq!(handler.dispatch(dptree::deps![10]).await, ControlFlow::Break("done"));
assert_eq!(
handler.dispatch(dptree::deps![-10]).await,
ControlFlow::Continue(dptree::deps![-10])
);
sourcepub fn branch(
self,
next: Handler<'a, Input, Output, Descr>
) -> Handler<'a, Input, Output, Descr>where
Output: Send,
pub fn branch( self, next: Handler<'a, Input, Output, Descr> ) -> Handler<'a, Input, Output, Descr>where Output: Send,
Chain two handlers to make a tree of responsibility.
Chaining is different from branching. See “The difference between chaining and branching”.
Examples
use dptree::prelude::*;
#[derive(Debug, PartialEq)]
enum Output {
Five,
One,
GT,
}
let dispatcher: Handler<_, _> = dptree::entry()
.branch(dptree::filter(|num: i32| num == 5).endpoint(|| async move { Output::Five }))
.branch(dptree::filter(|num: i32| num == 1).endpoint(|| async move { Output::One }))
.branch(dptree::filter(|num: i32| num > 2).endpoint(|| async move { Output::GT }));
assert_eq!(dispatcher.dispatch(dptree::deps![5]).await, ControlFlow::Break(Output::Five));
assert_eq!(dispatcher.dispatch(dptree::deps![1]).await, ControlFlow::Break(Output::One));
assert_eq!(dispatcher.dispatch(dptree::deps![3]).await, ControlFlow::Break(Output::GT));
assert_eq!(
dispatcher.dispatch(dptree::deps![0]).await,
ControlFlow::Continue(dptree::deps![0])
);
sourcepub async fn execute<Cont, ContFut>(
self,
container: Input,
cont: Cont
) -> impl Future<Output = ControlFlow<Output, Input>>where
Cont: FnOnce(Input) -> ContFut + Send + Sync + 'a,
ContFut: Future<Output = ControlFlow<Output, Input>> + Send + 'a,
pub async fn execute<Cont, ContFut>( self, container: Input, cont: Cont ) -> impl Future<Output = ControlFlow<Output, Input>>where Cont: FnOnce(Input) -> ContFut + Send + Sync + 'a, ContFut: Future<Output = ControlFlow<Output, Input>> + Send + 'a,
Executes this handler with a continuation.
Usually, you do not want to call this method by yourself, if you do not
write your own handler implementation. If you wish to execute handler
without a continuation, take a look at the Handler::dispatch
method.
Examples
use dptree::prelude::*;
let handler: Handler<_, _> = dptree::filter(|x: i32| x > 0);
let output = handler.execute(dptree::deps![10], |_| async { ControlFlow::Break("done") }).await;
assert_eq!(output, ControlFlow::Break("done"));
sourcepub async fn dispatch(
&self,
container: Input
) -> impl Future<Output = ControlFlow<Output, Input>>
pub async fn dispatch( &self, container: Input ) -> impl Future<Output = ControlFlow<Output, Input>>
Executes this handler.
Returns ControlFlow::Break
when executed successfully,
ControlFlow::Continue
otherwise.
sourcepub fn description(&self) -> &Descr
pub fn description(&self) -> &Descr
Returns the set of updates that can be processed by this handler.
source§impl<'a, Input, Output, Descr> Handler<'a, Input, Output, Descr>where
Input: Send + 'a,
Output: 'a,
Descr: HandlerDescription,
impl<'a, Input, Output, Descr> Handler<'a, Input, Output, Descr>where Input: Send + 'a, Output: 'a, Descr: HandlerDescription,
sourcepub fn filter<Pred, FnArgs>(
self,
pred: Pred
) -> Handler<'a, Input, Output, Descr>where
Asyncify<Pred>: Injectable<Input, bool, FnArgs> + Send + Sync + 'a,
pub fn filter<Pred, FnArgs>( self, pred: Pred ) -> Handler<'a, Input, Output, Descr>where Asyncify<Pred>: Injectable<Input, bool, FnArgs> + Send + Sync + 'a,
Chain this handler with the filter predicate pred
.
sourcepub fn filter_async<Pred, FnArgs>(
self,
pred: Pred
) -> Handler<'a, Input, Output, Descr>where
Pred: Injectable<Input, bool, FnArgs> + Send + Sync + 'a,
pub fn filter_async<Pred, FnArgs>( self, pred: Pred ) -> Handler<'a, Input, Output, Descr>where Pred: Injectable<Input, bool, FnArgs> + Send + Sync + 'a,
Chain this handler with the async filter predicate pred
.
sourcepub fn filter_map<Proj, NewType, Args>(
self,
proj: Proj
) -> Handler<'a, Input, Output, Descr>where
Input: Insert<NewType> + Clone,
Asyncify<Proj>: Injectable<Input, Option<NewType>, Args> + Send + Sync + 'a,
NewType: Send,
pub fn filter_map<Proj, NewType, Args>( self, proj: Proj ) -> Handler<'a, Input, Output, Descr>where Input: Insert<NewType> + Clone, Asyncify<Proj>: Injectable<Input, Option<NewType>, Args> + Send + Sync + 'a, NewType: Send,
Chain this handler with the filter projection proj
.
sourcepub fn filter_map_async<Proj, NewType, Args>(
self,
proj: Proj
) -> Handler<'a, Input, Output, Descr>where
Input: Insert<NewType> + Clone,
Proj: Injectable<Input, Option<NewType>, Args> + Send + Sync + 'a,
NewType: Send,
pub fn filter_map_async<Proj, NewType, Args>( self, proj: Proj ) -> Handler<'a, Input, Output, Descr>where Input: Insert<NewType> + Clone, Proj: Injectable<Input, Option<NewType>, Args> + Send + Sync + 'a, NewType: Send,
Chain this handler with the async filter projection proj
.
sourcepub fn map<Proj, NewType, Args>(
self,
proj: Proj
) -> Handler<'a, Input, Output, Descr>where
Input: Insert<NewType> + Clone,
Asyncify<Proj>: Injectable<Input, NewType, Args> + Send + Sync + 'a,
NewType: Send,
pub fn map<Proj, NewType, Args>( self, proj: Proj ) -> Handler<'a, Input, Output, Descr>where Input: Insert<NewType> + Clone, Asyncify<Proj>: Injectable<Input, NewType, Args> + Send + Sync + 'a, NewType: Send,
Chain this handler with the map projection proj
.
sourcepub fn map_async<Proj, NewType, Args>(
self,
proj: Proj
) -> Handler<'a, Input, Output, Descr>where
Input: Insert<NewType> + Clone,
Proj: Injectable<Input, NewType, Args> + Send + Sync + 'a,
NewType: Send,
pub fn map_async<Proj, NewType, Args>( self, proj: Proj ) -> Handler<'a, Input, Output, Descr>where Input: Insert<NewType> + Clone, Proj: Injectable<Input, NewType, Args> + Send + Sync + 'a, NewType: Send,
Chain this handler with the async map projection proj
.
sourcepub fn inspect<F, Args>(self, f: F) -> Handler<'a, Input, Output, Descr>where
Asyncify<F>: Injectable<Input, (), Args> + Send + Sync + 'a,
pub fn inspect<F, Args>(self, f: F) -> Handler<'a, Input, Output, Descr>where Asyncify<F>: Injectable<Input, (), Args> + Send + Sync + 'a,
Chain this handler with the inspection function f
.
sourcepub fn inspect_async<F, Args>(self, f: F) -> Handler<'a, Input, Output, Descr>where
F: Injectable<Input, (), Args> + Send + Sync + 'a,
pub fn inspect_async<F, Args>(self, f: F) -> Handler<'a, Input, Output, Descr>where F: Injectable<Input, (), Args> + Send + Sync + 'a,
Chain this handler with the async inspection function f
.
Trait Implementations§
source§impl<Output> HandlerExt<Output> for Handler<'static, DependencyMap, Output, DpHandlerDescription>where
Output: Send + Sync + 'static,
impl<Output> HandlerExt<Output> for Handler<'static, DependencyMap, Output, DpHandlerDescription>where Output: Send + Sync + 'static,
source§fn filter_command<C>(self) -> Selfwhere
C: BotCommands + Send + Sync + 'static,
fn filter_command<C>(self) -> Selfwhere C: BotCommands + Send + Sync + 'static,
C
. Read more