use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(bound(
serialize = "E: serde::Serialize",
deserialize = "E: serde::de::DeserializeOwned"
))]
pub struct ApiErrorBody<E = serde_json::Value> {
pub message: String,
pub status: u16,
pub code: String,
pub error: E,
}
impl<E: Serialize> ApiErrorBody<E> {
pub fn new(status: u16, code: impl Into<String>, message: impl Into<String>, error: E) -> Self {
Self {
message: message.into(),
status,
code: code.into(),
error,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct ProblemDetails {
#[serde(default = "default_type", rename = "type")]
pub type_: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
pub status: u16,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub instance: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
}
fn default_type() -> String {
"about:blank".to_string()
}
impl ProblemDetails {
pub fn new(status: u16) -> Self {
Self {
type_: default_type(),
title: None,
status,
detail: None,
instance: None,
code: None,
}
}
pub fn with_title(mut self, title: impl Into<String>) -> Self {
self.title = Some(title.into());
self
}
pub fn with_detail(mut self, detail: impl Into<String>) -> Self {
self.detail = Some(detail.into());
self
}
pub fn with_code(mut self, code: impl Into<String>) -> Self {
self.code = Some(code.into());
self
}
pub fn with_instance(mut self, instance: impl Into<String>) -> Self {
self.instance = Some(instance.into());
self
}
pub fn with_type(mut self, type_: impl Into<String>) -> Self {
self.type_ = type_.into();
self
}
}