use chrono::format::ParseError;
use reqwest::Error as ReqwestError;
use serde_json::Error as JsonError;
use std::error::Error as StdError;
use std::fmt::Display;
use std::io::Error as IoError;
pub type Result<T> = ::std::result::Result<T, Error>;
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum ToornamentErrorType {
EmailDuplicate,
MatchIntegrity,
}
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum ToornamentErrorScope {
Query,
Body,
}
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct ToornamentError {
pub message: String,
pub scope: ToornamentErrorScope,
pub property_path: Option<String>,
pub invalid_value: Option<String>,
#[serde(rename = "type")]
pub error_type: Option<ToornamentErrorType>,
}
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct ToornamentErrors(pub Vec<ToornamentError>);
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct ToornamentServiceError {
pub errors: ToornamentErrors,
}
#[derive(Debug, Clone)]
pub enum IterError {
NoSuchTournament(::TournamentId),
NoTournamentId(Box<::Tournament>),
NoSuchMatch(::TournamentId, ::MatchId),
NoPermissionId,
NoSuchDiscipline(::DisciplineId),
}
impl Display for IterError {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
let s;
match *self {
IterError::NoSuchTournament(ref id) => {
s = format!("A tournament with id ({}) does not exist", id.0);
}
IterError::NoTournamentId(_) => {
s = "A tournament does not have an id set.".to_owned();
}
IterError::NoSuchMatch(ref t_id, ref m_id) => {
s = format!(
"A match does not exist (tournament id = {}, match id = {})",
t_id.0, m_id.0
);
}
IterError::NoPermissionId => {
s = "A permission does not have an id set.".to_owned();
}
IterError::NoSuchDiscipline(ref id) => {
s = format!("A permission with id ({}) does not exist.", id.0);
}
};
fmt.write_str(&s)
}
}
#[derive(Debug)]
pub enum Error {
Reqwest(ReqwestError),
Json(JsonError),
Io(IoError),
Date(ParseError),
Toornament(::reqwest::StatusCode, ToornamentServiceError),
Status(::reqwest::StatusCode),
RateLimited(u64),
Iter(IterError),
Rest(&'static str),
}
impl From<::reqwest::blocking::Response> for Error {
fn from(response: ::reqwest::blocking::Response) -> Error {
#[derive(Deserialize)]
struct TooManyRequests {
retry_after: u64,
}
let status = response.status();
if status == ::reqwest::StatusCode::TOO_MANY_REQUESTS {
if let Ok(value) = response.json::<TooManyRequests>() {
return Error::RateLimited(value.retry_after);
}
} else if !status.is_success() {
if let Ok(e) = response.json::<ToornamentServiceError>() {
return Error::Toornament(status, e);
}
}
Error::Status(status)
}
}
impl From<IoError> for Error {
fn from(err: IoError) -> Error {
Error::Io(err)
}
}
impl From<ReqwestError> for Error {
fn from(err: ReqwestError) -> Error {
Error::Reqwest(err)
}
}
impl From<JsonError> for Error {
fn from(err: JsonError) -> Error {
Error::Json(err)
}
}
impl From<ParseError> for Error {
fn from(err: ParseError) -> Error {
Error::Date(err)
}
}
impl Display for Error {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match *self {
Error::Reqwest(ref inner) => inner.fmt(f),
Error::Json(ref inner) => inner.fmt(f),
Error::Io(ref inner) => inner.fmt(f),
Error::Date(ref inner) => inner.fmt(f),
_ => f.write_str(&self.to_string()),
}
}
}
impl StdError for Error {
fn cause(&self) -> Option<&dyn StdError> {
match *self {
Error::Reqwest(ref inner) => Some(inner),
Error::Json(ref inner) => Some(inner),
Error::Io(ref inner) => Some(inner),
Error::Date(ref inner) => Some(inner),
_ => None,
}
}
}