[][src]Crate handle

A Handle Trait for asynchronous context pipeline.

Maintain context in multiple handles.

Pin<&mut 🦀> Don't let him/she get away. 'Stay at home' 2020.

Examples

use handle::Handle;
use async_trait::async_trait;
use futures::executor::block_on;
use std::{future::Future, pin::Pin, sync::Arc};

type Result = anyhow::Result<()>;
type BoxFuture<'a, T = Result> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

struct Context {
    index: usize,
    middleware: Vec<Box<dyn for<'a> Handle<'a, Context, Result>>>,
}

impl Context {
    async fn next(mut self: Pin<&mut Context>) -> Result {
        if let Some(m) = self.middleware.pop() {
            m.call(self).await
        } else {
            Ok(())
        }
    }
}

async fn a(mut cx: Pin<&mut Context>) -> Result {
    let size = cx.middleware.len();
    let repeat = "-".repeat(2 * size);
    println!("exec Fn a --{}>> {:>2}", repeat, cx.index);
    cx.index += 1;
    let fut = cx.as_mut().next().await;
    cx.index += 1;
    println!("exec Fn a --{}<< {:>2}", repeat, cx.index);
    fut
}

#[derive(Clone)]
struct A {
    index: usize,
}

#[async_trait]
impl<'a> Handle<'a, Context, Result> for A {
    async fn call(&'a self, mut cx: Pin<&'a mut Context>) -> Result {
        let size = cx.middleware.len();
        let repeat = "-".repeat(2 * size);
        println!("exec St A --{}>> {:>2}", repeat, cx.index);
        cx.index += self.index;
        let fut = cx.as_mut().next().await;
        cx.index -= self.index;
        println!("exec St A --{}<< {:>2}", repeat, cx.index);
        fut
    }
}

#[async_std::main]
async fn main() -> Result {
    let mut cx = Context {
        index: 0,
        middleware: vec![Box::new(a), Box::new(A { index: 2 })],
    };

    let mut cx: Pin<&mut Context> = Pin::new(&mut cx);

    let result = cx.as_mut().next().await;
    assert!(result.is_ok());
    assert_eq!(result.unwrap(), ());

    Ok(())
}

Traits

Handle