From 5f2466e463edcf6d161f9ba6371eaf7afc3549e3 Mon Sep 17 00:00:00 2001 From: Gus Power Date: Thu, 15 May 2025 15:18:39 +0100 Subject: construct full config, use Args to load it --- src/error.rs | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 src/error.rs (limited to 'src/error.rs') 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 = Result; +#[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) -> Self { + match self { + Self::ConfigParseError { source, .. } => Self::ConfigParseError { + source, + path: path.into(), + }, + err => err, + } + } + + pub fn with_url(self, url: impl Into) -> 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 for AppError { + fn from(err: io::Error) -> Self { + Self::IoError(err) + } +} + +impl From 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 for AppError { + fn from(err: JsonError) -> Self { + Self::ConfigParseError { + source: err, + path: PathBuf::from("unknown"), // Default path + } + } +} -- cgit v1.2.3