use doc::Link;
use http::StatusCode;
use value::{Key, Map};
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Serialize)]
pub struct ErrorObject {
#[serde(skip_serializing_if = "Option::is_none")]
pub code: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub detail: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub links: Map<Key, Link>,
#[serde(default, skip_serializing_if = "Map::is_empty")]
pub meta: Map,
#[serde(skip_serializing_if = "Option::is_none")]
pub source: Option<ErrorSource>,
#[serde(skip_serializing_if = "Option::is_none", with = "serde_status")]
pub status: Option<StatusCode>,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip)]
_ext: (),
}
impl ErrorObject {
pub fn new(status: Option<StatusCode>) -> Self {
let title = status
.and_then(|value| value.canonical_reason())
.map(|reason| reason.to_owned());
ErrorObject {
status,
title,
..Default::default()
}
}
}
#[derive(Clone, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct ErrorSource {
#[serde(skip_serializing_if = "Option::is_none")]
pub parameter: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub pointer: Option<String>,
#[serde(skip)]
_ext: (),
}
impl ErrorSource {
pub fn new(parameter: Option<String>, pointer: Option<String>) -> Self {
ErrorSource {
parameter,
pointer,
_ext: (),
}
}
}
mod serde_status {
use std::fmt::{self, Formatter};
use serde::de::{Deserializer, Error, Visitor};
use serde::ser::Serializer;
use http::StatusCode;
pub fn deserialize<'de, D>(deserializer: D) -> Result<Option<StatusCode>, D::Error>
where
D: Deserializer<'de>,
{
struct StatusVisitor;
impl<'de> Visitor<'de> for StatusVisitor {
type Value = Option<StatusCode>;
fn expecting(&self, f: &mut Formatter) -> fmt::Result {
f.write_str("a string containing a http status code")
}
fn visit_none<E>(self) -> Result<Self::Value, E> {
Ok(None)
}
fn visit_some<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_str(self)
}
fn visit_str<E: Error>(self, value: &str) -> Result<Self::Value, E> {
value.parse().map(Some).map_err(Error::custom)
}
}
deserializer.deserialize_option(StatusVisitor)
}
pub fn serialize<S>(
value: &Option<StatusCode>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match *value {
Some(status) => serializer.serialize_str(status.as_str()),
None => serializer.serialize_none(),
}
}
}