pub struct Handler<'a, 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 -> cAnd branching looks like this:
a -> b
-> cThis 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, Output, Descr> Handler<'a, Output, Descr>where
Output: 'a,
Descr: HandlerDescription,
impl<'a, Output, Descr> Handler<'a, Output, Descr>where
Output: 'a,
Descr: HandlerDescription,
Sourcepub fn chain(self, next: Self) -> Self
pub fn chain(self, next: Self) -> Self
Chain two handlers to form a chain of responsibility.
Chaining is different from branching. See “The difference between chaining and branching”.
This method makes use of HandlerSignature (stored in every handler)
to perform run-time type inference of the resulting handler
signature; this information is used by crate::type_check to make
sure that all required types are provided before execution.
§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: Self) -> Selfwhere
Output: Send,
pub fn branch(self, next: Self) -> Selfwhere
Output: Send,
Chain two handlers to make a tree of responsibility.
Chaining is different from branching. See “The difference between chaining and branching”.
This method makes use of HandlerSignature (stored in every handler)
to perform run-time type inference of the resulting handler
signature; this information is used by crate::type_check to make
sure that all required types are provided before execution.
§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,
input: DependencyMap,
cont: Cont,
) -> ControlFlow<Output, DependencyMap>where
Cont: FnOnce(DependencyMap) -> ContFut + Send + Sync + 'a,
ContFut: Future<Output = ControlFlow<Output, DependencyMap>> + Send + 'a,
pub async fn execute<Cont, ContFut>(
self,
input: DependencyMap,
cont: Cont,
) -> ControlFlow<Output, DependencyMap>where
Cont: FnOnce(DependencyMap) -> ContFut + Send + Sync + 'a,
ContFut: Future<Output = ControlFlow<Output, DependencyMap>> + 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.
NOTE: If you are using DependencyMap, you should first call
crate::type_check to type-check your handler against a container;
otherwise, type checking will be delayed until the actual execution,
which can make things harder to debug.
§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,
input: DependencyMap,
) -> ControlFlow<Output, DependencyMap>
pub async fn dispatch( &self, input: DependencyMap, ) -> ControlFlow<Output, DependencyMap>
Executes this handler.
Returns ControlFlow::Break when executed successfully,
ControlFlow::Continue otherwise.
NOTE: If you are using DependencyMap, you should first call
crate::type_check to type-check your handler against a container;
otherwise, type checking will be delayed until the actual execution,
which can make things harder to debug.
Sourcepub fn description(&self) -> &Descr
pub fn description(&self) -> &Descr
Returns the set of updates that can be processed by this handler.
Sourcepub fn sig(&self) -> &HandlerSignature
pub fn sig(&self) -> &HandlerSignature
Returns this handler’s run-time type signature.
Source§impl<'a, Output, Descr> Handler<'a, Output, Descr>where
Output: 'a,
Descr: HandlerDescription,
impl<'a, Output, Descr> Handler<'a, Output, Descr>where
Output: 'a,
Descr: HandlerDescription,
Sourcepub fn filter<Pred, FnArgs>(self, pred: Pred) -> Handler<'a, Output, Descr>
pub fn filter<Pred, FnArgs>(self, pred: Pred) -> Handler<'a, Output, Descr>
Chain this handler with the filter predicate pred.
Sourcepub fn filter_async<Pred, FnArgs>(
self,
pred: Pred,
) -> Handler<'a, Output, Descr>
pub fn filter_async<Pred, FnArgs>( self, pred: Pred, ) -> Handler<'a, Output, Descr>
Chain this handler with the async filter predicate pred.
Sourcepub fn filter_map<Proj, NewType, Args>(
self,
proj: Proj,
) -> Handler<'a, Output, Descr>
pub fn filter_map<Proj, NewType, Args>( self, proj: Proj, ) -> Handler<'a, Output, Descr>
Chain this handler with the filter projection proj.
Sourcepub fn filter_map_async<Proj, NewType, Args>(
self,
proj: Proj,
) -> Handler<'a, Output, Descr>
pub fn filter_map_async<Proj, NewType, Args>( self, proj: Proj, ) -> Handler<'a, Output, Descr>
Chain this handler with the async filter projection proj.
Sourcepub fn map<Proj, NewType, Args>(self, proj: Proj) -> Handler<'a, Output, Descr>
pub fn map<Proj, NewType, Args>(self, proj: Proj) -> Handler<'a, Output, Descr>
Chain this handler with the map projection proj.
Sourcepub fn map_async<Proj, NewType, Args>(
self,
proj: Proj,
) -> Handler<'a, Output, Descr>
pub fn map_async<Proj, NewType, Args>( self, proj: Proj, ) -> Handler<'a, Output, Descr>
Chain this handler with the async map projection proj.
Sourcepub fn inspect<F, Args>(self, f: F) -> Handler<'a, Output, Descr>
pub fn inspect<F, Args>(self, f: F) -> Handler<'a, Output, Descr>
Chain this handler with the inspection function f.
Sourcepub fn inspect_async<F, Args>(self, f: F) -> Handler<'a, Output, Descr>
pub fn inspect_async<F, Args>(self, f: F) -> Handler<'a, Output, Descr>
Chain this handler with the async inspection function f.