ferrous_forge/
error.rs

1//! Error handling for Ferrous Forge
2//!
3//! This module provides a unified error handling system for all Ferrous Forge operations.
4
5/// Ferrous Forge specific errors
6#[derive(Debug, thiserror::Error)]
7pub enum Error {
8    /// IO errors (file operations, etc.)
9    #[error("IO error: {0}")]
10    Io(#[from] std::io::Error),
11
12    /// Configuration errors
13    #[error("Configuration error: {0}")]
14    Config(String),
15
16    /// Validation errors
17    #[error("Validation error: {0}")]
18    Validation(String),
19
20    /// Template errors
21    #[error("Template error: {0}")]
22    Template(String),
23
24    /// Update system errors
25    #[error("Update error: {0}")]
26    Update(String),
27
28    /// Standards enforcement errors
29    #[error("Standards violation: {0}")]
30    Standards(String),
31
32    /// CLI argument errors
33    #[error("CLI error: {0}")]
34    Cli(String),
35
36    /// External process errors
37    #[error("Process error: {0}")]
38    Process(String),
39
40    /// Serialization errors
41    #[error("Serialization error: {0}")]
42    Serialization(#[from] serde_json::Error),
43
44    /// TOML parsing errors
45    #[error("TOML error: {0}")]
46    Toml(#[from] toml::de::Error),
47
48    /// Network/HTTP errors
49    #[error("Network error: {0}")]
50    Network(String),
51
52    /// Semver parsing errors
53    #[error("Version error: {0}")]
54    Version(#[from] semver::Error),
55
56    /// Parse errors
57    #[error("Parse error: {0}")]
58    Parse(String),
59
60    /// Rust not found
61    #[error("Rust not found: {0}")]
62    RustNotFound(String),
63
64    /// Command execution error
65    #[error("Command error: {0}")]
66    Command(String),
67
68    /// File not found
69    #[error("File not found: {0}")]
70    FileNotFound(String),
71
72    /// Rate limited
73    #[error("Rate limited: retry after {0} seconds")]
74    RateLimited(u64),
75
76    /// Migration error
77    #[error("Migration error: {0}")]
78    Migration(String),
79
80    /// Regex error
81    #[error("Regex error: {0}")]
82    Regex(#[from] regex::Error),
83
84    /// UTF-8 conversion error
85    #[error("UTF-8 error: {0}")]
86    Utf8(#[from] std::str::Utf8Error),
87
88    /// Safety pipeline error
89    #[error("Safety error: {0}")]
90    Safety(String),
91
92    /// Safety pipeline blocked operation
93    #[error("Safety blocked: {0}")]
94    SafetyBlocked(String),
95}
96
97/// Result type alias for Ferrous Forge operations
98pub type Result<T> = std::result::Result<T, Error>;
99
100impl Error {
101    /// Create a new configuration error
102    pub fn config(msg: impl Into<String>) -> Self {
103        Self::Config(msg.into())
104    }
105
106    /// Create a new validation error
107    pub fn validation(msg: impl Into<String>) -> Self {
108        Self::Validation(msg.into())
109    }
110
111    /// Create a new template error
112    pub fn template(msg: impl Into<String>) -> Self {
113        Self::Template(msg.into())
114    }
115
116    /// Create a new update error
117    pub fn update(msg: impl Into<String>) -> Self {
118        Self::Update(msg.into())
119    }
120
121    /// Create a new standards error
122    pub fn standards(msg: impl Into<String>) -> Self {
123        Self::Standards(msg.into())
124    }
125
126    /// Create a new CLI error
127    pub fn cli(msg: impl Into<String>) -> Self {
128        Self::Cli(msg.into())
129    }
130
131    /// Create a new process error
132    pub fn process(msg: impl Into<String>) -> Self {
133        Self::Process(msg.into())
134    }
135
136    /// Create a new parse error
137    pub fn parse(msg: impl Into<String>) -> Self {
138        Self::Parse(msg.into())
139    }
140
141    /// Create a new rust not found error
142    pub fn rust_not_found(msg: impl Into<String>) -> Self {
143        Self::RustNotFound(msg.into())
144    }
145
146    /// Create a new command error
147    pub fn command(msg: impl Into<String>) -> Self {
148        Self::Command(msg.into())
149    }
150
151    /// Create a new file not found error
152    pub fn file_not_found(msg: impl Into<String>) -> Self {
153        Self::FileNotFound(msg.into())
154    }
155
156    /// Create a new rate limited error
157    pub fn rate_limited(retry_after: u64) -> Self {
158        Self::RateLimited(retry_after)
159    }
160
161    /// Create a new IO error from a string
162    pub fn io(msg: impl Into<String>) -> Self {
163        Self::Io(std::io::Error::other(msg.into()))
164    }
165
166    /// Create a new security error
167    pub fn security(msg: impl Into<String>) -> Self {
168        Self::Validation(format!("Security: {}", msg.into()))
169    }
170
171    /// Create a new migration error
172    pub fn migration(msg: impl Into<String>) -> Self {
173        Self::Migration(msg.into())
174    }
175
176    /// Create a new network error
177    pub fn network(msg: impl Into<String>) -> Self {
178        Self::Network(msg.into())
179    }
180
181    /// Create a new safety error
182    pub fn safety(msg: impl Into<String>) -> Self {
183        Self::Safety(msg.into())
184    }
185
186    /// Create a new safety blocked error
187    pub fn safety_blocked(msg: impl Into<String>) -> Self {
188        Self::SafetyBlocked(msg.into())
189    }
190
191    /// Create a new tool not found error
192    pub fn tool_not_found(tool: impl Into<String>) -> Self {
193        Self::Process(format!("Tool not found: {}", tool.into()))
194    }
195}
196
197/// Convert anyhow errors to our error type
198impl From<anyhow::Error> for Error {
199    fn from(err: anyhow::Error) -> Self {
200        Self::Process(err.to_string())
201    }
202}
203
204/// Convert reqwest errors to our error type
205impl From<reqwest::Error> for Error {
206    fn from(err: reqwest::Error) -> Self {
207        Self::Network(err.to_string())
208    }
209}