use thiserror::Error;
pub type Result<T> = std::result::Result<T, AnalyticsError>;
#[derive(Debug, Error)]
pub enum AnalyticsError {
#[error("Invalid input: {0}")]
InvalidInput(String),
#[error("Insufficient data: {0}")]
InsufficientData(String),
#[error("Convergence failed: {0}")]
ConvergenceError(String),
#[error("Numerical instability: {0}")]
NumericalInstability(String),
#[error("Matrix operation failed: {0}")]
MatrixError(String),
#[error("Dimension mismatch: expected {expected}, got {actual}")]
DimensionMismatch { expected: String, actual: String },
#[error("Invalid parameter '{param}': {reason}")]
InvalidParameter { param: String, reason: String },
#[error("Statistical test failed: {0}")]
StatisticalTestError(String),
#[error("Clustering failed: {0}")]
ClusteringError(String),
#[error("Interpolation failed: {0}")]
InterpolationError(String),
#[error("Time series analysis failed: {0}")]
TimeSeriesError(String),
#[error("Hotspot analysis failed: {0}")]
HotspotError(String),
#[error("Change detection failed: {0}")]
ChangeDetectionError(String),
#[error("Zonal statistics failed: {0}")]
ZonalStatsError(String),
#[error("Core error: {0}")]
CoreError(#[from] oxigdal_core::error::OxiGdalError),
#[error("SciRS2 error: {0}")]
SciRS2Error(String),
#[error("I/O error: {0}")]
IoError(#[from] std::io::Error),
}
impl AnalyticsError {
pub fn invalid_input(msg: impl Into<String>) -> Self {
Self::InvalidInput(msg.into())
}
pub fn insufficient_data(msg: impl Into<String>) -> Self {
Self::InsufficientData(msg.into())
}
pub fn convergence_error(msg: impl Into<String>) -> Self {
Self::ConvergenceError(msg.into())
}
pub fn numerical_instability(msg: impl Into<String>) -> Self {
Self::NumericalInstability(msg.into())
}
pub fn matrix_error(msg: impl Into<String>) -> Self {
Self::MatrixError(msg.into())
}
pub fn dimension_mismatch(expected: impl Into<String>, actual: impl Into<String>) -> Self {
Self::DimensionMismatch {
expected: expected.into(),
actual: actual.into(),
}
}
pub fn invalid_parameter(param: impl Into<String>, reason: impl Into<String>) -> Self {
Self::InvalidParameter {
param: param.into(),
reason: reason.into(),
}
}
pub fn statistical_test_error(msg: impl Into<String>) -> Self {
Self::StatisticalTestError(msg.into())
}
pub fn clustering_error(msg: impl Into<String>) -> Self {
Self::ClusteringError(msg.into())
}
pub fn interpolation_error(msg: impl Into<String>) -> Self {
Self::InterpolationError(msg.into())
}
pub fn time_series_error(msg: impl Into<String>) -> Self {
Self::TimeSeriesError(msg.into())
}
pub fn hotspot_error(msg: impl Into<String>) -> Self {
Self::HotspotError(msg.into())
}
pub fn change_detection_error(msg: impl Into<String>) -> Self {
Self::ChangeDetectionError(msg.into())
}
pub fn zonal_stats_error(msg: impl Into<String>) -> Self {
Self::ZonalStatsError(msg.into())
}
pub fn scirs2_error(msg: impl Into<String>) -> Self {
Self::SciRS2Error(msg.into())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_creation() {
let err = AnalyticsError::invalid_input("test");
assert!(matches!(err, AnalyticsError::InvalidInput(_)));
let err = AnalyticsError::dimension_mismatch("3x3", "4x4");
assert!(matches!(err, AnalyticsError::DimensionMismatch { .. }));
}
#[test]
fn test_error_display() {
let err = AnalyticsError::invalid_input("invalid parameter value");
assert_eq!(format!("{}", err), "Invalid input: invalid parameter value");
let err = AnalyticsError::dimension_mismatch("3x3", "4x4");
assert_eq!(
format!("{}", err),
"Dimension mismatch: expected 3x3, got 4x4"
);
}
}