axum_resp_result/resp_result/
try_op.rs

1use std::{
2    convert::Infallible,
3    ops::{ControlFlow, FromResidual, Try},
4};
5#[cfg(feature = "tracing")]
6use trace::{event, Level};
7
8use crate::RespError;
9
10use super::RespResult;
11
12impl<T, E: RespError> Try for RespResult<T, E> {
13    type Output = T;
14
15    type Residual = RespResult<Infallible, E>;
16
17    #[inline]
18    fn from_output(output: Self::Output) -> Self {
19        Self::Success(output)
20    }
21    #[inline]
22    fn branch(self) -> ControlFlow<Self::Residual, Self::Output> {
23        match self {
24            RespResult::Success(data) => {
25                #[cfg(feature = "tracing")]
26                event!(Level::TRACE, control_flow = "Continue");
27                ControlFlow::Continue(data)
28            }
29            RespResult::Err(e) => {
30                #[cfg(feature = "tracing")]
31                event!(Level::TRACE, control_flow = "Break");
32                ControlFlow::Break(RespResult::Err(e))
33            }
34        }
35    }
36}
37
38impl<T, E, Ei> FromResidual<RespResult<Infallible, Ei>> for RespResult<T, E>
39where
40    E: From<Ei>,
41{
42    #[inline]
43    fn from_residual(residual: RespResult<Infallible, Ei>) -> Self {
44        match residual {
45            RespResult::Err(e) => Self::Err(From::from(e)),
46            RespResult::Success(_) => unreachable!(),
47        }
48    }
49}
50
51impl<T, E, F> FromResidual<Result<Infallible, E>> for RespResult<T, F>
52where
53    F: From<E>,
54{
55    #[inline]
56    fn from_residual(residual: Result<Infallible, E>) -> Self {
57        match residual {
58            Err(e) => Self::Err(F::from(e)),
59            Ok(_) => unreachable!(),
60        }
61    }
62}
63
64impl<T, E, F> FromResidual<RespResult<Infallible, E>> for Result<T, F>
65where
66    F: From<E>,
67{
68    #[inline]
69    fn from_residual(residual: RespResult<Infallible, E>) -> Self {
70        match residual {
71            RespResult::Err(err) => Result::Err(F::from(err)),
72            RespResult::Success(_) => unreachable!(),
73        }
74    }
75}
76
77#[cfg(test)]
78mod test {
79    use crate::{RespError, RespResult};
80
81    struct A;
82    struct B;
83
84    impl From<A> for MockA {
85        fn from(a: A) -> Self {
86            MockA::A(a)
87        }
88    }
89
90    impl From<B> for MockA {
91        fn from(v: B) -> Self {
92            MockA::B(v)
93        }
94    }
95
96    enum MockA {
97        A(A),
98        B(B),
99    }
100    impl RespError for MockA {
101        fn log_message(&self) -> std::borrow::Cow<'static, str> {
102            "MockA".into()
103        }
104
105        #[cfg(feature = "extra-error")]
106        type ExtraMessage = String;
107        #[cfg(feature = "extra-error")]
108        fn extra_message(&self) -> Self::ExtraMessage {
109            String::new()
110        }
111    }
112
113    // test wether ? can work on Result
114    fn _testb() -> RespResult<u32, MockA> {
115        let a = Result::<_, A>::Ok(11u32)?;
116        let _b = RespResult::<_, MockA>::ok(a)?;
117        let c = Result::<u32, B>::Err(B)?;
118
119        RespResult::Success(c)
120    }
121}