use thiserror::Error;
#[derive(Error, Debug)]
pub enum TransformError {
#[error("Invalid input: {0}")]
InvalidInput(String),
#[error("Transformation error: {0}")]
TransformationError(String),
#[error("Core error: {0}")]
CoreError(#[from] scirs2_core::error::CoreError),
#[error("Linear algebra error: {0}")]
LinalgError(#[from] scirs2_linalg::error::LinalgError),
#[error("FFT error: {0}")]
FFTError(#[from] scirs2_fft::error::FFTError),
#[error("IO error: {0}")]
IoError(#[from] std::io::Error),
#[error("Computation error: {0}")]
ComputationError(String),
#[error("Model not fitted: {0}")]
NotFitted(String),
#[error("Feature not enabled: {0}")]
FeatureNotEnabled(String),
#[error("GPU error: {0}")]
GpuError(String),
#[error("Distributed processing error: {0}")]
DistributedError(String),
#[error("Monitoring error: {0}")]
MonitoringError(String),
#[error("Memory error: {0}")]
MemoryError(String),
#[error("Convergence error: {0}")]
ConvergenceError(String),
#[error("Data validation error: {0}")]
DataValidationError(String),
#[error("Parallel processing error: {0}")]
ParallelError(String),
#[error("Configuration error: {0}")]
ConfigurationError(String),
#[error("Timeout error: {0}")]
TimeoutError(String),
#[error("SIMD error: {0}")]
SimdError(String),
#[error("Streaming error: {0}")]
StreamingError(String),
#[error("Cross-validation error: {0}")]
CrossValidationError(String),
#[cfg(feature = "monitoring")]
#[error("Prometheus error: {0}")]
PrometheusError(#[from] prometheus::Error),
#[cfg(feature = "distributed")]
#[error("Serialization error: {0}")]
SerializationError(#[from] oxicode::Error),
#[error("Not implemented: {0}")]
NotImplemented(String),
#[error("Parse error: {0}")]
ParseError(String),
#[error("Error: {0}")]
Other(String),
}
pub type Result<T> = std::result::Result<T, TransformError>;
pub trait ErrorContext<T> {
fn context(self, msg: &str) -> Result<T>;
fn with_context<F>(self, f: F) -> Result<T>
where
F: FnOnce() -> String;
}
impl<T> ErrorContext<T> for Result<T> {
fn context(self, msg: &str) -> Result<T> {
self.map_err(|e| TransformError::Other(format!("{msg}: {e}")))
}
fn with_context<F>(self, f: F) -> Result<T>
where
F: FnOnce() -> String,
{
self.map_err(|e| TransformError::Other(format!("{}: {e}", f())))
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ErrorKind {
Validation,
Computation,
Configuration,
Resource,
External,
Internal,
}
impl TransformError {
pub fn kind(&self) -> ErrorKind {
match self {
TransformError::InvalidInput(_)
| TransformError::DataValidationError(_)
| TransformError::ConfigurationError(_) => ErrorKind::Validation,
TransformError::ComputationError(_)
| TransformError::TransformationError(_)
| TransformError::ConvergenceError(_)
| TransformError::SimdError(_) => ErrorKind::Computation,
TransformError::MemoryError(_)
| TransformError::GpuError(_)
| TransformError::TimeoutError(_) => ErrorKind::Resource,
TransformError::IoError(_)
| TransformError::DistributedError(_)
| TransformError::StreamingError(_)
| TransformError::MonitoringError(_) => ErrorKind::External,
TransformError::NotImplemented(_)
| TransformError::NotFitted(_)
| TransformError::FeatureNotEnabled(_)
| TransformError::Other(_) => ErrorKind::Internal,
TransformError::CoreError(_)
| TransformError::LinalgError(_)
| TransformError::FFTError(_) => ErrorKind::External,
TransformError::ParallelError(_)
| TransformError::CrossValidationError(_)
| TransformError::ParseError(_) => ErrorKind::Computation,
#[cfg(feature = "monitoring")]
TransformError::PrometheusError(_) => ErrorKind::External,
#[cfg(feature = "distributed")]
TransformError::SerializationError(_) => ErrorKind::External,
}
}
pub fn is_recoverable(&self) -> bool {
match self.kind() {
ErrorKind::Validation | ErrorKind::Configuration => false,
ErrorKind::Resource | ErrorKind::External => true,
ErrorKind::Computation => true, ErrorKind::Internal => false,
}
}
pub fn should_retry(&self) -> bool {
matches!(
self,
TransformError::TimeoutError(_)
| TransformError::MemoryError(_)
| TransformError::DistributedError(_)
| TransformError::StreamingError(_)
| TransformError::ParallelError(_)
| TransformError::IoError(_)
)
}
pub fn user_message(&self) -> String {
match self {
TransformError::InvalidInput(_) => "Invalid input data provided".to_string(),
TransformError::NotFitted(_) => "Model must be fitted before use".to_string(),
TransformError::MemoryError(_) => "Insufficient memory for operation".to_string(),
TransformError::TimeoutError(_) => "Operation timed out".to_string(),
TransformError::FeatureNotEnabled(_) => "Required feature is not enabled".to_string(),
_ => "An error occurred during transformation".to_string(),
}
}
}