1use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct ErrorResponse {
10 pub error: ErrorDetail,
12}
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct ErrorDetail {
17 pub message: String,
19 pub r#type: String,
21 #[serde(skip_serializing_if = "Option::is_none")]
23 pub param: Option<String>,
24 #[serde(skip_serializing_if = "Option::is_none")]
26 pub code: Option<String>,
27}
28
29impl ErrorResponse {
30 pub fn new(message: impl Into<String>, error_type: impl Into<String>) -> Self {
32 Self {
33 error: ErrorDetail {
34 message: message.into(),
35 r#type: error_type.into(),
36 param: None,
37 code: None,
38 },
39 }
40 }
41
42 pub fn invalid_request(message: impl Into<String>) -> Self {
44 Self::new(message, "invalid_request_error")
45 }
46
47 pub fn authentication_error() -> Self {
49 Self::new("Invalid authentication", "authentication_error")
50 }
51
52 pub fn rate_limit_error() -> Self {
54 Self::new("Rate limit exceeded", "rate_limit_error")
55 }
56
57 pub fn server_error(message: impl Into<String>) -> Self {
59 Self::new(message, "server_error")
60 }
61}
62
63pub fn normalize_error(status: u16, message: impl Into<String>) -> ErrorResponse {
65 let message = message.into();
66 match status {
67 400 => ErrorResponse::invalid_request(message),
68 401 => ErrorResponse::authentication_error(),
69 429 => ErrorResponse::rate_limit_error(),
70 _ => ErrorResponse::server_error(message),
71 }
72}
73
74impl std::fmt::Display for ErrorResponse {
75 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
76 write!(f, "{}: {}", self.error.r#type, self.error.message)
77 }
78}
79
80impl std::error::Error for ErrorResponse {}