sofie_core/
error_status.rs1use crate::Error;
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq)]
4pub enum ErrorStatus {
5 BadRequest,
6 NotFound,
7 Conflict,
8 Unprocessable,
9 TooManyRequests,
10 Internal,
11 Unavailable,
12}
13
14const CODES: [(ErrorStatus, u16); 7] = [
15 (ErrorStatus::BadRequest, 400),
16 (ErrorStatus::NotFound, 404),
17 (ErrorStatus::Conflict, 409),
18 (ErrorStatus::Unprocessable, 422),
19 (ErrorStatus::TooManyRequests, 429),
20 (ErrorStatus::Internal, 500),
21 (ErrorStatus::Unavailable, 503),
22];
23
24impl ErrorStatus {
25 #[must_use]
26 pub fn of(error: &Error) -> Self {
27 match error {
28 Error::NotFound | Error::Moved { .. } => Self::NotFound,
29 Error::Conflict => Self::Conflict,
30 Error::BadRequest(_) => Self::BadRequest,
31 Error::Invalid(_) | Error::Rule(_) | Error::KeyedRule(_) => Self::Unprocessable,
32 Error::TooManyRequests(_) => Self::TooManyRequests,
33 Error::Unavailable(_) => Self::Unavailable,
34 Error::Internal { .. } => Self::Internal,
35 }
36 }
37
38 #[must_use]
39 pub fn code(self) -> u16 {
40 CODES
41 .iter()
42 .find(|(status, _)| *status == self)
43 .map(|(_, code)| *code)
44 .expect("every status is in the table")
45 }
46
47 #[must_use]
48 pub fn from_code(code: u16) -> Option<Self> {
49 CODES
50 .iter()
51 .find(|(_, candidate)| *candidate == code)
52 .map(|(status, _)| *status)
53 }
54}
55
56#[cfg(test)]
57mod tests {
58 use std::time::Duration;
59
60 use super::*;
61
62 #[test]
63 fn reads_back_the_status_each_error_is_answered_with() {
64 let errors = [
65 (Error::BadRequest(String::new()), 400),
66 (Error::NotFound, 404),
67 (Error::Conflict, 409),
68 (Error::Rule(String::new()), 422),
69 (Error::TooManyRequests(Duration::ZERO), 429),
70 (Error::internal_message(""), 500),
71 (Error::Unavailable(String::new()), 503),
72 ];
73
74 for (error, code) in errors {
75 let status = ErrorStatus::of(&error);
76 assert_eq!(status.code(), code);
77 assert_eq!(ErrorStatus::from_code(code), Some(status));
78 }
79 assert_eq!(ErrorStatus::from_code(418), None);
80 }
81}