use std::error;
use std::fmt;
#[derive(Debug, Serialize)]
pub struct ErrorResponse {
status_code: u16,
message: String,
#[serde(skip_serializing)]
source: Option<Box<dyn error::Error>>,
}
impl ErrorResponse {
pub fn new(status_code: u16, message: &str) -> Self {
Self {
status_code,
message: message.to_string(),
source: None,
}
}
pub fn internal_error(source: Box<dyn error::Error>) -> Self {
Self {
status_code: 500,
message: "An internal error occurred".to_string(),
source: Some(source),
}
}
pub fn status_code(&self) -> u16 {
self.status_code
}
pub fn message(&self) -> &str {
&self.message
}
}
impl error::Error for ErrorResponse {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
self.source.as_ref().map(|s| s.as_ref())
}
}
impl fmt::Display for ErrorResponse {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(ref src) = self.source {
write!(f, "{}", src)
} else {
write!(
f,
"Status Code {}: Message {}",
self.status_code, self.message
)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::Deserialize;
use serde_json::Result;
#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
struct Response {
status_code: u16,
message: String,
}
#[test]
fn test_error_response_internal_error_display() {
let error = "NaN".parse::<u32>().unwrap_err();
let response = ErrorResponse::internal_error(Box::new(error));
assert_eq!(response.to_string(), "invalid digit found in string");
}
#[test]
fn test_error_response_new_display() {
let response = ErrorResponse::new(501, "The endpoint is not implemented");
assert_eq!(
response.to_string(),
"Status Code 501: Message The endpoint is not implemented"
);
}
#[test]
fn test_error_response_new_json_serialization() -> Result<()> {
let response = ErrorResponse::new(501, "The endpoint is not implemented");
let json = serde_json::to_string(&response)?;
let deserialized: Response = serde_json::from_str(&json)?;
assert_eq!(deserialized.status_code, 501);
assert_eq!(deserialized.message, "The endpoint is not implemented");
Ok(())
}
#[test]
fn test_error_response_internal_error_json_serialization() -> Result<()> {
let err = "NaN".parse::<u32>().unwrap_err();
let response = ErrorResponse::internal_error(Box::new(err));
let json = serde_json::to_string(&response)?;
let deserialized: Response = serde_json::from_str(&json)?;
assert_eq!(deserialized.status_code, 500);
assert_eq!(deserialized.message, "An internal error occurred");
Ok(())
}
}