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 }