sofie-core 0.4.0

The value model, ids, time, encodings, the registration rules and the framework's error every crate shares.
Documentation
use crate::Error;

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorStatus {
    BadRequest,
    NotFound,
    Conflict,
    Unprocessable,
    TooManyRequests,
    Internal,
    Unavailable,
}

const CODES: [(ErrorStatus, u16); 7] = [
    (ErrorStatus::BadRequest, 400),
    (ErrorStatus::NotFound, 404),
    (ErrorStatus::Conflict, 409),
    (ErrorStatus::Unprocessable, 422),
    (ErrorStatus::TooManyRequests, 429),
    (ErrorStatus::Internal, 500),
    (ErrorStatus::Unavailable, 503),
];

impl ErrorStatus {
    #[must_use]
    pub fn of(error: &Error) -> Self {
        match error {
            Error::NotFound | Error::Moved { .. } => Self::NotFound,
            Error::Conflict => Self::Conflict,
            Error::BadRequest(_) => Self::BadRequest,
            Error::Invalid(_) | Error::Rule(_) | Error::KeyedRule(_) => Self::Unprocessable,
            Error::TooManyRequests(_) => Self::TooManyRequests,
            Error::Unavailable(_) => Self::Unavailable,
            Error::Internal { .. } => Self::Internal,
        }
    }

    #[must_use]
    pub fn code(self) -> u16 {
        CODES
            .iter()
            .find(|(status, _)| *status == self)
            .map(|(_, code)| *code)
            .expect("every status is in the table")
    }

    #[must_use]
    pub fn from_code(code: u16) -> Option<Self> {
        CODES
            .iter()
            .find(|(_, candidate)| *candidate == code)
            .map(|(status, _)| *status)
    }
}

#[cfg(test)]
mod tests {
    use std::time::Duration;

    use super::*;

    #[test]
    fn reads_back_the_status_each_error_is_answered_with() {
        let errors = [
            (Error::BadRequest(String::new()), 400),
            (Error::NotFound, 404),
            (Error::Conflict, 409),
            (Error::Rule(String::new()), 422),
            (Error::TooManyRequests(Duration::ZERO), 429),
            (Error::internal_message(""), 500),
            (Error::Unavailable(String::new()), 503),
        ];

        for (error, code) in errors {
            let status = ErrorStatus::of(&error);
            assert_eq!(status.code(), code);
            assert_eq!(ErrorStatus::from_code(code), Some(status));
        }
        assert_eq!(ErrorStatus::from_code(418), None);
    }
}