use thiserror::Error;
use std::io;
#[derive(Error, Debug)]
pub enum IskraError {
#[error("HTTP error: {source} (url: {url})")]
Http {
source: reqwest::Error,
url: String,
},
#[error("HTTP status error: {status} (url: {url})")]
Status {
status: u16,
url: String,
},
#[error("IO error: {source} (path: {path})")]
Io {
source: io::Error,
path: String,
},
#[error("Cache error: {msg} (key: {key})")]
Cache {
msg: String,
key: String,
},
#[error("Config error: {msg}")]
Config {
msg: String,
},
#[error("Timeout error: {operation} (timeout: {timeout_secs}s)")]
Timeout {
operation: String,
timeout_secs: u64,
},
#[error("Other error: {0}")]
Other(String),
}
impl IskraError {
pub fn print_report(&self) {
use std::error::Error;
eprintln!("\x1b[1;31mIskra Error:\x1b[0m {self}");
match self {
IskraError::Http { source, url } => {
eprintln!(" Type: HTTP client/network error");
eprintln!(" URL: {url}");
eprintln!(" Reqwest: {source}");
if source.is_timeout() {
eprintln!(" Suggestion: Check your network connection or increase --timeout.");
}
}
IskraError::Status { status, url } => {
eprintln!(" Type: HTTP status error");
eprintln!(" URL: {url}");
eprintln!(" Status: {status}");
if *status == 404 {
eprintln!(" Suggestion: Check the URL for typos or missing resources.");
} else if *status >= 500 {
eprintln!(" Suggestion: The server may be down or experiencing issues.");
}
}
IskraError::Io { source, path } => {
eprintln!(" Type: Filesystem/IO error");
eprintln!(" Path: {path}");
eprintln!(" IO: {source}");
}
IskraError::Cache { msg, key } => {
eprintln!(" Type: Cache error");
eprintln!(" Key: {key}");
eprintln!(" Msg: {msg}");
}
IskraError::Config { msg } => {
eprintln!(" Type: Configuration error");
eprintln!(" Msg: {msg}");
}
IskraError::Timeout { operation, timeout_secs } => {
eprintln!(" Type: Timeout error");
eprintln!(" Operation: {operation}");
eprintln!(" Timeout: {timeout_secs}s");
eprintln!(" Suggestion: Try increasing --timeout or check your network.");
}
IskraError::Other(msg) => {
eprintln!(" Type: Other error");
eprintln!(" Msg: {msg}");
}
}
let mut source = self.source();
let mut depth = 0;
if source.is_some() {
eprintln!(" Error chain:");
}
while let Some(err) = source {
eprintln!(" {err}");
source = err.source();
depth += 1;
if depth > 8 { break; }
}
#[cfg(debug_assertions)]
eprintln!("[Debug] {:#?}", self);
}
}