Skip to main content

data_gov/
error.rs

1use data_gov_catalog::CatalogError;
2use thiserror::Error;
3
4/// Errors that can occur when using the Data.gov client.
5#[derive(Error, Debug)]
6pub enum DataGovError {
7    /// Error from the underlying Catalog API.
8    #[error("Catalog API error: {0}")]
9    CatalogError(#[from] CatalogError),
10
11    /// HTTP request error.
12    #[error("HTTP request failed: {0}")]
13    HttpError(#[from] reqwest::Error),
14
15    /// File I/O error.
16    #[error("File operation failed: {0}")]
17    IoError(#[from] std::io::Error),
18
19    /// Invalid URL error.
20    #[error("Invalid URL: {0}")]
21    UrlError(#[from] url::ParseError),
22
23    /// Resource not found.
24    #[error("Resource not found: {message}")]
25    ResourceNotFound { message: String },
26
27    /// Download failed.
28    #[error("Download failed: {message}")]
29    DownloadError { message: String },
30
31    /// Invalid resource format.
32    #[error("Invalid resource format: expected {expected}, got {actual}")]
33    InvalidFormat { expected: String, actual: String },
34
35    /// Configuration error.
36    #[error("Configuration error: {message}")]
37    ConfigError { message: String },
38
39    /// Validation error.
40    #[error("Validation error: {message}")]
41    ValidationError { message: String },
42
43    /// Generic error with custom message.
44    #[error("{message}")]
45    Other { message: String },
46}
47
48impl DataGovError {
49    /// Create a new resource not found error.
50    pub fn resource_not_found<S: Into<String>>(message: S) -> Self {
51        Self::ResourceNotFound {
52            message: message.into(),
53        }
54    }
55
56    /// Create a new download error.
57    pub fn download_error<S: Into<String>>(message: S) -> Self {
58        Self::DownloadError {
59            message: message.into(),
60        }
61    }
62
63    /// Create a new configuration error.
64    pub fn config_error<S: Into<String>>(message: S) -> Self {
65        Self::ConfigError {
66            message: message.into(),
67        }
68    }
69
70    /// Create a new validation error.
71    pub fn validation_error<S: Into<String>>(message: S) -> Self {
72        Self::ValidationError {
73            message: message.into(),
74        }
75    }
76
77    /// Create a generic error with a custom message.
78    pub fn other<S: Into<String>>(message: S) -> Self {
79        Self::Other {
80            message: message.into(),
81        }
82    }
83
84    /// Sanitize error message for external consumption.
85    ///
86    /// Removes filesystem paths and other potentially sensitive information.
87    pub fn sanitized_message(&self) -> String {
88        let msg = self.to_string();
89        msg.split_whitespace()
90            .map(|word| {
91                if word.starts_with('/') || word.contains(":\\") || word.starts_with("./") {
92                    "[path]"
93                } else {
94                    word
95                }
96            })
97            .collect::<Vec<_>>()
98            .join(" ")
99    }
100}
101
102/// Type alias for Results using [`DataGovError`].
103pub type Result<T> = std::result::Result<T, DataGovError>;