Struct Handler

Source
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 -> 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, Output, Descr> Handler<'a, Output, Descr>
where Output: 'a, Descr: HandlerDescription,

Source

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])
);
Source

pub fn branch(self, next: Self) -> Self
where 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])
);
Source

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"));
Source

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.

Source

pub fn description(&self) -> &Descr

Returns the set of updates that can be processed by this handler.

Source

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,

Source

pub fn filter<Pred, FnArgs>(self, pred: Pred) -> Handler<'a, Output, Descr>
where Asyncify<Pred>: Injectable<bool, FnArgs> + Send + Sync + 'a,

Chain this handler with the filter predicate pred.

Source

pub fn filter_async<Pred, FnArgs>( self, pred: Pred, ) -> Handler<'a, Output, Descr>
where Pred: Injectable<bool, FnArgs> + Send + Sync + 'a,

Chain this handler with the async filter predicate pred.

Source

pub fn filter_map<Proj, NewType, Args>( self, proj: Proj, ) -> Handler<'a, Output, Descr>
where Asyncify<Proj>: Injectable<Option<NewType>, Args> + Send + Sync + 'a, NewType: Send + Sync + 'static,

Chain this handler with the filter projection proj.

Source

pub fn filter_map_async<Proj, NewType, Args>( self, proj: Proj, ) -> Handler<'a, Output, Descr>
where Proj: Injectable<Option<NewType>, Args> + Send + Sync + 'a, NewType: Send + Sync + 'static,

Chain this handler with the async filter projection proj.

Source

pub fn map<Proj, NewType, Args>(self, proj: Proj) -> Handler<'a, Output, Descr>
where Asyncify<Proj>: Injectable<NewType, Args> + Send + Sync + 'a, NewType: Send + Sync + 'static,

Chain this handler with the map projection proj.

Source

pub fn map_async<Proj, NewType, Args>( self, proj: Proj, ) -> Handler<'a, Output, Descr>
where Proj: Injectable<NewType, Args> + Send + Sync + 'a, NewType: Send + Sync + 'static,

Chain this handler with the async map projection proj.

Source

pub fn inspect<F, Args>(self, f: F) -> Handler<'a, Output, Descr>
where Asyncify<F>: Injectable<(), Args> + Send + Sync + 'a,

Chain this handler with the inspection function f.

Source

pub fn inspect_async<F, Args>(self, f: F) -> Handler<'a, Output, Descr>
where F: Injectable<(), Args> + Send + Sync + 'a,

Chain this handler with the async inspection function f.

Source

pub fn endpoint<F, FnArgs>(self, f: F) -> Handler<'a, Output, Descr>
where F: Injectable<Output, FnArgs> + Send + Sync + 'a, Output: 'static,

Chain this handler with the endpoint handler f.

Trait Implementations§

Source§

impl<Output, Descr> Clone for Handler<'_, Output, Descr>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more

Auto Trait Implementations§

§

impl<'a, Output, Descr> Freeze for Handler<'a, Output, Descr>

§

impl<'a, Output, Descr = Unspecified> !RefUnwindSafe for Handler<'a, Output, Descr>

§

impl<'a, Output, Descr> Send for Handler<'a, Output, Descr>
where Descr: Sync + Send,

§

impl<'a, Output, Descr> Sync for Handler<'a, Output, Descr>
where Descr: Sync + Send,

§

impl<'a, Output, Descr> Unpin for Handler<'a, Output, Descr>

§

impl<'a, Output, Descr = Unspecified> !UnwindSafe for Handler<'a, Output, Descr>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.