aboutsummaryrefslogtreecommitdiff
path: root/src/error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/error.rs')
-rw-r--r--src/error.rs96
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
+ }
+ }
+}