use http::StatusCode;
use topcoat_core::{context::Cx, error::Result};
use crate::response::{IntoResponse, Response};
pub fn bad_request(description: impl Into<String>) -> BadRequestError {
BadRequestError::new(None, description.into())
}
pub fn bad_request_at(
path: impl std::fmt::Display,
description: impl Into<String>,
) -> BadRequestError {
let path = path.to_string();
let description = description.into();
BadRequestError::new(Some(path), description)
}
#[derive(Debug, Clone)]
pub struct BadRequestError {
path: Option<String>,
description: String,
}
impl BadRequestError {
fn new(path: Option<String>, description: String) -> Self {
Self { path, description }
}
#[must_use]
pub fn path(&self) -> Option<&str> {
self.path.as_deref()
}
#[must_use]
pub fn description(&self) -> &str {
&self.description
}
}
impl std::fmt::Display for BadRequestError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match &self.path {
Some(path) => write!(f, "bad request: {} (at `{path}`)", self.description),
None => write!(f, "bad request: {}", self.description),
}
}
}
impl std::error::Error for BadRequestError {}
impl IntoResponse for BadRequestError {
fn into_response(self, cx: &Cx) -> Result<Response> {
(StatusCode::BAD_REQUEST, self.to_string()).into_response(cx)
}
}