handle 0.2.1

A Handle Trait for asynchronous context pipeline.
Documentation

Example

use async_trait::Handle;
use futures::executor::block_on;
use std::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<Arc<dyn for<'a> Handle<'a, Context, Result>>>,
}

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

block_on(async move {
    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.next().await;
        cx.index += 1;
        println!("exec Fn a --{}<< {:>2}", repeat, cx.index);
        fut
    }

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

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

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

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

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

    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.next().await;
            cx.index -= self.index;
            println!("exec St A --{}<< {:>2}", repeat, cx.index);
            fut
        }
    }

    struct B {
        index: usize,
    }

    #[async_trait]
    impl<'a> Handle<'a, Context, Result> for B {
        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 B --{}>> {:>2}", repeat, cx.index);
            cx.index += self.index;
            let fut = cx.next().await;
            cx.index -= self.index;
            println!("exec St B --{}<< {:>2}", repeat, cx.index);
            fut
        }
    }

    let mut cx = Context {
        index: 0,
        middleware: Vec::new(),
    };

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

    // let _ = a(cx.as_mut()).await;
    // let _ = b(cx.as_mut()).await;
    // let _ = c(cx.as_mut()).await;
    // let _ = d(cx.as_mut()).await;
    // let _ = e(cx.as_mut()).await;
    // let _ = f(cx.as_mut()).await;
    // // let _ = g(cx.as_mut()).await;
    // let _ = (B {}).call(cx.as_mut()).await;
    // let _ = (A {}).call(cx.as_mut()).await;

    let mut v: Vec<Arc<dyn for<'a> Handle<'a, Context, Result>>> = vec![];
    v.push(Arc::new(a));
    v.push(Arc::new(b));
    v.push(Arc::new(c));
    v.push(Arc::new(d));
    v.push(Arc::new(e));
    v.push(Arc::new(f));
    // v.puArcBox::new(g));
    v.push(Arc::new(B { index: 1 }));
    v.push(Arc::new(A { index: 2 }));

    cx.as_mut().middleware = v.clone();
    println!("mw 0: {}", v.len());

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

    println!("mw 1: {}", v.len());

    cx.as_mut().middleware = v.clone();

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

    println!("mw 2: {}", v.len());

    cx.as_mut().middleware = v.clone();

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

License