viz_core/handler/
catch_error.rs

1use std::marker::PhantomData;
2
3use crate::{Handler, IntoResponse, Response, Result};
4
5/// Catches rejected error while calling the handler.
6#[derive(Debug)]
7pub struct CatchError<H, F, E, R> {
8    h: H,
9    f: F,
10    _marker: PhantomData<fn(E) -> R>,
11}
12
13impl<H, F, E, R> Clone for CatchError<H, F, E, R>
14where
15    H: Clone,
16    F: Clone,
17{
18    fn clone(&self) -> Self {
19        Self {
20            h: self.h.clone(),
21            f: self.f.clone(),
22            _marker: PhantomData,
23        }
24    }
25}
26
27impl<H, F, E, R> CatchError<H, F, E, R> {
28    /// Creates a [`CatchError`] handler.
29    #[inline]
30    pub fn new(h: H, f: F) -> Self {
31        Self {
32            h,
33            f,
34            _marker: PhantomData,
35        }
36    }
37}
38
39#[crate::async_trait]
40impl<H, I, O, F, E, R> Handler<I> for CatchError<H, F, E, R>
41where
42    I: Send + 'static,
43    H: Handler<I, Output = Result<O>>,
44    O: IntoResponse + Send,
45    E: std::error::Error + Send + 'static,
46    F: Handler<E, Output = R>,
47    R: IntoResponse + 'static,
48{
49    type Output = Result<Response>;
50
51    async fn call(&self, i: I) -> Self::Output {
52        match self.h.call(i).await {
53            Ok(r) => Ok(r.into_response()),
54            Err(e) => Ok(self.f.call(e.downcast::<E>()?).await.into_response()),
55        }
56    }
57}