diff options
Diffstat (limited to 'src/error.rs')
| -rw-r--r-- | src/error.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 0000000..d7bbfaf --- /dev/null +++ b/src/error.rs @@ -0,0 +1,96 @@ +use std::fmt; +use std::io; +use std::path::PathBuf; +use reqwest::Error as ReqwestError; +use serde_json::Error as JsonError; + +pub type AppResult<T> = Result<T, AppError>; +#[derive(Debug)] +pub enum AppError { + FileNotFound(PathBuf), + IoError(io::Error), + ConfigParseError { source: JsonError, path: PathBuf }, + RequestFailed { url: String, source: ReqwestError }, + InvalidResponse { url: String, reason: String }, + Timeout { url: String }, +} + +impl AppError { + pub fn with_path(self, path: impl Into<PathBuf>) -> Self { + match self { + Self::ConfigParseError { source, .. } => Self::ConfigParseError { + source, + path: path.into(), + }, + err => err, + } + } + + pub fn with_url(self, url: impl Into<String>) -> Self { + match self { + Self::RequestFailed { source, .. } => Self::RequestFailed { + source, + url: url.into(), + }, + Self::InvalidResponse { reason, .. } => Self::InvalidResponse { + reason, + url: url.into(), + }, + Self::Timeout { .. } => Self::Timeout { + url: url.into(), + }, + err => err, + } + } +} + +impl fmt::Display for AppError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::FileNotFound(path) => write!(f, "File not found: {}", path.display()), + Self::IoError(err) => write!(f, "I/O error: {}", err), + Self::ConfigParseError { path, .. } => write!(f, "Failed to parse config at {}", path.display()), + Self::RequestFailed { url, .. } => write!(f, "Request to {} failed", url), + Self::InvalidResponse { url, reason } => { + write!(f, "Invalid response from {}: {}", url, reason) + } + Self::Timeout { url } => write!(f, "Request to {} timed out", url), + } + } +} + +impl std::error::Error for AppError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + Self::IoError(err) => Some(err), + Self::ConfigParseError { source, .. } => Some(source), + Self::RequestFailed { source, .. } => Some(source), + _ => None, + } + } +} + +// Convenient conversions from library errors +impl From<io::Error> for AppError { + fn from(err: io::Error) -> Self { + Self::IoError(err) + } +} + +impl From<ReqwestError> for AppError { + fn from(err: ReqwestError) -> Self { + Self::RequestFailed { + url: err.url().map_or_else(|| "unknown".to_string(), |u| u.to_string()), + source: err, + } + } +} + +impl From<JsonError> for AppError { + fn from(err: JsonError) -> Self { + Self::ConfigParseError { + source: err, + path: PathBuf::from("unknown"), // Default path + } + } +} |
