use http::StatusCode;
use std::sync::Arc;
#[derive(Debug, Clone, Copy, thiserror::Error)]
#[error("deserialization produced no value")]
pub(crate) struct DeserializationProducedNoValue;
#[derive(Debug, Clone, thiserror::Error)]
pub enum NegotiationError {
#[error("no acceptable response format found (requested: {requested}; supported: {supported})")]
NotAcceptable {
requested: Arc<str>,
supported: Arc<str>,
},
#[error("request content-type not supported (provided: {provided}; supported: {supported})")]
UnsupportedMediaType {
provided: Arc<str>,
supported: Arc<str>,
},
#[error("serialization failed: {0}")]
Serialization(Arc<dyn std::error::Error + Send + Sync>),
#[error("deserialization failed: {0}")]
Deserialization(Arc<dyn std::error::Error + Send + Sync>),
#[error("failed to collect response body: {0}")]
BodyCollection(Arc<dyn std::error::Error + Send + Sync>),
}
impl NegotiationError {
pub fn status_code(&self) -> StatusCode {
match self {
Self::NotAcceptable { .. } => StatusCode::NOT_ACCEPTABLE,
Self::UnsupportedMediaType { .. } => StatusCode::UNSUPPORTED_MEDIA_TYPE,
Self::Serialization(_) | Self::Deserialization(_) | Self::BodyCollection(_) => {
StatusCode::INTERNAL_SERVER_ERROR
}
}
}
pub fn not_acceptable(requested: Option<&str>, supported: &[String]) -> Self {
Self::NotAcceptable {
requested: requested.unwrap_or("none provided").into(),
supported: supported.join(", ").into(),
}
}
pub fn unsupported_media_type(provided: Option<&str>, supported: &[String]) -> Self {
Self::UnsupportedMediaType {
provided: provided.unwrap_or("none provided").into(),
supported: supported.join(", ").into(),
}
}
pub fn serialization(err: impl std::error::Error + Send + Sync + 'static) -> Self {
Self::Serialization(Arc::new(err))
}
pub fn deserialization(err: impl std::error::Error + Send + Sync + 'static) -> Self {
Self::Deserialization(Arc::new(err))
}
pub fn body_collection(err: impl std::error::Error + Send + Sync + 'static) -> Self {
Self::BodyCollection(Arc::new(err))
}
pub(crate) fn deserialization_produced_no_value() -> Self {
Self::Deserialization(Arc::new(DeserializationProducedNoValue))
}
}