1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use std::future::Future;
use futures_util::future::BoxFuture;
use teo_result::Result;
use crate::arguments::Arguments;
use crate::pipeline::Ctx;
use crate::pipeline::ctx::extract::ExtractFromPipelineCtx;

pub enum CallbackResult {
    Result(Result<()>)
}

impl From<()> for CallbackResult {
    fn from(_: ()) -> Self {
        CallbackResult::Result(Ok(()))
    }
}

impl From<Result<()>> for CallbackResult {
    fn from(result: Result<()>) -> Self {
        CallbackResult::Result(result)
    }
}

pub trait CallbackArgument<A, O: Into<CallbackResult>>: Send + Sync + 'static {
    fn call(&self, args: Arguments, ctx: Ctx) -> BoxFuture<'static, O>;
}

impl<A0, O, F, Fut> CallbackArgument<(A0,), O> for F where
    A0: ExtractFromPipelineCtx + Send + Sync,
    F: Fn(A0) -> Fut + Sync + Send + Clone + 'static,
    O: Into<CallbackResult> + Send + Sync,
    Fut: Future<Output = O> + Send + 'static {
    fn call(&self, args: Arguments, ctx: Ctx) -> BoxFuture<'static, O> {
        let value: A0 = ExtractFromPipelineCtx::extract(&args, &ctx);
        Box::pin(self(value))
    }
}

impl<A0, A1, O, F, Fut> CallbackArgument<(A0, A1), O> for F where
    A0: ExtractFromPipelineCtx + Send + Sync,
    A1: ExtractFromPipelineCtx + Send + Sync,
    F: Fn(A0, A1) -> Fut + Sync + Send + 'static,
    O: Into<CallbackResult> + Send + Sync,
    Fut: Future<Output = O> + Send + 'static {
    fn call(&self, args: Arguments, ctx: Ctx) -> BoxFuture<'static, O> {
        let value: A0 = ExtractFromPipelineCtx::extract(&args, &ctx);
        let arg1: A1 = ExtractFromPipelineCtx::extract(&args, &ctx);
        Box::pin(self(value, arg1))
    }
}

impl<A0, A1, A2, O, F, Fut> CallbackArgument<(A0, A1, A2), O> for F where
    A0: ExtractFromPipelineCtx + Send + Sync,
    A1: ExtractFromPipelineCtx + Send + Sync,
    A2: ExtractFromPipelineCtx + Send + Sync,
    F: Fn(A0, A1, A2) -> Fut + Sync + Send + 'static,
    O: Into<CallbackResult> + Send + Sync,
    Fut: Future<Output = O> + Send + 'static {
    fn call(&self, args: Arguments, ctx: Ctx) -> BoxFuture<'static, O> {
        let value: A0 = ExtractFromPipelineCtx::extract(&args, &ctx);
        let arg1: A1 = ExtractFromPipelineCtx::extract(&args, &ctx);
        let arg2: A2 = ExtractFromPipelineCtx::extract(&args, &ctx);
        Box::pin(self(value, arg1, arg2))
    }
}

impl<A0, A1, A2, A3, O, F, Fut> CallbackArgument<(A0, A1, A2, A3), O> for F where
    A0: ExtractFromPipelineCtx + Send + Sync,
    A1: ExtractFromPipelineCtx + Send + Sync,
    A2: ExtractFromPipelineCtx + Send + Sync,
    A3: ExtractFromPipelineCtx + Send + Sync,
    F: Fn(A0, A1, A2, A3) -> Fut + Sync + Send + 'static,
    O: Into<CallbackResult> + Send + Sync,
    Fut: Future<Output = O> + Send + 'static {
    fn call(&self, args: Arguments, ctx: Ctx) -> BoxFuture<'static, O> {
        let value: A0 = ExtractFromPipelineCtx::extract(&args, &ctx);
        let arg1: A1 = ExtractFromPipelineCtx::extract(&args, &ctx);
        let arg2: A2 = ExtractFromPipelineCtx::extract(&args, &ctx);
        let arg3: A3 = ExtractFromPipelineCtx::extract(&args, &ctx);
        Box::pin(self(value, arg1, arg2, arg3))
    }
}