oxigdal_ml_foundation/
error.rs1use thiserror::Error;
4
5pub type Result<T> = core::result::Result<T, Error>;
7
8#[derive(Debug, Error)]
10#[non_exhaustive]
11pub enum Error {
12 #[error("Invalid input dimensions: expected {expected}, got {actual}")]
14 InvalidDimensions {
15 expected: String,
17 actual: String,
19 },
20
21 #[error("Invalid parameter: {name} = {value}, reason: {reason}")]
23 InvalidParameter {
24 name: String,
26 value: String,
28 reason: String,
30 },
31
32 #[error("Model architecture error: {0}")]
34 ModelArchitecture(String),
35
36 #[error("Training error: {0}")]
38 Training(String),
39
40 #[error("Optimizer error: {0}")]
42 Optimizer(String),
43
44 #[error("Loss function error: {0}")]
46 LossFunction(String),
47
48 #[error("Data augmentation error: {0}")]
50 Augmentation(String),
51
52 #[error("Checkpoint I/O error: {0}")]
54 Checkpoint(String),
55
56 #[error("Transfer learning error: {0}")]
58 TransferLearning(String),
59
60 #[error("Metric computation error: {0}")]
62 Metric(String),
63
64 #[error(
66 "Feature not available: {feature}. Enable the '{cargo_feature}' feature to use this functionality"
67 )]
68 FeatureNotAvailable {
69 feature: String,
71 cargo_feature: String,
73 },
74
75 #[error("OxiGDAL core error: {0}")]
77 Core(#[from] oxigdal_core::error::OxiGdalError),
78
79 #[error("Image processing error: {0}")]
81 Image(String),
82
83 #[error("Serialization error: {0}")]
85 Serialization(String),
86
87 #[error("I/O error: {0}")]
89 Io(#[from] std::io::Error),
90
91 #[error("Numerical error: {0}")]
93 Numerical(String),
94
95 #[error("Early stopping triggered: {reason}")]
97 EarlyStopping {
98 reason: String,
100 },
101
102 #[error("Invalid model state: {0}")]
104 InvalidState(String),
105
106 #[error("Backend error: {0}")]
108 Backend(String),
109
110 #[error("Not implemented: {0}")]
112 NotImplemented(String),
113}
114
115impl Error {
116 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 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 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 pub fn numerical(msg: impl Into<String>) -> Self {
150 Self::Numerical(msg.into())
151 }
152
153 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}