use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ErrorResponse {
pub code: ErrorCode,
pub message: String,
}
impl ErrorResponse {
pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
Self {
code,
message: message.into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ErrorCode {
BadRequest,
Unauthorized,
PayloadTooLarge,
UnsupportedTarget,
RenderFailed,
Internal,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn error_response_round_trips_through_json() {
let err = ErrorResponse::new(ErrorCode::RenderFailed, "typst: unclosed delimiter");
let json = serde_json::to_string(&err).unwrap();
assert_eq!(
json,
r#"{"code":"render_failed","message":"typst: unclosed delimiter"}"#
);
assert_eq!(serde_json::from_str::<ErrorResponse>(&json).unwrap(), err);
}
#[test]
fn error_codes_serialize_snake_case() {
for (code, expected) in [
(ErrorCode::BadRequest, "\"bad_request\""),
(ErrorCode::Unauthorized, "\"unauthorized\""),
(ErrorCode::PayloadTooLarge, "\"payload_too_large\""),
(ErrorCode::UnsupportedTarget, "\"unsupported_target\""),
(ErrorCode::RenderFailed, "\"render_failed\""),
(ErrorCode::Internal, "\"internal\""),
] {
let json = serde_json::to_string(&code).unwrap();
assert_eq!(json, expected);
assert_eq!(serde_json::from_str::<ErrorCode>(&json).unwrap(), code);
}
}
}