Skip to main content

oxigdal_ml_foundation/
error.rs

1//! Error types for ML foundation operations.
2
3use thiserror::Error;
4
5/// Result type for ML foundation operations.
6pub type Result<T> = core::result::Result<T, Error>;
7
8/// Error types for ML foundation operations.
9#[derive(Debug, Error)]
10#[non_exhaustive]
11pub enum Error {
12    /// Invalid input dimensions
13    #[error("Invalid input dimensions: expected {expected}, got {actual}")]
14    InvalidDimensions {
15        /// Expected dimension description
16        expected: String,
17        /// Actual dimension found
18        actual: String,
19    },
20
21    /// Invalid parameter value
22    #[error("Invalid parameter: {name} = {value}, reason: {reason}")]
23    InvalidParameter {
24        /// Parameter name
25        name: String,
26        /// Parameter value
27        value: String,
28        /// Reason for invalidity
29        reason: String,
30    },
31
32    /// Model architecture error
33    #[error("Model architecture error: {0}")]
34    ModelArchitecture(String),
35
36    /// Training error
37    #[error("Training error: {0}")]
38    Training(String),
39
40    /// Optimizer error
41    #[error("Optimizer error: {0}")]
42    Optimizer(String),
43
44    /// Loss function error
45    #[error("Loss function error: {0}")]
46    LossFunction(String),
47
48    /// Data augmentation error
49    #[error("Data augmentation error: {0}")]
50    Augmentation(String),
51
52    /// Checkpoint I/O error
53    #[error("Checkpoint I/O error: {0}")]
54    Checkpoint(String),
55
56    /// Transfer learning error
57    #[error("Transfer learning error: {0}")]
58    TransferLearning(String),
59
60    /// Metric computation error
61    #[error("Metric computation error: {0}")]
62    Metric(String),
63
64    /// Feature not available
65    #[error(
66        "Feature not available: {feature}. Enable the '{cargo_feature}' feature to use this functionality"
67    )]
68    FeatureNotAvailable {
69        /// Feature name that is not available
70        feature: String,
71        /// Cargo feature required to enable this functionality
72        cargo_feature: String,
73    },
74
75    /// OxiGDAL core error
76    #[error("OxiGDAL core error: {0}")]
77    Core(#[from] oxigdal_core::error::OxiGdalError),
78
79    /// Image processing error
80    #[error("Image processing error: {0}")]
81    Image(String),
82
83    /// Serialization/deserialization error
84    #[error("Serialization error: {0}")]
85    Serialization(String),
86
87    /// I/O error
88    #[error("I/O error: {0}")]
89    Io(#[from] std::io::Error),
90
91    /// Numerical error (overflow, underflow, NaN, etc.)
92    #[error("Numerical error: {0}")]
93    Numerical(String),
94
95    /// Early stopping triggered
96    #[error("Early stopping triggered: {reason}")]
97    EarlyStopping {
98        /// Reason for early stopping
99        reason: String,
100    },
101
102    /// Invalid model state
103    #[error("Invalid model state: {0}")]
104    InvalidState(String),
105
106    /// Backend error
107    #[error("Backend error: {0}")]
108    Backend(String),
109
110    /// Not implemented
111    #[error("Not implemented: {0}")]
112    NotImplemented(String),
113}
114
115impl Error {
116    /// Creates an invalid dimensions error.
117    pub fn invalid_dimensions(expected: impl Into<String>, actual: impl Into<String>) -> Self {
118        Self::InvalidDimensions {
119            expected: expected.into(),
120            actual: actual.into(),
121        }
122    }
123
124    /// Creates an invalid parameter error.
125    pub fn invalid_parameter(
126        name: impl Into<String>,
127        value: impl std::fmt::Display,
128        reason: impl Into<String>,
129    ) -> Self {
130        Self::InvalidParameter {
131            name: name.into(),
132            value: value.to_string(),
133            reason: reason.into(),
134        }
135    }
136
137    /// Creates a feature not available error.
138    pub fn feature_not_available(
139        feature: impl Into<String>,
140        cargo_feature: impl Into<String>,
141    ) -> Self {
142        Self::FeatureNotAvailable {
143            feature: feature.into(),
144            cargo_feature: cargo_feature.into(),
145        }
146    }
147
148    /// Creates a numerical error.
149    pub fn numerical(msg: impl Into<String>) -> Self {
150        Self::Numerical(msg.into())
151    }
152
153    /// Creates an early stopping error.
154    pub fn early_stopping(reason: impl Into<String>) -> Self {
155        Self::EarlyStopping {
156            reason: reason.into(),
157        }
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    #[test]
166    fn test_error_messages() {
167        let err = Error::invalid_dimensions("[32, 3, 224, 224]", "[32, 3, 256, 256]");
168        assert!(err.to_string().contains("expected"));
169
170        let err = Error::invalid_parameter("learning_rate", 0.0, "must be positive");
171        assert!(err.to_string().contains("learning_rate"));
172
173        let err = Error::feature_not_available("PyTorch backend", "pytorch");
174        assert!(err.to_string().contains("pytorch"));
175    }
176}