iskra 0.6.0

A safe, modern, Rust-native data transfer tool.
Documentation
use thiserror::Error;
use std::io;

/// The main error type for Iskra, representing all possible error cases.
#[derive(Error, Debug)]
pub enum IskraError {
    /// HTTP client error (network, protocol, etc.)
    #[error("HTTP error: {source} (url: {url})")]
    Http {
        source: reqwest::Error,
        url: String,
    },
    /// HTTP status error (non-success)
    #[error("HTTP status error: {status} (url: {url})")]
    Status {
        status: u16,
        url: String,
    },
    /// IO error (filesystem, etc.)
    #[error("IO error: {source} (path: {path})")]
    Io {
        source: io::Error,
        path: String,
    },
    /// Cache error (corrupt, IO, etc.)
    #[error("Cache error: {msg} (key: {key})")]
    Cache {
        msg: String,
        key: String,
    },
    /// Configuration or argument error
    #[error("Config error: {msg}")]
    Config {
        msg: String,
    },
    /// Timeout error
    #[error("Timeout error: {operation} (timeout: {timeout_secs}s)")]
    Timeout {
        operation: String,
        timeout_secs: u64,
    },
    /// Any other error
    #[error("Other error: {0}")]
    Other(String),
}

impl IskraError {
    /// Print a detailed error report to stderr.
    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}");
            }
        }
        // Print error chain
        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; }
        }
        // Optionally, print debug info for advanced users
        #[cfg(debug_assertions)]
        eprintln!("[Debug] {:#?}", self);
    }
}