use http::StatusCode;
use http_api_problem::{ApiError, ApiErrorBuilder};
use iri_string::types::UriReferenceString;
use super::{Problem, ProblemBuilder};
pub struct ProblemType {
pub id: UriReferenceString,
pub title: String,
}
pub type LazyStaticProblemType = once_cell::sync::Lazy<ProblemType>;
impl ProblemType {
#[cfg(feature = "anon-problem-type")]
pub fn new_anonymous(title: impl Into<String>) -> Self {
Self {
id: format!("urn::dyn_problem::_anon/{}", uuid::Uuid::new_v4())
.parse()
.expect("Must be a valid urm."),
title: title.into(),
}
}
#[inline]
pub fn new_problem(&self) -> Problem {
self.new_problem_builder().finish()
}
#[inline]
pub fn new_problem_builder(&self) -> ProblemBuilder {
Problem::builder()
.type_url(self.id.to_string())
.title(self.title.clone())
}
#[inline]
pub fn new_api_error_builder(&self, status: StatusCode) -> ApiErrorBuilder {
ApiError::builder(status)
.type_url(self.id.to_string())
.title(self.title.clone())
}
#[inline]
pub fn is_type_of(&self, e: &Problem) -> bool {
e.type_url()
.map(|type_url| self.id.as_str() == type_url)
.unwrap_or(false)
}
#[inline]
pub fn is_type_of_api_err(&self, e: &ApiError) -> bool {
e.type_url()
.map(|type_url| self.id.as_str() == type_url)
.unwrap_or(false)
}
}
#[macro_export(local_inner_macros)]
#[cfg(feature = "anon-problem-type")]
macro_rules! define_anon_problem_types {
(
$($(#[$outer:meta])*$PROBLEM:ident: ($title:expr);)*
) => {
$(
#[allow(missing_docs)]
$(#[$outer])*
pub static $PROBLEM: $crate::type_::LazyStaticProblemType = $crate::type_::LazyStaticProblemType::new(|| {
$crate::type_::ProblemType::new_anonymous($title)
});
)*
};
}
define_anon_problem_types!(
INTERNAL_ERROR: ("Internal error");
UNKNOWN_IO_ERROR: (
"Unknown io error."
);
INFALLIBLE: ("Infallible.");
);