|
|
|
use std::fmt;
|
|
|
|
use std::error::Error as StdError;
|
|
|
|
use reqwest::Error as ReqError;
|
|
|
|
use serde::{
|
|
|
|
Serialize,
|
|
|
|
Deserialize
|
|
|
|
};
|
|
|
|
|
|
|
|
pub type BoxError = Box<(dyn StdError + Send + Sync + 'static)>;
|
|
|
|
pub type UResult<T> = std::result::Result<T, UError>;
|
|
|
|
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
|
|
pub enum JobErrType {
|
|
|
|
AlreadyRunning,
|
|
|
|
Finished,
|
|
|
|
System
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
|
|
pub enum UErrType {
|
|
|
|
ConnectionError,
|
|
|
|
ParseError,
|
|
|
|
JobError(JobErrType),
|
|
|
|
Unknown,
|
|
|
|
Raw(String)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
|
|
|
struct Inner {
|
|
|
|
err_type: UErrType,
|
|
|
|
source: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
|
|
pub struct UError {
|
|
|
|
inner: Box<Inner>
|
|
|
|
}
|
|
|
|
|
|
|
|
impl UError {
|
|
|
|
pub fn new(err_type: UErrType, source: String) -> Self {
|
|
|
|
Self {
|
|
|
|
inner: Box::new(Inner {
|
|
|
|
source,
|
|
|
|
err_type
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn new_type(err_type: UErrType) -> Self {
|
|
|
|
UError::new(err_type, String::new())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Debug for UError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
let mut builder = f.debug_struct("errors::UError");
|
|
|
|
builder.field("kind", &self.inner.err_type);
|
|
|
|
builder.field("source", &self.inner.source);
|
|
|
|
builder.finish()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl fmt::Display for UError {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
let e_type = match self.inner.err_type {
|
|
|
|
UErrType::Raw(ref msg) => msg.clone(),
|
|
|
|
UErrType::ConnectionError => "Connection error".to_string(),
|
|
|
|
UErrType::ParseError => "Parse error".to_string(),
|
|
|
|
UErrType::JobError(ref inner) =>
|
|
|
|
(String::from("Job error: ") + match *inner {
|
|
|
|
JobErrType::AlreadyRunning => "job is already running",
|
|
|
|
JobErrType::Finished => "once-scheduled job is already finished",
|
|
|
|
JobErrType::System => "system error"
|
|
|
|
}),
|
|
|
|
UErrType::Unknown => "Unknown error".to_string(),
|
|
|
|
};
|
|
|
|
f.write_str(&e_type)?;
|
|
|
|
|
|
|
|
write!(f, ": {}", self.inner.source)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl From<ReqError> for UError {
|
|
|
|
fn from(e: ReqError) -> Self {
|
|
|
|
let err_type = if e.is_request() {
|
|
|
|
UErrType::ConnectionError
|
|
|
|
} else if e.is_decode() {
|
|
|
|
UErrType::ParseError
|
|
|
|
} else {
|
|
|
|
UErrType::Unknown
|
|
|
|
};
|
|
|
|
UError::new(err_type, e.to_string())
|
|
|
|
}
|
|
|
|
}
|