use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ApiErrorCode {
Unauthorized,
Forbidden,
BadRequest,
NotFound,
Conflict,
InvalidState,
TooManyRequests,
Protocol,
Internal,
}
impl ApiErrorCode {
pub const fn http_status(self) -> u16 {
match self {
Self::Unauthorized => 401,
Self::Forbidden => 403,
Self::BadRequest | Self::Protocol => 400,
Self::NotFound => 404,
Self::Conflict => 409,
Self::InvalidState => 409,
Self::TooManyRequests => 429,
Self::Internal => 500,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Error)]
#[error("{code:?}: {message}")]
pub struct ApiError {
pub code: ApiErrorCode,
pub message: String,
pub request_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub protocol_code: Option<String>,
}
impl ApiError {
pub fn new(code: ApiErrorCode, message: impl Into<String>, request_id: impl Into<String>) -> Self {
Self {
code,
message: message.into(),
request_id: request_id.into(),
protocol_code: None,
}
}
pub fn with_protocol_code(mut self, sub: impl Into<String>) -> Self {
self.protocol_code = Some(sub.into());
self
}
}
#[cfg(test)]
mod tests;