Skip to main content

carapax/core/error/
mod.rs

1use std::{future::Future, marker::PhantomData};
2
3use crate::core::{
4    convert::TryFromInput,
5    handler::{Handler, HandlerError, HandlerInput, HandlerResult, IntoHandlerResult},
6};
7
8#[cfg(test)]
9mod tests;
10
11/// Allows to process an error returned by a handler.
12pub struct ErrorDecorator<E, H, HI> {
13    error_handler: E,
14    handler: H,
15    handler_input: PhantomData<HI>,
16}
17
18impl<E, H, HI> ErrorDecorator<E, H, HI> {
19    /// Creates a new `ErrorDecorator`.
20    ///
21    /// # Arguments
22    ///
23    /// * `error_handler` - A handler for errors returned by a decorated handler.
24    /// * `handler` - The handler to be decorated.
25    pub fn new(error_handler: E, handler: H) -> Self {
26        Self {
27            error_handler,
28            handler,
29            handler_input: PhantomData,
30        }
31    }
32}
33
34impl<E, H, HI> Clone for ErrorDecorator<E, H, HI>
35where
36    E: Clone,
37    H: Clone,
38{
39    fn clone(&self) -> Self {
40        Self {
41            error_handler: self.error_handler.clone(),
42            handler: self.handler.clone(),
43            handler_input: PhantomData,
44        }
45    }
46}
47
48impl<E, H, HI> Handler<HandlerInput> for ErrorDecorator<E, H, HI>
49where
50    E: ErrorHandler + Clone + Sync + 'static,
51    H: Handler<HI> + Sync + 'static,
52    HI: TryFromInput + Sync,
53    HI::Error: 'static,
54    H::Output: IntoHandlerResult,
55{
56    type Output = HandlerResult;
57
58    async fn handle(&self, input: HandlerInput) -> Self::Output {
59        let future = HI::try_from_input(input);
60        match future.await {
61            Ok(Some(input)) => match self.handler.handle(input).await.into_result() {
62                Err(err) => Err(self.error_handler.handle(err).await),
63                result => result,
64            },
65            Ok(None) => Ok(()),
66            Err(err) => Err(self.error_handler.handle(HandlerError::new(err)).await),
67        }
68    }
69}
70
71/// Allows to process errors returned by handlers.
72pub trait ErrorHandler: Send {
73    /// Handles a errors.
74    ///
75    /// # Arguments
76    ///
77    /// * `err` - An error to handle.
78    fn handle(&self, err: HandlerError) -> impl Future<Output = HandlerError> + Send;
79}
80
81impl<H, F> ErrorHandler for H
82where
83    H: Fn(HandlerError) -> F + Send + Sync,
84    F: Future<Output = HandlerError> + Send,
85{
86    async fn handle(&self, err: HandlerError) -> HandlerError {
87        (self)(err).await
88    }
89}
90
91/// Provides a shortcut for creating error decorator.
92pub trait ErrorExt<E, HI>: Sized {
93    /// A shortcut to create a new error decorator.
94    ///
95    /// Example: `handler.on_error(error_handler)`
96    ///
97    /// # Arguments
98    ///
99    /// * `error_handler` - An error handler.
100    fn on_error(self, error_handler: E) -> ErrorDecorator<E, Self, HI> {
101        ErrorDecorator::new(error_handler, self)
102    }
103}
104
105impl<E, H, HI> ErrorExt<E, HI> for H
106where
107    H: Handler<HI>,
108    HI: TryFromInput,
109{
110}