1use async_trait::async_trait;
2use std::future::Future;
3
4#[async_trait]
5pub trait AsyncFn<Args, Output> {
6 async fn call(&self, args: Args) -> Output;
7}
8
9macro_rules! ary ({ $($param:ident)* } => {
18 #[async_trait::async_trait]
19 impl<Func, Fut, $($param:Send + 'static,)*> AsyncFn<($($param,)*), Fut::Output> for Func
20 where
21 Func: Send + Sync + Fn($($param),*) -> Fut,
22 Fut: Future + Send
23 {
24 #[inline]
25 #[allow(non_snake_case)]
26 async fn call(&self, ($($param,)*): ($($param,)*)) -> Fut::Output {
27 (self)($($param,)*).await
28 }
29 }
30});
31
32ary! {}
33ary! { A }
34ary! { A B }
35ary! { A B C }
36ary! { A B C D }
37ary! { A B C D E }
38ary! { A B C D E F }
39ary! { A B C D E F G }
40ary! { A B C D E F G H }
41ary! { A B C D E F G H I }
42ary! { A B C D E F G H I J }
43ary! { A B C D E F G H I J K }
44ary! { A B C D E F G H I J K L }
45
46#[cfg(test)]
47mod tests {
48 use super::*;
49
50 struct Request {}
51 struct Response {}
52 struct Body {}
53
54 impl From<Request> for (Request,) {
55 fn from(req: Request) -> Self {
56 (req,)
57 }
58 }
59
60 impl From<Request> for (Body,) {
61 fn from(_req: Request) -> Self {
62 (Body {},)
63 }
64 }
65
66 impl From<&'static str> for Response {
67 fn from(_s: &'static str) -> Self {
68 Response {}
69 }
70 }
71
72 fn assert_impl_output<T: From<Request>, O: Into<Response>>(_: impl AsyncFn<T, O>) {}
73
74 #[test]
75 fn test_trait_bounds() {
76 async fn with_request_resp(_req: Request) -> &'static str {
77 "hello"
78 }
79
80 async fn with_body_resp(_body: Body) -> &'static str {
81 "hello"
82 }
83
84 assert_impl_output(with_request_resp);
85 assert_impl_output(with_body_resp);
86 }
87
88 fn assert_impl_fn<T, O>(_: impl AsyncFn<T, O>) {}
89
90 #[test]
91 fn test_args() {
92 async fn min() {}
93 async fn min_output() -> i32 {
94 4
95 }
96 async fn with_req(_req: String) -> &'static str {
97 "foo"
98 }
99 async fn with_refs(_r: &str, _b: &[u8]) -> &'static str {
100 "asdf"
101 }
102 struct Test {
103 _a: bool,
104 b: u8,
105 }
106
107 impl Test {
108 async fn bleh(&self) -> &u8 {
109 &self.b
110 }
111 }
112
113 #[rustfmt::skip]
114 #[allow(clippy::too_many_arguments, clippy::just_underscores_and_digits)]
115 async fn max(
116 _01: (), _02: (), _03: (), _04: (), _05: (), _06: (),
117 _07: (), _08: (), _09: (), _10: (), _11: (), _12: (),
118 ) {}
119
120 assert_impl_fn(min);
121 assert_impl_fn(with_req);
122 assert_impl_fn(min_output);
123 assert_impl_fn(max);
124 assert_impl_fn(with_refs);
125 assert_impl_fn(Test::bleh);
126 }
127}