1use crate::traits::{Handled, HandlerError};
2use crate::CanonicalMessage;
3
4pub trait IntoHandled {
6 fn into_handled(self) -> Handled;
7}
8
9impl IntoHandled for Handled {
10 fn into_handled(self) -> Handled {
11 self
12 }
13}
14
15impl IntoHandled for () {
16 fn into_handled(self) -> Handled {
17 Handled::Ack
18 }
19}
20
21impl IntoHandled for CanonicalMessage {
22 fn into_handled(self) -> Handled {
23 Handled::Publish(self)
24 }
25}
26
27impl IntoHandled for Option<CanonicalMessage> {
28 fn into_handled(self) -> Handled {
29 match self {
30 Some(msg) => Handled::Publish(msg),
31 None => Handled::Ack,
32 }
33 }
34}
35
36pub trait IntoHandlerResult: Send + Sync + 'static {
71 fn into_handler_result(self) -> Result<Handled, HandlerError>;
72}
73
74pub trait ErgonomicResponse: IntoHandlerResult {}
77
78impl IntoHandlerResult for Handled {
79 fn into_handler_result(self) -> Result<Handled, HandlerError> {
80 Ok(self)
81 }
82}
83impl ErgonomicResponse for Handled {}
84
85impl IntoHandlerResult for () {
86 fn into_handler_result(self) -> Result<Handled, HandlerError> {
87 Ok(Handled::Ack)
88 }
89}
90impl ErgonomicResponse for () {}
91
92impl IntoHandlerResult for CanonicalMessage {
93 fn into_handler_result(self) -> Result<Handled, HandlerError> {
94 Ok(Handled::Publish(self))
95 }
96}
97impl ErgonomicResponse for CanonicalMessage {}
98
99impl IntoHandlerResult for Option<CanonicalMessage> {
100 fn into_handler_result(self) -> Result<Handled, HandlerError> {
101 Ok(self.into_handled())
102 }
103}
104impl ErgonomicResponse for Option<CanonicalMessage> {}
105
106impl IntoHandlerResult for Result<Handled, HandlerError> {
109 fn into_handler_result(self) -> Result<Handled, HandlerError> {
110 self
111 }
112}
113
114impl<E> IntoHandlerResult for Result<(), E>
115where
116 E: ToHandlerError + Send + Sync + 'static,
117{
118 fn into_handler_result(self) -> Result<Handled, HandlerError> {
119 match self {
120 Ok(_) => Ok(Handled::Ack),
121 Err(err) => Err(err.to_handler_error()),
122 }
123 }
124}
125impl<E> ErgonomicResponse for Result<(), E> where E: ToHandlerError + Send + Sync + 'static {}
126
127impl<E> IntoHandlerResult for Result<CanonicalMessage, E>
128where
129 E: ToHandlerError + Send + Sync + 'static,
130{
131 fn into_handler_result(self) -> Result<Handled, HandlerError> {
132 match self {
133 Ok(msg) => Ok(Handled::Publish(msg)),
134 Err(err) => Err(err.to_handler_error()),
135 }
136 }
137}
138impl<E> ErgonomicResponse for Result<CanonicalMessage, E> where
139 E: ToHandlerError + Send + Sync + 'static
140{
141}
142
143impl<E> IntoHandlerResult for Result<Option<CanonicalMessage>, E>
144where
145 E: ToHandlerError + Send + Sync + 'static,
146{
147 fn into_handler_result(self) -> Result<Handled, HandlerError> {
148 match self {
149 Ok(val) => Ok(val.into_handled()),
150 Err(err) => Err(err.to_handler_error()),
151 }
152 }
153}
154impl<E> ErgonomicResponse for Result<Option<CanonicalMessage>, E> where
155 E: ToHandlerError + Send + Sync + 'static
156{
157}
158
159pub trait ToHandlerError {
161 fn to_handler_error(self) -> HandlerError;
162}
163
164impl ToHandlerError for HandlerError {
165 fn to_handler_error(self) -> HandlerError {
166 self
167 }
168}
169
170impl ToHandlerError for anyhow::Error {
171 fn to_handler_error(self) -> HandlerError {
172 crate::errors::ProcessingError::Retryable(self)
173 }
174}
175
176impl ToHandlerError for String {
177 fn to_handler_error(self) -> HandlerError {
178 crate::errors::ProcessingError::NonRetryable(anyhow::anyhow!(self))
179 }
180}
181
182impl ToHandlerError for &str {
183 fn to_handler_error(self) -> HandlerError {
184 crate::errors::ProcessingError::NonRetryable(anyhow::anyhow!(self.to_string()))
185 }
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191 use crate::errors::ProcessingError;
192
193 #[test]
194 fn test_into_handled_converts_supported_success_types() {
195 assert!(matches!(().into_handled(), Handled::Ack));
196 assert!(matches!(
197 None::<CanonicalMessage>.into_handled(),
198 Handled::Ack
199 ));
200
201 let message = CanonicalMessage::from("payload");
202 match message.clone().into_handled() {
203 Handled::Publish(published) => assert_eq!(published.get_payload_str(), "payload"),
204 Handled::Ack => panic!("expected publish result"),
205 }
206
207 match Some(message).into_handled() {
208 Handled::Publish(published) => assert_eq!(published.get_payload_str(), "payload"),
209 Handled::Ack => panic!("expected publish result"),
210 }
211 }
212
213 #[test]
214 fn test_into_handler_result_converts_ok_variants() {
215 assert!(matches!(().into_handler_result().unwrap(), Handled::Ack));
216 assert!(matches!(
217 Option::<CanonicalMessage>::None
218 .into_handler_result()
219 .unwrap(),
220 Handled::Ack
221 ));
222
223 match CanonicalMessage::from("reply")
224 .into_handler_result()
225 .unwrap()
226 {
227 Handled::Publish(message) => assert_eq!(message.get_payload_str(), "reply"),
228 Handled::Ack => panic!("expected publish result"),
229 }
230
231 match Result::<Option<CanonicalMessage>, &str>::Ok(Some(CanonicalMessage::from("maybe")))
232 .into_handler_result()
233 .unwrap()
234 {
235 Handled::Publish(message) => assert_eq!(message.get_payload_str(), "maybe"),
236 Handled::Ack => panic!("expected publish result"),
237 }
238 }
239
240 #[test]
241 fn test_into_handler_result_and_to_handler_error_convert_errors() {
242 let retryable =
243 Result::<CanonicalMessage, anyhow::Error>::Err(anyhow::anyhow!("temporary"))
244 .into_handler_result()
245 .unwrap_err();
246 assert!(matches!(retryable, ProcessingError::Retryable(_)));
247
248 let non_retryable = Result::<(), &str>::Err("permanent")
249 .into_handler_result()
250 .unwrap_err();
251 assert!(matches!(non_retryable, ProcessingError::NonRetryable(_)));
252
253 let string_error = "string failure".to_string().to_handler_error();
254 assert!(matches!(string_error, ProcessingError::NonRetryable(_)));
255
256 let str_error = "str failure".to_handler_error();
257 assert!(matches!(str_error, ProcessingError::NonRetryable(_)));
258 }
259}