resplus_impl/
fut.rs

1use std::borrow::Cow;
2
3use async_trait::async_trait;
4
5use crate::ErrorChain;
6
7#[async_trait]
8pub trait FutResultChain<I, T, E, D> {
9    async fn about(self, desc: D) -> Result<T, ErrorChain<I>>
10    where
11        Self: Sized,
12        E: Into<I>,
13        D: Into<Cow<'static, str>>;
14    async fn about_else(self, f: impl FnOnce() -> D + Send) -> Result<T, ErrorChain<I>>
15    where
16        Self: Sized,
17        E: Into<I>,
18        D: Into<Cow<'static, str>>;
19}
20
21#[async_trait]
22impl<I, T, E, F> FutResultChain<I, T, E, &'static str> for F
23where
24    F: Future<Output = std::result::Result<T, E>> + Send,
25{
26    async fn about(self, desc: &'static str) -> Result<T, ErrorChain<I>>
27    where
28        Self: Sized,
29        E: Into<I>,
30    {
31        self.await.map_err(|e| ErrorChain {
32            source: e.into(),
33            context: vec![desc.into()],
34        })
35    }
36    async fn about_else(self, f: impl FnOnce() -> &'static str + Send) -> Result<T, ErrorChain<I>>
37    where
38        Self: Sized,
39        E: Into<I>,
40    {
41        self.await.map_err(|e| ErrorChain {
42            source: e.into(),
43            context: vec![f().into()],
44        })
45    }
46}
47
48#[async_trait]
49impl<I, T, E, F> FutResultChain<I, T, E, String> for F
50where
51    F: Future<Output = std::result::Result<T, E>> + Send,
52{
53    async fn about(self, desc: String) -> Result<T, ErrorChain<I>>
54    where
55        Self: Sized,
56        E: Into<I>,
57    {
58        self.await.map_err(|e| ErrorChain {
59            source: e.into(),
60            context: vec![desc.into()],
61        })
62    }
63    async fn about_else(self, f: impl FnOnce() -> String + Send) -> Result<T, ErrorChain<I>>
64    where
65        Self: Sized,
66        E: Into<I>,
67    {
68        self.await.map_err(|e| ErrorChain {
69            source: e.into(),
70            context: vec![f().into()],
71        })
72    }
73}
74
75#[cfg(test)]
76mod tests {
77    use super::FutResultChain;
78    use crate as resplus;
79    use crate::tests::{about, about_else};
80    use test_util::*;
81
82    #[tokio::test]
83    async fn about() {
84        async_assert_result!(about!(af0()), "source: Error\n  source");
85        async_assert_result!(about!(af1(1)), "source: Error\n  source");
86        async_assert_result!(about!(af2(1, 1)), "source: Error\n  source");
87    }
88
89    #[tokio::test]
90    async fn about_else() {
91        async_assert_result!(about_else!(af0()), "source: Error\n  source");
92        async_assert_result!(about_else!(af1(1)), "source: Error\n  source");
93        async_assert_result!(about_else!(af2(1, 1)), "source: Error\n  source");
94    }
95    //
96    // #[tokio::test]
97    // async fn attach() {
98    //     async_assert_result!(attach!(about!(af0())), "source: Error\n  source\n  attach");
99    //     async_assert_result!(attach!(about!(af1(1))), "source: Error\n  source\n  attach");
100    //     async_assert_result!(
101    //         attach!(about!(af2(1, 1))),
102    //         "source: Error\n  source\n  attach"
103    //     );
104    // }
105    //
106    // #[tokio::test]
107    // async fn attach_else() {
108    //     async_assert_result!(
109    //         attach_else!(about!(af0())),
110    //         "source: Error\n  source\n  attach"
111    //     );
112    //     async_assert_result!(
113    //         attach_else!(about!(af1(1))),
114    //         "source: Error\n  source\n  attach"
115    //     );
116    //     async_assert_result!(
117    //         attach_else!(about!(af2(1, 1))),
118    //         "source: Error\n  source\n  attach"
119    //     );
120    // }
121}