sophia_api/source/
_stream_error.rs

1use std::error::Error;
2
3/// A error that is raised by functions that move fallible `Source`s into
4/// fallible `Sinks`.
5///
6/// In case this error is raised it can be matched to investigate if `Source`
7/// or `Sink` failed.
8///
9/// # Conversion
10///
11/// Both variants `SourceError` and `SinkError` are public exported.
12/// Consequently, `StreamError` can be constructed with `.map_err(SourceError)`
13/// and `.map_err(SinkError)`.
14#[derive(Debug, thiserror::Error)]
15pub enum StreamError<SourceErr, SinkErr>
16where
17    SourceErr: Error,
18    SinkErr: Error,
19{
20    /// Error caused by the source
21    #[error("Source failed: {0}")]
22    SourceError(#[source] SourceErr),
23    /// Error caused by the sink
24    #[error("Sink failed: {0}")]
25    SinkError(#[source] SinkErr),
26}
27pub use StreamError::*;
28
29impl<SourceErr, SinkErr> StreamError<SourceErr, SinkErr>
30where
31    SourceErr: Error,
32    SinkErr: Error,
33{
34    /// Checks if `StreamError` was raised by the `Source`.
35    pub fn is_source_error(&self) -> bool {
36        matches!(self, SourceError(_))
37    }
38    /// Checks if `StreamError` was raised by the `Sink`.
39    pub fn is_sink_error(&self) -> bool {
40        matches!(self, SinkError(_))
41    }
42    /// Converts `StreamError` into an inner error.
43    pub fn inner_into<Err>(self) -> Err
44    where
45        SourceErr: Error + Into<Err>,
46        SinkErr: Error + Into<Err>,
47    {
48        match self {
49            SourceError(err) => err.into(),
50            SinkError(err) => err.into(),
51        }
52    }
53    /// Convert using `f` if a `SourceError`
54    pub fn map_source<E, F>(self, f: F) -> StreamError<E, SinkErr>
55    where
56        E: Error,
57        F: FnOnce(SourceErr) -> E,
58    {
59        match self {
60            SourceError(e) => SourceError(f(e)),
61            SinkError(e) => SinkError(e),
62        }
63    }
64    /// Convert using `f` if a `SinkError`
65    pub fn map_sink<E, F>(self, f: F) -> StreamError<SourceErr, E>
66    where
67        E: Error,
68        F: FnOnce(SinkErr) -> E,
69    {
70        match self {
71            SourceError(e) => SourceError(e),
72            SinkError(e) => SinkError(f(e)),
73        }
74    }
75    /// Unwrap as the inner SourceError.
76    ///
77    /// # Panic
78    /// Panic if self is actually a SinkError.
79    pub fn unwrap_source_error(self) -> SourceErr {
80        match self {
81            SourceError(err) => err,
82            SinkError(_) => panic!("this is a SinkError"),
83        }
84    }
85    /// Unwrap as the inner SinkError.
86    ///
87    /// # Panic
88    /// Panic if self is actually a SourceError.
89    pub fn unwrap_sink_error(self) -> SinkErr {
90        match self {
91            SourceError(_) => panic!("this is a SourceError"),
92            SinkError(err) => err,
93        }
94    }
95    /// Switch source and sink error.
96    pub fn reverse(self) -> StreamError<SinkErr, SourceErr> {
97        match self {
98            SourceError(e) => SinkError(e),
99            SinkError(e) => SourceError(e),
100        }
101    }
102}
103
104/// Convenient type alias for [`Result`] whose error is [`StreamError`].
105pub type StreamResult<T, E1, E2> = Result<T, StreamError<E1, E2>>;
106
107/// Additional methods for [`StreamResult`]
108pub trait StreamResultExt<T, E1, E2>
109where
110    E1: Error,
111    E2: Error,
112{
113    /// Map the error if it is a [`SourceError`]
114    fn map_source_err<E, F>(self, f: F) -> StreamResult<T, E, E2>
115    where
116        E: Error,
117        F: FnOnce(E1) -> E;
118    /// Map the error if it is a [`SinkError`]
119    fn map_sink_err<E, F>(self, f: F) -> StreamResult<T, E1, E>
120    where
121        E: Error,
122        F: FnOnce(E2) -> E;
123}
124
125impl<T, E1, E2> StreamResultExt<T, E1, E2> for StreamResult<T, E1, E2>
126where
127    E1: Error,
128    E2: Error,
129{
130    fn map_source_err<E, F>(self, f: F) -> StreamResult<T, E, E2>
131    where
132        E: Error,
133        F: FnOnce(E1) -> E,
134    {
135        self.map_err(|err| err.map_source(f))
136    }
137
138    fn map_sink_err<E, F>(self, f: F) -> StreamResult<T, E1, E>
139    where
140        E: Error,
141        F: FnOnce(E2) -> E,
142    {
143        self.map_err(|err| err.map_sink(f))
144    }
145}