use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde_json;
use std::{
env,
hash::{Hash, Hasher},
};
use thiserror::Error;
use time::error::{ComponentRange, Parse};
#[derive(Error, Debug)]
pub enum AppError {
#[error("DateTime operation error: {0}")]
DateTimeError(#[from] DateTimeError),
#[error("Serialization error: {0}")]
SerializationError(#[from] serde_json::Error),
#[error("General I/O or parsing error: {0}")]
GeneralError(#[from] std::io::Error),
#[error("Other error: {0}")]
Other(String),
#[error("Simulated error")]
SimulatedError,
#[error("Environment variable error: {0}")]
EnvVarError(#[from] env::VarError),
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Error)]
pub enum DateTimeError {
#[error("Invalid date format")]
InvalidFormat,
#[error("Invalid or unsupported timezone; DST not supported")]
InvalidTimezone,
#[error("Invalid date")]
InvalidDate,
#[error("Invalid time")]
InvalidTime,
#[error("Parsing error")]
ParseError(#[from] Parse),
#[error("Component range error")]
ComponentRange(#[from] ComponentRange),
}
impl Hash for DateTimeError {
fn hash<H: Hasher>(&self, state: &mut H) {
std::mem::discriminant(self).hash(state);
}
}
impl Serialize for DateTimeError {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
Self::InvalidFormat => {
serializer.serialize_str("InvalidFormat")
}
Self::InvalidTimezone => {
serializer.serialize_str("InvalidTimezone")
}
Self::InvalidDate => {
serializer.serialize_str("InvalidDate")
}
Self::InvalidTime => {
serializer.serialize_str("InvalidTime")
}
Self::ParseError(_) => {
serializer.serialize_str("ParseError")
}
Self::ComponentRange(_) => {
serializer.serialize_str("ComponentRange")
}
}
}
}
impl<'de> Deserialize<'de> for DateTimeError {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s: &str = Deserialize::deserialize(deserializer)?;
match s {
"InvalidFormat" => Ok(Self::InvalidFormat),
"InvalidTimezone" => Ok(Self::InvalidTimezone),
"InvalidDate" => Ok(Self::InvalidDate),
"InvalidTime" => Ok(Self::InvalidTime),
"ParseError" => Err(serde::de::Error::custom(
"Cannot deserialize ParseError directly",
)),
"ComponentRange" => Err(serde::de::Error::custom(
"Cannot deserialize ComponentRange directly",
)),
_ => Err(serde::de::Error::unknown_variant(
s,
&[
"InvalidFormat",
"InvalidTimezone",
"InvalidDate",
"InvalidTime",
"ParseError",
"ComponentRange",
],
)),
}
}
}
impl Default for DateTimeError {
fn default() -> Self {
Self::InvalidFormat
}
}