Skip to main content

thrust/
error.rs

1//! Custom error types for thrust.
2//!
3//! This module provides a unified error type for all thrust operations,
4//! replacing generic `Box<dyn std::error::Error>` with a concrete enum
5//! that enables better error handling, logging, and debugging.
6
7use std::fmt;
8
9/// A unified error type for thrust operations.
10///
11/// This enum represents all possible error conditions that can occur
12/// when parsing aviation data, querying databases, or performing I/O operations.
13///
14/// # Examples
15///
16/// ```rust
17/// use thrust::ThrustError;
18///
19/// let err = ThrustError::ParseError("Invalid altitude format".to_string());
20/// assert!(matches!(err, ThrustError::ParseError(_)));
21/// ```
22#[derive(Debug, Clone)]
23pub enum ThrustError {
24    /// Parsing error with descriptive message
25    ParseError(String),
26
27    /// File not found or inaccessible
28    FileNotFound(String),
29
30    /// Invalid or corrupted data
31    InvalidData(String),
32
33    /// I/O error (read, write, seek, etc.)
34    Io(String),
35
36    /// ZIP file processing error
37    ZipError(String),
38
39    /// XML parsing or validation error
40    XmlError(String),
41
42    /// CSV parsing error
43    CsvError(String),
44
45    /// HTTP/network error
46    NetworkError(String),
47
48    /// Database operation error
49    DatabaseError(String),
50
51    /// Missing required field or data
52    MissingField(String),
53
54    /// Generic error with context
55    Other(String),
56}
57
58impl fmt::Display for ThrustError {
59    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
60        match self {
61            Self::ParseError(msg) => write!(f, "Parse error: {}", msg),
62            Self::FileNotFound(msg) => write!(f, "File not found: {}", msg),
63            Self::InvalidData(msg) => write!(f, "Invalid data: {}", msg),
64            Self::Io(msg) => write!(f, "I/O error: {}", msg),
65            Self::ZipError(msg) => write!(f, "ZIP error: {}", msg),
66            Self::XmlError(msg) => write!(f, "XML error: {}", msg),
67            Self::CsvError(msg) => write!(f, "CSV error: {}", msg),
68            Self::NetworkError(msg) => write!(f, "Network error: {}", msg),
69            Self::DatabaseError(msg) => write!(f, "Database error: {}", msg),
70            Self::MissingField(msg) => write!(f, "Missing field: {}", msg),
71            Self::Other(msg) => write!(f, "Error: {}", msg),
72        }
73    }
74}
75
76impl std::error::Error for ThrustError {}
77
78// Conversion implementations for common error types
79
80impl From<std::io::Error> for ThrustError {
81    fn from(e: std::io::Error) -> Self {
82        Self::Io(e.to_string())
83    }
84}
85
86impl From<csv::Error> for ThrustError {
87    fn from(e: csv::Error) -> Self {
88        Self::CsvError(e.to_string())
89    }
90}
91
92impl From<zip::result::ZipError> for ThrustError {
93    fn from(e: zip::result::ZipError) -> Self {
94        Self::ZipError(e.to_string())
95    }
96}
97
98impl From<serde_json::Error> for ThrustError {
99    fn from(e: serde_json::Error) -> Self {
100        Self::InvalidData(e.to_string())
101    }
102}
103
104impl From<chrono::ParseError> for ThrustError {
105    fn from(e: chrono::ParseError) -> Self {
106        Self::ParseError(e.to_string())
107    }
108}
109
110impl From<quick_xml::Error> for ThrustError {
111    fn from(e: quick_xml::Error) -> Self {
112        Self::XmlError(e.to_string())
113    }
114}
115
116impl From<std::str::Utf8Error> for ThrustError {
117    fn from(e: std::str::Utf8Error) -> Self {
118        Self::ParseError(e.to_string())
119    }
120}
121
122impl From<std::num::ParseFloatError> for ThrustError {
123    fn from(e: std::num::ParseFloatError) -> Self {
124        Self::ParseError(e.to_string())
125    }
126}
127
128// For quick_xml attribute errors
129impl From<quick_xml::events::attributes::AttrError> for ThrustError {
130    fn from(e: quick_xml::events::attributes::AttrError) -> Self {
131        Self::XmlError(e.to_string())
132    }
133}
134
135#[cfg(feature = "net")]
136impl From<reqwest::Error> for ThrustError {
137    fn from(e: reqwest::Error) -> Self {
138        Self::NetworkError(e.to_string())
139    }
140}
141
142impl From<&str> for ThrustError {
143    fn from(e: &str) -> Self {
144        Self::Other(e.to_string())
145    }
146}
147
148impl From<String> for ThrustError {
149    fn from(e: String) -> Self {
150        Self::Other(e)
151    }
152}