#![deny(clippy::all, clippy::pedantic)]
#![forbid(unsafe_code)]
#![allow(
clippy::module_name_repetitions,
clippy::unused_async,
clippy::unused_self
)]
#[cfg(feature = "axum")]
mod axum;
use std::collections::BTreeMap;
use http::StatusCode;
use serde_json::Value;
#[allow(dead_code)] pub struct Problem {
pub status_code: StatusCode,
pub body: BTreeMap<String, Value>,
}
#[must_use]
pub fn new<S>(status_code: S) -> Problem
where
S: Into<StatusCode>,
{
Problem {
status_code: status_code.into(),
body: BTreeMap::new(),
}
}
impl Problem {
#[must_use]
pub fn with_type<S>(self, value: S) -> Self
where
S: Into<String>,
{
self.with_value("type", value.into())
}
#[must_use]
pub fn with_title<S>(self, value: S) -> Self
where
S: Into<String>,
{
self.with_value("title", value.into())
}
#[must_use]
pub fn with_detail<S>(self, value: S) -> Self
where
S: Into<String>,
{
self.with_value("detail", value.into())
}
#[must_use]
pub fn with_instance<S>(self, value: S) -> Self
where
S: Into<String>,
{
self.with_value("instance", value.into())
}
#[must_use]
pub fn with_value<V>(mut self, key: &str, value: V) -> Self
where
V: Into<Value>,
{
self.body.insert(key.to_owned(), value.into());
self
}
}
impl<S> From<S> for Problem
where
S: Into<StatusCode>,
{
fn from(status_code: S) -> Self {
new(status_code.into())
}
}
pub type Result<T> = std::result::Result<T, Problem>;