10 个版本 (3 个稳定)

1.0.2 2021 年 9 月 29 日
1.0.0 2020 年 5 月 22 日
0.2.5 2020 年 4 月 19 日
0.1.0 2020 年 4 月 5 日

#408异步

Download history 686/week @ 2024-03-14 624/week @ 2024-03-21 670/week @ 2024-03-28 478/week @ 2024-04-04 402/week @ 2024-04-11 613/week @ 2024-04-18 523/week @ 2024-04-25 589/week @ 2024-05-02 679/week @ 2024-05-09 494/week @ 2024-05-16 577/week @ 2024-05-23 638/week @ 2024-05-30 488/week @ 2024-06-06 484/week @ 2024-06-13 542/week @ 2024-06-20 410/week @ 2024-06-27

每月 2,052 次下载

MIT/Apache

24KB
298

Handle

异步上下文管道的 Handle 特性。

示例

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

type Result = anyhow::Result<()>;
type Middleware = dyn for<'a> Handle<'a, Context, Result>;

struct Context {
    index: usize,
    middleware: Vec<Arc<Middleware>>,
}

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

async fn a(cx: &mut Context) -> Result {
    let size = cx.middleware.len();
    let repeat = "-".repeat(2 * size);

    println!("exec Fn a --{}>> {:>2}", repeat, cx.index);

    assert_eq!(cx.index, 0);
    cx.index += 1;
    assert_eq!(cx.index, 1);

    let fut = cx.next().await;

    assert_eq!(cx.index, 1);
    cx.index -= 1;
    assert_eq!(cx.index, 0);

    println!("exec Fn a --{}<< {:>2}", repeat, cx.index);

    fut
}

fn b<'a>(cx: &'a mut Context) -> BoxFuture<'a, Result> {
    let size = cx.middleware.len();
    let repeat = "-".repeat(2 * size);

    println!("exec Fn b --{}>> {:>2}", repeat, cx.index);

    assert_eq!(cx.index, 1);
    cx.index += 1;
    assert_eq!(cx.index, 2);

    Box::pin(async move {
        let fut = cx.next().await;

        assert_eq!(cx.index, 2);
        cx.index -= 1;
        assert_eq!(cx.index, 1);

        println!("exec Fn b --{}<< {:>2}", repeat, cx.index);

        fut
    })
}

fn c(cx: &mut Context) -> BoxFuture<'_, Result> {
    let size = cx.middleware.len();
    let repeat = "-".repeat(2 * size);

    println!("exec Fn c --{}>> {:>2}", repeat, cx.index);

    assert_eq!(cx.index, 2);
    cx.index += 1;
    assert_eq!(cx.index, 3);

    Box::pin(async move {
        let fut = cx.next().await;

        assert_eq!(cx.index, 3);
        cx.index -= 1;
        assert_eq!(cx.index, 2);

        println!("exec Fn c --{}<< {:>2}", repeat, cx.index);

        fut
    })
}

fn d<'a>(cx: &'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);

    assert_eq!(cx.index, 3);
    cx.index += 1;
    assert_eq!(cx.index, 4);

    async move {
        let fut = cx.next().await;

        assert_eq!(cx.index, 4);
        cx.index -= 1;
        assert_eq!(cx.index, 3);

        println!("exec Fn d --{}<< {:>2}", repeat, cx.index);

        fut
    }
}

fn e(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);

    assert_eq!(cx.index, 4);
    cx.index += 1;
    assert_eq!(cx.index, 5);

    async move {
        let fut = cx.next().await;

        assert_eq!(cx.index, 5);
        cx.index -= 1;
        assert_eq!(cx.index, 4);

        println!("exec Fn e --{}<< {:>2}", repeat, cx.index);

        fut
    }
}

async fn f(cx: &mut Context) -> Result {
    let size = cx.middleware.len();
    let repeat = "-".repeat(2 * size);

    println!("exec Fn f --{}>> {:>2}", repeat, cx.index);

    assert_eq!(cx.index, 5);
    cx.index += 1;
    assert_eq!(cx.index, 6);

    let fut = cx.next().await;

    assert_eq!(cx.index, 6);
    cx.index -= 1;
    assert_eq!(cx.index, 5);

    println!("exec Fn f --{}<< {:>2}", repeat, cx.index);

    fut
}

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

impl<'a> Handle<'a, Context, Result> for A {
    fn call(&'a self, cx: &'a mut Context) -> BoxFuture<'a, Self::Output> {
        Box::pin(async move {
            let size = cx.middleware.len();
            let repeat = "-".repeat(2 * size);

            println!("exec St A --{}>> {:>2}", repeat, cx.index);

            assert_eq!(cx.index, 6);
            cx.index += self.index; // + 1
            assert_eq!(cx.index, 7);

            let fut = cx.next().await;

            assert_eq!(cx.index, 7);
            cx.index -= self.index; // - 1
            assert_eq!(cx.index, 6);

            println!("exec St A --{}<< {:>2}", repeat, cx.index);

            fut
        })
    }
}

struct B {
    index: usize,
}

impl<'a> Handle<'a, Context, Result> for B {
    fn call(&'a self, cx: &'a mut Context) -> BoxFuture<'a, Self::Output> {
        Box::pin(async move {
            let size = cx.middleware.len();
            let repeat = "-".repeat(2 * size);

            println!("exec St B --{}>> {:>2}", repeat, cx.index);

            assert_eq!(cx.index, 7);
            cx.index += self.index; // + 2
            assert_eq!(cx.index, 9);

            let fut = cx.next().await;

            assert_eq!(cx.index, 9);
            cx.index -= self.index; // - 2
            assert_eq!(cx.index, 7);

            println!("exec St B --{}<< {:>2}", repeat, cx.index);

            fut
        })
    }
}

struct C {
    index: usize,
}

impl<'a> Handle<'a, Context, Result> for C {
    fn call(&'a self, cx: &'a mut Context) -> BoxFuture<'a, Self::Output> {
        Box::pin(async move {
            let size = cx.middleware.len();
            let repeat = "-".repeat(2 * size);

            println!("exec St C --{}>> {:>2}", repeat, cx.index);

            assert_eq!(cx.index, 9);
            cx.index += self.index; // + 3
            assert_eq!(cx.index, 12);

            let fut = cx.next().await;

            assert_eq!(cx.index, 12);
            cx.index -= self.index; // - 3
            assert_eq!(cx.index, 9);

            println!("exec St C --{}<< {:>2}", repeat, cx.index);

            fut
        })
    }
}

fn main() {
    assert!(block_on(async move {
        let mut cx = Context {
            index: 0,
            middleware: Vec::new(),
        };

        let mut v: Vec<Box<Middleware>> = vec![
            Box::new(a),
            Box::new(b),
            Box::new(c),
            Box::new(d),
            Box::new(e),
            Box::new(f),
        ];

        let mut v: Vec<Arc<Middleware>> = vec![
            // Handled it!
            // A Closure cant use `cx.next()` in async block.
            Arc::new(|cx: &mut Context| {
                assert_eq!(cx.index, 12);

                println!("We handled it!");

                async move {
                    // assert_eq!(cx.index, 12); // compiled panic!
                    Ok(())
                }
            }),
            Arc::new(C { index: 3 }),
            Arc::new(B { index: 2 }),
            Arc::new(A { index: 1 }),
            Arc::new(f),
            Arc::new(e),
            Arc::new(d),
            Arc::new(c),
            Arc::new(b),
            Arc::new(a),
        ];

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

        let result = cx.next().await?;
        assert_eq!(result, ());

        v.clear();

        v.insert(0, Arc::new(a));
        v.insert(0, Arc::new(b));
        v.insert(0, Arc::new(c));
        v.insert(0, Arc::new(d));
        v.insert(0, Arc::new(e));
        v.insert(0, Arc::new(f));
        v.insert(0, Arc::new(A { index: 1 }));
        v.insert(0, Arc::new(B { index: 2 }));
        v.insert(0, Arc::new(C { index: 3 }));
        // Handled it!
        async fn handler(cx: &mut Context) -> Result {
            assert_eq!(cx.index, 12);

            println!("We handled it!");

            Ok(())
        }
        v.insert(0, Arc::new(handler));

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

        let result = cx.next().await?;
        assert_eq!(result, ());

        Ok::<_, Error>()
    }).is_ok());
}

许可证

根据您的选择,受 Apache 许可证 2.0 版MIT 许可证 许可。
除非您明确表示,否则根据 Apache-2.0 许可证定义,您提交的任何旨在包含在此软件包中的贡献,将按上述方式双重许可,没有任何附加条款或条件。

无运行时依赖