Skip to main content

sofie_core/
error_status.rs

1use 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}