little_stomper/error/
mod.rs

1use std::convert::{From, Infallible};
2use std::error::Error;
3use std::fmt::{self, Display, Formatter};
4
5use sender_sink::wrappers::SinkError;
6use stomp_parser::error::StompParseError;
7
8#[derive(Debug, PartialEq, Eq, Clone)]
9pub struct StomperError {
10    pub message: String,
11}
12
13impl StomperError {
14    pub fn new(message: &str) -> StomperError {
15        StomperError {
16            message: message.to_owned(),
17        }
18    }
19}
20
21impl From<StompParseError> for StomperError {
22    fn from(err: StompParseError) -> Self {
23        StomperError {
24            message: err.message().to_owned(),
25        }
26    }
27}
28
29impl From<Infallible> for StomperError {
30    fn from(_: Infallible) -> Self {
31        StomperError {
32            message: "Should have been Infallible!".to_owned(),
33        }
34    }
35}
36
37impl From<SinkError> for StomperError {
38    fn from(err: SinkError) -> Self {
39        StomperError {
40            message: format!("Error sending to Sink: {:?}", err),
41        }
42    }
43}
44
45impl Display for StomperError {
46    fn fmt(
47        &self,
48        formatter: &mut std::fmt::Formatter<'_>,
49    ) -> std::result::Result<(), std::fmt::Error> {
50        formatter.write_str(&self.message)
51    }
52}
53
54#[derive(Debug)]
55pub struct ErrorWrapper(Box<dyn Error + Send + Sync>);
56
57impl ErrorWrapper {
58    pub(crate) fn new<E: Into<Box<dyn Error + Send + Sync>>>(err: E) -> ErrorWrapper {
59        ErrorWrapper(err.into())
60    }
61}
62
63impl Display for ErrorWrapper {
64    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
65        write!(f, "{:?},", self.0)
66    }
67}
68
69impl<T> From<T> for ErrorWrapper
70where
71    T: Error + Send + Sync + 'static,
72{
73    fn from(err: T) -> Self {
74        ErrorWrapper::new(err)
75    }
76}
77
78#[derive(Debug)]
79pub struct UnknownCommandError {
80    text: &'static str,
81}
82
83impl Display for UnknownCommandError {
84    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
85        write!(f, "Unknown command {:?}", self.text)
86    }
87}
88
89impl Error for UnknownCommandError {}
90
91#[cfg(test)]
92mod test {
93    use sender_sink::wrappers::SinkError;
94    use stomp_parser::error::StompParseError;
95
96    use crate::error::{ErrorWrapper, StomperError};
97    use std::convert::Infallible;
98    use std::error::Error;
99    use std::fmt::{Display, Formatter};
100    #[derive(Debug)]
101    struct ErrorForTest(u32);
102
103    impl Error for ErrorForTest {}
104
105    impl Display for ErrorForTest {
106        fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
107            write!(f, "ErrorForTest({})", self.0)
108        }
109    }
110
111    #[test]
112    fn wraps_error() {
113        let error = ErrorForTest(42);
114
115        let wrapped_error = ErrorWrapper::new(error);
116
117        assert_eq!(42, wrapped_error.0.downcast::<ErrorForTest>().unwrap().0);
118    }
119
120    #[test]
121    fn from_stomp_parse_error() {
122        let src = StompParseError::new("freaky");
123        let error: StomperError = src.into();
124
125        assert_eq!("freaky", error.message);
126    }
127
128    #[test]
129    fn from_sink_error() {
130        let src = SinkError::ChannelClosed;
131        let error: StomperError = src.into();
132
133        assert!(error.message.contains("Closed"));
134    }
135
136    fn never_error() -> Result<(), Infallible> {
137        Ok(())
138    }
139
140    #[test]
141    fn from_infallible() {
142        let src = never_error();
143        let target = src.map_err(StomperError::from);
144
145        // this is really a compiler test
146        assert!(target.is_ok());
147    }
148
149    #[test]
150    fn error_display() {
151        let src = StomperError::new("Hello, world!");
152
153        // this is really a compiler test
154        assert_eq!("Hello, world!", src.to_string());
155    }
156}